webpack.js.org icon indicating copy to clipboard operation
webpack.js.org copied to clipboard

Provide underlying reason for a ChunkLoadError

Open neemah opened this issue 5 years ago • 12 comments

Feature request

What is the expected behavior?

When a ChunkLoadError is thrown, you are able to catch it and determine the exact reason for it.

What is motivation or use case for adding/changing the behavior?

Knowing the underlying reason for that error, you will be able to make and appropriate action. For example, if the reason is 404 HTTP ERROR, that in our case mean, that application version is updated and current page needed to be refreshed in order to reload core chunks and obtain new urls for others.

How should this be implemented in your opinion?

I am not sure on that one, but any object that is provided along with error itself, containing reason would be sufficient.

Are you willing to work on this yourself?

Yes, yet I'd need some advice on where to start from

neemah avatar Mar 03 '20 16:03 neemah

You find the type in a type property on the error object. There is also request to the url.

sokra avatar Mar 03 '20 20:03 sokra

@sokra thanks for your response, we've just examined type and request properties:

chunk-error-details

I'd say they don't help much to determine the underlying reason. In that particular case, it was 404, but we couldn't get that information.

Is there a chance to get that info somehow?

Any suggestions much appreciated.

neemah avatar Mar 05 '20 09:03 neemah

The 404 error is mean the 404 error :smile: The simplest scenario - you delete files before build/deploy and use [hash]/[contenthash]/other hashes, but one of your visitors already had an open page, so files became unavailable on server

alexander-akait avatar Mar 05 '20 10:03 alexander-akait

@evilebottnawi how is this relevant to a described scenario? :)

neemah avatar Mar 05 '20 10:03 neemah

@neemah yep, my mistake :smile: wrote the wrong place

alexander-akait avatar Mar 05 '20 10:03 alexander-akait

So, after research, I've found that chunks being loaded via script tag and that does not give any chance to get http error.

So the only strategy here is to make HEAD request with provided url and then decide what to do.

Thanks, I guess that is common scenario, might be worth to note somewhere.

neemah avatar Mar 05 '20 11:03 neemah

So, after research, I've found that chunks being loaded via script tag and that does not give any chance to get http error.

yep, we already pass along all information we have.

sokra avatar Mar 06 '20 11:03 sokra

Thanks, I guess that is common scenario, might be worth to note somewhere.

Send a PR to the documentation

sokra avatar Mar 06 '20 11:03 sokra

This issue had no activity for at least three months.

It's subject to automatic issue closing if there is no activity in the next 15 days.

webpack-bot avatar Jun 06 '20 07:06 webpack-bot

We has the same problems. To get rid of it, we check the error to be sure it's a chunk failed error, then we search in the cache to know if the cache doesn't have the file or if the chunk is invalid ( To avoid reload on syntax error )

As we know now our chunk is not in the cache, we trigger an update of our service worker and reload the page.

We use Offline Plugin to manage our service worker. See code below :

errorBoundary.js :

  static getDerivedStateFromError(error) {
    const chunkFailedMessage = /Loading chunk [\d]+ failed/;
    if (
      error.name === 'ChunkLoadError' &&
      chunkFailedMessage.test(error.message)
    ) {
      return { hasChunkError: true };
    }
    return { hasCriticalError: true };
  }

  componentDidCatch(error, errorInfo) {
    if (this.state.hasChunkError) {
      // This is a chunk error, check if this error is normal or critical
      if (caches) {
        // Browser support caches, we can check chunk existence
        caches.match(error.request).then(r => {
          if (r === undefined) {
            // chunk is not in cache => application enctounter 404
            const isOnline = require('is-online'); // eslint-disable-line global-require
            isOnline().then(connected => {
              if (connected) {
                // user is online so missing chunk come from new version
                // we should update the service worker to update app
                window.swForceUpdate = true;
                OfflinePluginRuntime.update();
              } else {
                // user is disconnected, missing chunk come from offline
                this.setState({ isOffline: true });
              }
            });
          } else {
            // if chunk is found, then chunk may be corrupted
            this.setState({ hasCriticalError: true });
          }
        });
      } else {
        // if caches is not defined (not supported browser), then error is critical but we do not need to log to sentry
        this.setState({ hasCriticalError: true });
      }
    }
   ...
}

App.js :

    OfflinePluginRuntime.install({
      ...
      onUpdated: () => {
        // eslint-disable-next-line no-console
        console.log('SW Event:', 'onUpdated');
        if (window.swForceUpdate) {
          // if swForceUpdate, it means that a chunk is missing, reload the page immediately
          window.location.reload();
        }
        // Render a pop up to advise user to reload
      },
      ....
    });

LeComptoirDesPharmacies avatar Jun 25 '20 09:06 LeComptoirDesPharmacies

Issue was closed because of inactivity.

If you think this is still a valid issue, please file a new issue with additional information.

webpack-bot avatar Oct 10 '20 04:10 webpack-bot

@chenxsan need to docs only this https://github.com/webpack/webpack.js.org/issues/4479#issuecomment-595180374

alexander-akait avatar Jan 25 '21 10:01 alexander-akait