angularservice-workerworkbox

Workbox pre-caches angular's lazy loaded bundles


I have an angular application and use Workbox Service Worker(SW) for gaining PWA compatibility. My angular app has several lazy loaded bundles, which I except to load only when required. Everything works fine in development mode, as my SW is enabled only in production.

The problem is that, whenever I load my application the bundles which are supposed to load lazily also loads up. That's not preferred.

The workbox pre-caching config caches all js files.I think this is the one causing problem. Here's the config, workbox-config.js

module.exports = {
  globDirectory: 'dist/myapp/',
  globPatterns: ['**/*.{css,scss,eot,html,ico,jpg,jpeg,js,json,png,svg,ttf,txt,webmanifest,woff,woff2,webm,xml}'],
  globFollow: true,
  globStrict: true,
  globIgnores: [
    `**/*-es5.*.js`,
    '**/assets/tinymce/**',
    '**/assets/icons/icon-*.png'
  ],
  dontCacheBustURLsMatching: new RegExp('.+.[a-f0-9]{20}..+'),
  maximumFileSizeToCacheInBytes: 4 * 1024 * 1024,
  swSrc: 'dist/myapp/service-worker.js',
  swDest: 'dist/myapp/service-worker.js' 
};

Then I inject it to my SW after production build using this

workbox injectManifest ./src/sw/workbox-config.js

To give you a better idea here is the network snapshot on first load.

enter image description here

The bundles {6,7,8,9}-es2015.*.js are expected to be lazily loaded. But I think due to my Workbox config, it loads on start-up itself. I don't want this happening as the total download size on initial load overshoots to an unacceptable amount.

So, the solution that I came up with was to use runtime caching instead, by doing like this in SW file.

const appChunksMatcher = ({ url, request, event }) => {
  const href: string = url.href;
  const start = href.lastIndexOf('.') + 1;
  const end = href.length - 1;
  const isJSFile =  href.substring(start, end) === 'js';
  return ~href.indexOf('-es2015.') || isJSFile;
};
registerRoute(
  appChunksMatcher,
  new CacheFirst({
    cacheName: 'app-chunks'
  })
);

But, I am not sure this is the right way. I tried adding a regular expression check in my workbox config globIgnores array, to exclude hashed chunks except main-es2015 chunk.

globIgnores: [
  ...
  ...
  // This is to exclude precaching of lazy loaded angular chunks
  // They are of format 5-es2015.sbcd123e34fd.js
  '**/*-es2015.*.js'
  `[0-9]+\-es2015.*.js$`
]

But that didn't work too. That's why I went to the run time caching option. Can anyone tell me what I am doing wrong or provide me with a better solution. Certainly, I don't want to laod my lazy-loaded modules on startup.


Solution

  • +([0-9])-es2015.*.js
    

    Using this glob pattern worked for me. Final result is given below.

    globIgnores: [
      ...
      ...
      // This is to exclude precaching of lazy loaded angular chunks
      // They are of format 5-es2015.sbcd123e34fd.js
      '+([0-9])-es2015.*.js'
    ]