Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Router code split "randomly" fails at loading chunks

I am struggling with a issue with react-router + webpack code split + servicer worker (or cache).

Basically the issue is the following, the code split is working properly but from time to time I get error reports from customers at sentry.io such as:

"Dynamic page loading failed Error: Loading chunk 19 failed."

My react-router code is the following:

const errorLoading = (err) => {
    console.error('Dynamic page loading failed', err);
};

export default (
    <Route path="/" component={App}>
        <IndexRoute
            getComponent={(nextState, cb) => {
                System.import('./containers/home/home')
                    .then((module) => { cb(null, module.default); })
                    .catch(errorLoading);
            }}
        />
    </Route>
);

For my ServiceWorker I use OfflinePlugin with the following configuration:

new OfflinePlugin({
    cacheName: 'cache-name',
    cacheMaps: [
        {
            match: function(requestUrl) {
                return new URL('/', location);
            },
            requestTypes: ['navigate']
        }
    ],
    externals: [
        'assets/images/logos/slider.png',
        'assets/images/banners/banner-1-320.jpg',
        'assets/images/banners/banner-1-480.jpg',
        'assets/images/banners/banner-1-768.jpg',
        'assets/images/banners/banner-1-1024.jpg',
        'assets/images/banners/banner-1-1280.jpg',
        'assets/images/banners/banner-1-1400.jpg'
    ],
    responseStrategy: 'network-first', // One of my failed attempts to fix this issue
    ServiceWorker: {
        output: 'my-service-worker.js'
    }
})

The issue is not browser related because I have reports from IE11, safari, chrome, etc.

Any clues on what I might be doing wrong or how can I fix this issue?

like image 884
Canastro Avatar asked Mar 26 '17 20:03

Canastro


1 Answers

Edit 2: I ended using chunks with hashes, and doing a window.location.reload() inside errorLoading's catch(), so when the browser fails to load a chunk it will reload the window and fetch the new file.

<Route path="about" 
  getComponent={(location, callback) => {
    System.import('./about')
    .then(module => { callback(null, module.default) })
    .catch(() => {
      window.location.reload()
    })
  }} 
/>

It happens to me too and I don't think I have a proper solution yet, but what I noticed is this usually happens when I deploy a new version of the app, the hashes of the chunks change, and when I try to navigate to another address (chunk) the old chunk doesn't exist (it seems as if it wasn't cached) and I get the error.

I managed to reproduce this by removing the service worker that caches stuff and deploying a new version (which I guess simulates a user without the service worker running?).

  1. remove the service worker code
  2. unregister the service worker in devtools
  3. reload the page
  4. deploy a new app version
  5. navigate to another chunk (for instance from /home to /about)

In my case it appears as if the error occurs when the old files are not cached (hence not available any more) and the user doesn't reload the page to request new ones. Reloading 'fixes' the issue because the app has the new chunk names, which correctly load.

Something else I tried was to name the chunk files without their hashes, so instead of 3.something.js they were only 3.js. When I deployed a new version the chunks were obviously still there, but this is not a good solution because the files will be cached by the browser instead of being cached by the caching plugin.

Edit: same setup as you, using sw-precache-webpack-plugin.

like image 144
rudikovac Avatar answered Nov 19 '22 03:11

rudikovac