Serverless-next.js: NextJS with PWA setup

Created on 4 Nov 2019  路  4Comments  路  Source: serverless-nextjs/serverless-next.js

Is your feature request related to a problem? Please describe.
When setting up nextjs app to work offline as Progressive Web App using the method mentioned in https://github.com/ooade/NextSimpleStarter, it needs a redirect/re-route to be configured in the host to find service-worker.js

Examples are given for Now and Netlify below:
https://github.com/ooade/NextSimpleStarter/blob/master/netlify.toml
https://github.com/ooade/NextSimpleStarter/blob/master/now.json

It seems like if we use serverless component to deploy the nextjs app, we need to add a separate lambda @ edge to handle this redirect.

Otherwise the app will throw the error 404 trying to find service-worker.js file in root folder instead of /static/ folder.

Describe the solution you'd like
It will be awesome if the component creates the configurations needed to re-route requests to proper server worker.

Describe alternatives you've considered
Manually create the re-route configurations after deploying the app via serverless to cloudfront.

Additional context
image

next component

Most helpful comment

I don't believe this is a serverless issue. I believe you need to use the api routing feature of next which is supported with serverless-next.js. Something like this:

/pages/api/service-worker.js.js (default behavior is to serve file without the .js extension)

const fs = require("fs");
export default (req, res) => {
    // It is best practice to set no-cache until you are 100% certain you will never need to change sw
    res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
    res.setHeader("Content-Type", "application/javascript");
    res.setHeader("Service-Worker-Allowed", "/");
    res.statusCode = 200;
    // Quick hack to the manifest being relative - I am sure there is a better way to do this 
    res.send(Buffer.from(fs.readFileSync("./.next/static/service-worker.js", "utf8").toString()
        .replace(new RegExp("\"url\": \"_next", "g"), `"url": "/_next`)
    ));
}
const nextConfig = {
  target: "serverless",
  transformManifest: manifest => ['/'].concat(manifest), // add the homepage to the cache
  // Trying to set NODE_ENV=production when running yarn dev causes a build-time error so we
  // turn on the SW in dev mode so that we can actually test it
  generateInDevMode: true, 
  registerSwPrefix: "api",
  scope: "/",
  workboxOpts: {
    swDest: 'static/service-worker.js',
  ... 

All 4 comments

I don't believe this is a serverless issue. I believe you need to use the api routing feature of next which is supported with serverless-next.js. Something like this:

/pages/api/service-worker.js.js (default behavior is to serve file without the .js extension)

const fs = require("fs");
export default (req, res) => {
    // It is best practice to set no-cache until you are 100% certain you will never need to change sw
    res.setHeader("Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate");
    res.setHeader("Content-Type", "application/javascript");
    res.setHeader("Service-Worker-Allowed", "/");
    res.statusCode = 200;
    // Quick hack to the manifest being relative - I am sure there is a better way to do this 
    res.send(Buffer.from(fs.readFileSync("./.next/static/service-worker.js", "utf8").toString()
        .replace(new RegExp("\"url\": \"_next", "g"), `"url": "/_next`)
    ));
}
const nextConfig = {
  target: "serverless",
  transformManifest: manifest => ['/'].concat(manifest), // add the homepage to the cache
  // Trying to set NODE_ENV=production when running yarn dev causes a build-time error so we
  // turn on the SW in dev mode so that we can actually test it
  generateInDevMode: true, 
  registerSwPrefix: "api",
  scope: "/",
  workboxOpts: {
    swDest: 'static/service-worker.js',
  ... 

@vishwasnavadak Aside from @Enalmada 's suggestion you could put the service-worker.js in the public/ folder? That will make the worker reachable at the root url /service-worker.js

In terms of custom routes in the next component I considered doing this before but now it seems this is coming natively in next https://github.com/zeit/next.js/issues/9081 馃帀 so no need 馃槃

Apologies for digging up an old/closed thread, but with the new routing available in next, does you answer to this question change, @danielcondemarin?

Currently having this issue too, and wondering the best route to fix. Would your idea of putting the worker in public be achieved by this: workboxOpts: {swDest: 'public/service-worker.js' } or by moving the file after being generated? My worker is being generated correctly (in static) but the api method above hits a file not found.

@bradders were you able to solve this issue?
Can you help me out? Facing the same issue 馃槙.

Was this page helpful?
0 / 5 - 0 ratings