javascriptwebpackbundleservice-workerworkbox-webpack-plugin

self.__WB_MANIFEST is not replaced by InjectManifest generated urls for precaching using service worker


This is my webpack config

    new InjectManifest({
      swSrc: './app/service-worker.js',
      swDest: 'sw.js',
      maximumFileSizeToCacheInBytes: 5000000,
    }),

This is my servie-worker.js

import { skipWaiting, clientsClaim } from 'workbox-core';
import { cleanupOutdatedCaches, precacheAndRoute } from 'workbox-precaching';

skipWaiting();
clientsClaim();
cleanupOutdatedCaches();
precacheAndRoute(self.__WB_MANIFEST || []);

This is how i register serviceworker

import { Workbox } from 'workbox-window';

const register = () => {
  // service worker should be installed only in prod env.
  if (process.env.NODE_ENV !== 'production') {
    return;
  }
  // check if browser supports SW before register.
  if ('serviceWorker' in navigator) {
    const wb = new Workbox('/company/sw.js');

    wb.register().then((registration) => {
      console.log('Registration success', registration.scope);
    }).catch((err) => {
      console.log('Registration failed', err);
    });
  }
};

register();

This is the sw.js code generated by webpack bundler using InjectManifest where it injects the route by replacing self.__WB_MANIFEST

    f81121bb716d06db5a3c: function (e, t, r) {
        "use strict";
        var n = r("ee2c850f71b22ec627d9"),
            a = r("71160463eb5f8808d43e");
        (0, n.skipWaiting)(), (0, n.clientsClaim)(), (0, a.cleanupOutdatedCaches)(), (0, a.precacheAndRoute)([{
            'revision': 'd6d49a7c4da3232a63313d0296cb697c',
            'url': '/company/index.html'
        },  {
            'revision': null,
            'url': '/company/static/js/main.eecf38c8e0bdeb9edfd0.chunk.js'
        }, {
            'revision': 'd77aa54cfc47caccf631a032dccdd1a4',
            'url': '/company/static/js/main.eecf38c8e0bdeb9edfd0.chunk.js.br'
        }, {
            'revision': 'f583ac2ae2e839d40f7390f44de0d09e',
            'url': '/company/static/js/main.eecf38c8e0bdeb9edfd0.chunk.js.gz'
        }, {
            'revision': null,
            'url': '/company/static/js/node_vendors.dfc2f2b312f9103e4f57.chunk.js'
        }, {
            'revision': 'cc71224b8f04e2722f7fd8e934625d99',
            'url': '/company/static/js/node_vendors.dfc2f2b312f9103e4f57.chunk.js.br'
        }, {
            'revision': 'a66582b83e005784db6aa640e3075f67',
            'url': '/company/static/js/node_vendors.dfc2f2b312f9103e4f57.chunk.js.gz'
        }, {
            'revision': null,
            'url': '/company/static/js/runtime~main.67d1bc90b93c84b2daf6.js'
        }, {
            'revision': 'e0a95983d322b621a7fd3b16888aaa8b',
            'url': '/company/sw.js.br'
        }, {
            'revision': 'e1ab2a71f411919e92a90675915af0ef',
            'url': '/company/sw.js.gz'
        }] || [])
    },

Below is the screenshot of sw.js code from devtools when served from localhost enter image description here

As we could clearly see in the sw.js file served in localhost, the self.__WB_MANIFEST is not replaced by the urls generated by InjectManifest. Here my question is how come the sw.js file is having different code from what its generated by bundler. I tried unregister service worker and tried empty cache as well still there is difference in sw.js from what i have in build vs what served. Please suggest some ideas here. Below is the version im using

    "workbox-core": "^6.4.2",
    "workbox-precaching": "^6.4.2",
    "workbox-window": "^6.4.2",
    "workbox-webpack-plugin": "^6.4.2"

Solution

  • After a days effort I figured out where I went wrong. Previously my webpack config was like this

        new CompressionPlugin({
          filename: '[path].gz[query]',
          algorithm: 'gzip',
          test: /\.js$|\.css$|\.html$/,
          threshold: 10240,
          minRatio: 0.7,
        }),
    
        new BrotliPlugin({
          asset: '[path].br[query]',
          test: /\.js$|\.css$|\.html$/,
          threshold: 10240,
          minRatio: 0.7,
        }),
            new InjectManifest({
          // exclude: [/\.map$/, /asset-manifest\.json$/],
          // importWorkboxFrom: 'cdn',
          swSrc: './app/service-worker.js',
          swDest: 'sw.js',
          maximumFileSizeToCacheInBytes: 5000000,
        }),
    
    

    Now I moved InjectManifest plugin before the compressions plugin which eventually solved the problem

        new InjectManifest({
          // exclude: [/\.map$/, /asset-manifest\.json$/],
          // importWorkboxFrom: 'cdn',
          swSrc: './app/service-worker.js',
          swDest: 'sw.js',
          maximumFileSizeToCacheInBytes: 5000000,
        }),
    
        new CompressionPlugin({
          filename: '[path].gz[query]',
          algorithm: 'gzip',
          test: /\.js$|\.css$|\.html$/,
          threshold: 10240,
          minRatio: 0.7,
        }),
    
        new BrotliPlugin({
          asset: '[path].br[query]',
          test: /\.js$|\.css$|\.html$/,
          threshold: 10240,
          minRatio: 0.7,
        }),
    

    Anyone has idea on how webpack handle this when making a bundle