mattlewis92 / webpack-retry-chunk-load-plugin

A webpack plugin to retry loading of chunks that failed to load
MIT License
235 stars 43 forks source link

Reload of CSS-Chunks #2

Open jens-duttke opened 4 years ago

jens-duttke commented 4 years ago

Would it be possible to extend this plugin to also reload non-JS-chunks? e.g. sometimes in my webapp, users get errors for CSS-Chunks:

PromiseRejectionEvent {
    isTrusted: true
    promise: Promise {
    }
    reason: Error {
        stack: "Error: Loading CSS chunk 5 failed.\n(/css/editor+scrollbar.433bb1fc9b0973e8a945.css)\n    at HTMLLinkElement.o.<computed>.o.<computed>.<computed>.r.push.o.<computed>.u.onerror (/js/runtime.a454100c5fd99edd31e7.min.js:78:38)"
        message: "Loading CSS chunk 5 failed.\n(/css/editor+scrollbar.433bb1fc9b0973e8a945.css)"
        code: "CSS_CHUNK_LOAD_FAILED"
        request: "/css/editor+scrollbar.433bb1fc9b0973e8a945.css"
    }
    NONE: 0
    CAPTURING_PHASE: 1
    AT_TARGET: 2
    BUBBLING_PHASE: 3
    type: "unhandledrejection"
    target: [object Window]
    currentTarget: [object Window]
    eventPhase: 2
    bubbles: false
    cancelable: true
    defaultPrevented: true
    composed: false
    timeStamp: 37068.84999999966
    srcElement: [object Window]
    returnValue: false
    cancelBubble: true
    path: Array {
        0: [object Window]
        length: 1
    }
}

Very often, these are timeout errors because of a bad internet connection.

mattlewis92 commented 4 years ago

If there's a hook in webpack to do it then it should be possible, I had a quick look and couldn't see anything though. I don't actually use this plugin anymore as I switched to a service worker (so everything is pre-loaded and resilient to the network going down), so it's not something I would be able to work on myself, but I'd be happy to review a PR. You might be able to fix your issue by doing this with your dynamic imports: https://webpack.js.org/guides/code-splitting/#prefetchingpreloading-modules or using a service worker: https://github.com/NekR/offline-plugin

jens-duttke commented 4 years ago

@mattlewis92 In the mean time, I'm using Service Workers too, and some first-time visitors still get ChunkLoadErrors, I assume simply because of network problems. Affected are chunks which are loaded directly by launching the web app. And since the browser was able to download other files just milliseconds before (e.g. the index.html) and since it's able to send a bug report, I assume it's just a temporary problem.

In the documentation of the recommended offline-plugin, they write:

As the above errors are out of the control of offline-plugin, there is nothing we can do to prevent them. What you may do if you receive any of them is to catch them in your code and try to reschedule the update.

So I think your plugin would still as useful as before. Or do you think there would be changes required to better interact with service workers?

mattlewis92 commented 4 years ago

One workaround I've found for this problem is to listen to the global error event and then use that to re-add stylesheets yourself, it seems to fix these types of errors in our logs. You could tweak the logic a bit to add multiple retry support and delays:

  <script>
    window.addEventListener('error', function (e) {
      // workaround for chrome bug where SW loaded css doesn't always work
      // https://bugs.chromium.org/p/chromium/issues/detail?id=968444
      var ele = e.target;
      if (
        ele.tagName === 'LINK' &&
        ele.getAttribute('rel') === 'stylesheet' &&
        ele.href.indexOf('ngsw-bypass') === -1
      ) {
        var link = document.createElement('link');
        link.setAttribute('rel', 'stylesheet');
        link.setAttribute('href', ele.href + '?ngsw-bypass=1');
        ele.parentNode.insertBefore(link, ele.nextSibling);
      }
    }, true);
  </script>
boswellgao commented 2 years ago

@mattlewis92 In my case I use mini-css-extract-plugin to extract the css to a chunk file. in sometimes the css request will got connection reset error. and I saw the mini-css-extract-plugin source code:

  Template.indent([
    "var errorType = event && (event.type === 'load' ? 'missing' : event.type);",
    'var realHref = event && event.target && event.target.href || fullhref;',
    'var err = new Error("Loading CSS chunk " + chunkId + " failed.\\n(" + realHref + ")");',
    'err.code = "CSS_CHUNK_LOAD_FAILED";',
    'err.type = errorType;',
    'err.request = realHref;',
    'delete installedCssChunks[chunkId]',
    'linkTag.parentNode.removeChild(linkTag)',
    'reject(err);',
  ])

as you can see,this plugin just reject the error and no retry. in this case I will got the error

Failed to load resource: xxxx.css net::ERR_CONNECTION_RESET
Uncaught (in promise) Error Loading CSS  chunk 5 failed. in the main.js

if this plugin can solve this problem ?