qlevar_router icon indicating copy to clipboard operation
qlevar_router copied to clipboard

Uncaught DeferredLoadException when user user refreshes page after deployment

Open tejHackerDEV opened this issue 2 years ago • 6 comments

Hi @SchabanBo I am using your deferred loading middleware concept to lazy load routes in web version. But the issue is when ever I deploy some changes & host the site, the users who were on the site at the time of hosting deployment are getting error when they refresh the page saying hash value has been changed & making user stuck in the loading screen by printing the below log in the browser console.

Uncaught DeferredLoadException: 'Loading main.dart.js_28.part.js failed: the code with hash 'x65fcDCd7yY7PcvPeBnWLAutpQA=' was not loaded.

If the user clears the cache & close all the browser tabs & re-opens then its opening the page. I think it is caching in browser & as the page refresh the hash is not getting matched with the one that is stored in local

tejHackerDEV avatar Sep 28 '22 13:09 tejHackerDEV

Hi @SchabanBo any update on this? Because it is making lot of issues in production. So many user are facing this issue.

tejHackerDEV avatar Sep 30 '22 05:09 tejHackerDEV

Hi @tejHackerDEV, I think it is just a cache problem and not a problem with the package. I had a similar issue with the main.dart.js and solved it with this, maybe this could help.

SchabanBo avatar Sep 30 '22 08:09 SchabanBo

Hi @tejHackerDEV, I think it is just a cache problem and not a problem with the package. I had a similar issue with the main.dart.js and solved it with this, maybe this could help.

Hi @SchabanBo, can you help me do it by connecting online or something, because I my script file in index.html is so different from the one that you tagged

tejHackerDEV avatar Sep 30 '22 12:09 tejHackerDEV

Hi @SchabanBo, I think this is what happening in my case service worker is getting downloaded the newer version but the main.dart.js_[number].part.js is failing to load showing mismatch hash

tejHackerDEV avatar Oct 01 '22 05:10 tejHackerDEV

@SchabanBo any updates on this?

tejHackerDEV avatar Oct 12 '22 12:10 tejHackerDEV

@tejHackerDEV Not really, because this is something that could not be fixed here from the package. Maybe you should open an issue for that in flutter project.

SchabanBo avatar Oct 12 '22 14:10 SchabanBo

@SchabanBo, as you said before it is not related to package which is true, it is related to how Flutter & service-worker, handles the part files generated by deferred_loading. So when ever an route has been marked as deferred, a part file is getting generated to it. Let suppose say for route name sign_in_page.dart an associated main.dart.js_1.part.js file is generated. And this main.dart.js_1.part.js file contains some hash at the end (inside file) & there is a main.dart.js file from which everything is loaded by flutter. So inside the main.dart.js file there are some contents named deferredPartUris & deferredPartHashes where flutter is mapping the hash to the part file & this hash will be equal to the one that is present inside the part file.

By default this service-worker is caching the part files but not the main.dart.js in the user browser & when ever user goes to that route, service-worker is fetching part files from the local cache.

So when ever new deployment happens the main.dart.js file is fetching freshly & it contains the updated hashes of the part files but service-worker fetching the part file from the user local-cache when user navigates to the page & Flutter internally checks the hashes contains in the main.dart.js file is equal to the part file fetched by service-worker. If both are not same then it is throwing Uncaught DeferredLoadException: 'Loading main.dart.js_{number}.part.js failed: the code with hash '{random_hash}' was not loaded

So in-order to suppress it there are two options as below can use either one:-

  1. --pwa-strategy=none add the flag while building web application ie., flutter build web --pwa-strategy=none.
  2. Add the below script tag inside <head> </head> tag of index.html present inside web folder.
    <script>
        if ('caches' in window) {
          caches.keys()
            .then(function(keyList) {
              return Promise.all(keyList.map(function(key) {
                return caches.delete(key);
              }));
            })
        }
    </script>

Where the first option will never save any cache but coming to second option it will clear the previously saved cache on every page refresh. So in both cases, service-worker will fetch the new files every time instead of fetching from local-cache.

To cross-check we can find these main.dart.js files inside build/web/

tejHackerDEV avatar Nov 24 '22 07:11 tejHackerDEV