Create-react-app: Custom ServiceWorker config

Created on 19 May 2017  路  16Comments  路  Source: facebook/create-react-app

1.0.0 added Progressive Web App support, is it possible to support custom config in near future? I really don't want to eject just to add runtime caching configs 馃槃

proposal question > PWA

Most helpful comment

@Timer I just updated to the newest version, and tried to use the new PWA support as well, and there seems to be an issue with Firebase auth. Firebase auth uses the /__/auth/handler path, which seems to be 'cached' by the default config (returning the app itself). So for now I had to abandon the idea. Here's what I believe to be a related issue, for the polymer project: https://github.com/Polymer/polymer-build/issues/35#issuecomment-245981301

All 16 comments

What specifically would you like to be able to change?

Currently I use sw-precache with a config file and run sw-precache --config=sw-precache-config.js after the build script.

I would expect to be able to define a sw-precache-config.js (or anything) to define my own configs.

@gnhuy91 so we are most likely not going to let you define your own config, but if you let us know what you are trying to achieve, we can consider adding support for specific options.

Thanks, this is my current config:

module.exports = {
  swFilePath: 'build/service-worker.js',
  stripPrefix: 'build/',
  staticFileGlobs: [
    'build/*.html',
    'build/manifest.json',
    'build/static/**/!(*map*)',
  ],
  dontCacheBustUrlsMatching: /\.\w{8}\./,
  navigateFallback: 'index.html',
  runtimeCaching: [{
    urlPattern: /https?:\/\/fonts.+/,
    handler: 'fastest',
  }, {
    urlPattern: /https?:\/\/images.+/,
    handler: 'fastest',
  }],
};

Currently I only need to define some runtimeCaching for my app, further configs may arise but I think most people will mostly find runtimeCaching useful and want to make use of it.

@Timer I just updated to the newest version, and tried to use the new PWA support as well, and there seems to be an issue with Firebase auth. Firebase auth uses the /__/auth/handler path, which seems to be 'cached' by the default config (returning the app itself). So for now I had to abandon the idea. Here's what I believe to be a related issue, for the polymer project: https://github.com/Polymer/polymer-build/issues/35#issuecomment-245981301

cc @jeffposnick on suggestions for how a tool striving to have minimal configuration could handle this.

There are definitely use cases where folks might want something other than the default configuration. I tried to choose default configuration options that are, in general safe, with the understanding that developers who need to make changes will go through the eject flow and modify the configuration (which seemed to in keeping with the overall approach for this project).

I don't know how common it is for servers to use the /__ prefix for "special" URLs that are server-rendered and shouldn't be fulfilled via the locally cached content, but adding in the configuration option

{
  navigateFallbackWhitelist: [/^(?!\/__)/]
}

would account for them. Doing so would be unlikely to break anyone, and it would accommodate some of the folks upthread without forcing them to eject.

As for the questions about configuring runtimeCaching, I tried to cover that in item 7 of this guide. There's no single configuration option that's likely to work for everyone, so using the eject flow would be the way forward.

I was really tempted to come here to support being able to configure runtimeCaching, but I think @jeffposnick is right. I think eject is the way to do for this.

I'm going to have to agree with Jeff that for now ejecting is probably the best call for customizing runtimeCaching. There are a few too many permutations for how we've seen folks use the option to provide a flexible alternative that would be as useful.

I鈥檒l close this for now, as we鈥檙e not going to do it soon, but we might consider this at some point in the future. For now you鈥檇 either need to eject, or add your own custom build step react-scripts build. Thanks for feedback!

Just for reference, here's how I've implemented the extra build step for the app to work with firebase auth:

const fs = require('fs')
fs.readFile('build/service-worker.js', 'utf8', (error, data) => {
  if (error) {
    return console.log(error)
  }
  const result = data.replace(/isPathWhitelisted\(\[\]/g, 'isPathWhitelisted([/^(?!\\/__)/]')
  fs.writeFile('build/service-worker.js', result, 'utf8', (error) => {
    if (error) {
      return console.log(error)
    }
  })
})

EDIT: This is not needed now, see below.

I've discovered that the issue that @dsgh mentioned is present in other projects such as https://github.com/Polymer/polymer-cli/issues/290, and the default navigateFallback configuration in Webpack config clobbers any Firebase project that uses auth or any other feature that makes use of Firebase's reserved namespace (/__*) (according to https://firebase.google.com/docs/hosting/reserved-urls, there are a few uses of the reserved namespace). So far, the only solution for that case is @jeffposnick's navigateFallbackWhitelist config, so as long as navigateFallback is set by default in Webpack config, then I think the whitelist should also be set by default.

Does this work right now?

I see this in my webpack.config.prod

    new SWPrecacheWebpackPlugin({
      // By default, a cache-busting query parameter is appended to requests
      // used to populate the caches, to ensure the responses are fresh.
      // If a URL is already hashed by Webpack, then there is no concern
      // about it being stale, and the cache-busting can be skipped.
      dontCacheBustUrlsMatching: /\.\w{8}\./,
      filename: 'service-worker.js',
      logger(message) {
        if (message.indexOf('Total precache size is') === 0) {
          // This message occurs for every build and is a bit too noisy.
          return;
        }
        if (message.indexOf('Skipping static resource') === 0) {
          // This message obscures real errors so we ignore it.
          // https://github.com/facebookincubator/create-react-app/issues/2612
          return;
        }
        console.log(message);
      },
      minify: true,
      // For unknown URLs, fallback to the index page
      navigateFallback: publicUrl + '/index.html',
      // Ignores URLs starting from /__ (useful for Firebase):
      // https://github.com/facebookincubator/create-react-app/issues/2237#issuecomment-302693219
      navigateFallbackWhitelist: [/^(?!\/__).*/],
      // Don't precache sourcemaps (they're large) and build asset manifest:
      staticFileGlobsIgnorePatterns: [/\.map$/, /asset-manifest\.json$/],
    }),

(This is a completely new app).

I serve this with a node server like so

const express = require("express");
const app = express();
app.get("*.js", function(req, res, next) {
  res.set("Content-Type", "application/javascript");
  next();
});

app.get("*.css", function(req, res, next) {
  res.set("Content-Type", "text/css");
  next();
});

app.use(express.static("build"));

app.get("/*", (req, res) => {
  res.sendFile(__dirname + "/build/index.html");
});
app.listen(3000, () => console.log("Server running on port 3000"));

But when I hit localhost:3000/__auth I get this message in my console

This web app is being served cache-first by a service worker. To learn more, visit https://goo.gl/SC7cgQ

I want to use this to bypass the service worker on another route, but I expected the above to work out of the box.

Any plans on allowing this soon? I've completely disabled the auto generated service worker as it caches some URLs it really shouldn't and I can't exclude them, without ejecting.

This can be done with react-app-rewired. In config-overrides.js you can do something like:

module.exports = function override(config, env) {
  const swPrecacheConfig = config.plugins.find(
    plugin => plugin.constructor.name === "SWPrecacheWebpackPlugin"
  );
  // Prevent some URLs from being cached by the service worker
  swPrecacheConfig.options.navigateFallbackWhitelist = [
    /^(?!\/(__|privacy-policy|terms-of-service)).*/
  ];
  return config;
};
Was this page helpful?
0 / 5 - 0 ratings

Related issues

godmar picture godmar  路  130Comments

gaearon picture gaearon  路  152Comments

sgriffey picture sgriffey  路  113Comments

xiaoxiangmoe picture xiaoxiangmoe  路  89Comments

rovansteen picture rovansteen  路  192Comments