how to use service-worker in dev mode

Viewed 1872

I am using create-react-app 4 and the cra-template-pwa (source)

By default, it looks like the service-worker is only used in production builds:

export function register(config) {
    if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {

https://github.com/cra-template/pwa/blob/25cb9f06938c671507684a8438c347d3c8bc8b24/packages/cra-template-pwa/template/src/serviceWorkerRegistration.js#L22

That's a problem for me since building the production build takes a long time, hence I would like to register the service-worker while dev builds too. In order to get that result I removed the check process.env.NODE_ENV === 'production' and also another isLocalhost check.

Now, even the debug build is trying to load the www.example.com/service-worker.js, just as I hoped.


The problem now is, this file is inside src. Which makes sense since it is using imports as you can see here. But because of this, the file itself is not accessible from the webbrowser and therefore www.example.com/service-worker.js is for sure unreachable.

Copying the file into public does not work either

Uncaught SyntaxError: Cannot use import statement outside a module

I fear I haven't really understood which part belongs to JS, which one to NodeJS, which one to reactjs and which one to CRA.

So my question now is:

Is there a way to get the "path" of the "translated" service-worker.js (after imports,..)?

2 Answers

First add craco to the react project craco

then create custome craco plugin using below files

serviceWorkerRegistration.js

change this line ===>  if ("process.env.NODE_ENV === 'production' && serviceWorker" in navigator)

to ===>  if ("serviceWorker" in navigator)



craco.config.js

const cracoServiceWorkerConfig = require("./cracoServiceWorkerConfig");

module.exports = {
    plugins: [{ plugin: cracoServiceWorkerConfig }],
};

cracoServiceWorkerConfig.js

const WorkboxWebpackPlugin = require("workbox-webpack-plugin");
const path = require("path");

module.exports = {
    overrideWebpackConfig: ({ webpackConfig, cracoConfig, pluginOptions, context: { env, paths } }) => {
        const isEnvDevelopment = env === "development";
        if (isEnvDevelopment) {
            const newConfig = {
                ...webpackConfig,
                plugins: [
                    ...webpackConfig.plugins,
                    isEnvDevelopment &&
                        new WorkboxWebpackPlugin.InjectManifest({
                            swSrc: path.resolve(__dirname, "src/service-worker.js"),
                            dontCacheBustURLsMatching: /\.[0-9a-f]{8}\./,
                            exclude: [/\.map$/, /asset-manifest\.json$/, /LICENSE/],
                            maximumFileSizeToCacheInBytes: 5 * 1024 * 1024,
                        }),
                ],
            };
            return newConfig;
        } else {
            return webpackConfig;
        }
        // Always return the config object.
    },
};


You simply cant. The CRA-service worker is an abstraction of the Javascript browser feature that is service-worker. It makes it possible to easily write this service worker, but it will only compile on the build. You can always write your own service worker in JS and test it in dev. But you dont want to.

Related