router.onError((error, to) => {
if (error.message.includes('Failed to fetch dynamically imported module')) {
window.location = to.fullPath
xiaobc1234, dhumdil-apps, fightingsun, tklaas, mattmbt, jrval, linfanxxxx, mxismean, Rakasch, buerxixi, and 23 more reacted with thumbs up emoji
IlyaSemenov, NazariiShvets, MarcoRiformato, andreataglia, Mikekkamara, kyrie1103, sujitykulkarni, ysyfff, Maxou44, Adrien-D, and 2 more reacted with laugh emoji
ysyfff, dinhtheloc, jaldhimehta-incentius, and pratikpatel-aurochs reacted with rocket emoji
domnantas, vaawebdev-ozee, lobaak, hasan-mehboob, basd1995, DRJungOok, NazariiShvets, Adidas-okkk, ron-tayler, komorebi-cqd, and 5 more reacted with eyes emoji
All reactions
@victorlmneves yeah, that works for vue-router
and is in the StackOverflow link I shared. Unfortunately we're using react-router
through various indirection connected-react-router
& react-router-config
. So even if it did expose an onError
handler which I've been unable to find, we'd struggle calling it :(
Any updates on this?
Also running into the same issue with a vue 2 + vite app, when using dynamic imports.
The vue router hack could work for some imports, but we have dynamic imports outside of the router, which i don't think the hack would be able to cover.
Besides, forcing a reload because an error occurred doesn't seem like the best UX, so wondering if there's a solution/workaround that is more subtle and "behind the scenes" 🤔
While I understand that we should try to solve this problem ourselves, it seems like this must be quite a fundamental problem that developers will have when creating apps with vite? Especially when continuous deployment comes into the mix, because the files update very often and trigger lots of errors. For now I am back to "nightly deployments" to try and minimize disruption 😬.
It would be great if there was a standard solution somewhere in the docs. Preferably one without making the users manually "opt-in" to a page reload. Even nicer would be if vite could somehow handle it for us so we don't have to do anything. Eg catch the error and refresh the files without a hard reload of the page. That would greatly improve the DX 🙂.
Thanks for all the great work. Vite is awesome.
hafidk, yakobe, khlevon, subdavis, p4trykJ, svbackend, Cantabile-Lu, ronilitman, brettsvoid, Evertvdw, and 2 more reacted with thumbs up emoji
yakobe reacted with confused emoji
All reactions
mhayes, namu254, jatrihim, shellonix, nasso, annkilzerbuild, Mrakobec, deizianens, Yelinz, ahaku, and 58 more reacted with thumbs up emoji
jamesj2, yosmanyga, ssadek-coder, boomsi, titenis, SOUTHYYY, weolbu-owner, Merzaad, SquirrelCoder, isaiahscheel, and 37 more reacted with thumbs down emoji
bachlge, annkilzerbuild, jacksteamdev, justbearcause, weristwiegott, tronghieu60s, LuanSdev, and Technologeek reacted with laugh emoji
annkilzerbuild, Dimiona, luis-viegas, Maurisss94, rafael-lua, fratzinger, prenolancoolblue, StrangeGirlMurph, bekzat-abbvie, JoaoFelipe-neuro, and 6 more reacted with heart emoji
mrwomsk, zevisert, cruzluna, LuanSdev, kigary, and samueleholo reacted with eyes emoji
All reactions
A lot of Cypress users run into this: cypress-io/cypress#25913
I don't think I can fix it on the Cypress end. I can spend time (several days of development resources) to patch Vite if needed, but it looks like the cause isn't entirely clear.
Some observations:
Happens mostly with large bundles - like MUI (Material UI).
Especially happens on CI with Docker + many instances running (eg, race condition/resource issue)?
Any tips -- maybe from someone more familiar with Vite - on debugging this?
I will inspect Cypress more first and keep the limitations in mind.
Component tests failing intermittently with uncaught Vite "failed to fetch dynamically imported module" error in CI
cypress-io/cypress#25913
We are just hitting this now too, but it's not just when the user has a browser tab open. It can also happen much later, if the user returns to our app after we have deployed. We're trying to work out if it's caused by the index.html
page being cached for too long, rather than an issue with the JS file hashes themselves. Maybe it helps someone who is experiencing this? My reasoning goes like this:
Let's say you have index.html
which references index.abc.js
which dynamically imports moduleX.123.js
.
You update your code and deploy it, so now you have index.def.js
which dynamically imports moduleX.456.js
. This should not cause any "module not found" issues because all the file hashes are new, even the entry index
JS file.
However, if your index.html
file has been cached for longer, it still contains the reference to index.abc.js
, which dynamically imports the now deleted moduleX.123.js
. Hence you get an error.
I'm still confirming this but I wondered if it matches anyone else's experience/setup?
I think there are possibly two separate issues being described by different users/teams in this thread:
failed to fetch after a new deployment where the old version was deleted from the server
in this case, attempting to load the resource referenced by the error is expected to fail, it has been deleted
failed to fetch that occurs somewhat randomly
in this case, attempting to load the resource succeeds
For people experiencing issue 1., the solution is to organise your deployments so that old versions aren't deleted immediately. Doing a deployment of new app code doesn't mean that all users running your app in their browser will update immediately (unless you force it somehow).
For those users who still have an older version running in their browser (lets say index.123.js
), navigating to routes that load chunks dynamically will always reference the chunk that was current when they loaded your app (ie home.123.js
), and this is correct. You don't want the user getting half of their chunks with new app code and half with old, this would lead to very hard to debug issues. If you delete those chunks while the user is still navigating around the app, you will hit this error when they change routes and try to load a chunk they haven't loaded yet.
For users that load the app after a deployment, index.html
will reference a new index.456.js
chunk that references all the other chunks that are consistent with that version (ie home.456.js
if there are also changes in that chunk). The only difference is which version was referenced by index.html
when the user loaded the tab.
If you keep a manifest of each deployment, and your instrumentation/logging includes the "version" of the app users are using, you should be able to figure out how long old versions are still used. My team has seen users still operating in the same tab they loaded a month ago without updating, so we keep all our built assets deployed for a long time. If you want to force users to reload when a new version is deployed, that's a whole piece of engineering in itself.
@SecretCastle No, see this example:
Let's say, to reduce the initial bundle size, you choose to bundle by page. Let's walk through what that means:
User requests /. Nginx is instructed to serve the same JS for every path, since it is a Single Page Application. The Browser loads index.js which contains a client side router [e.g. react-dom-router / NEXT.js implicitly]. The router mounts and sees that you want to see component A for '/', which triggers a request to 'chunk-component-a.js'. Let's assume thats going OK.
Now, the user now scrolls on Page '/' and after some time finds some interesting thing and clicks a button, initiating a redirect to '/abc'. The router knows to now show you component B. While the user was happily searching through Page '/', you redeployed and re-bundled your js.
Because you bundled by page, the router now fetch the JS chunk for component B. That's called lazy loading -- it's loaded when needed. The router now loads 'chunk-component-b.js' from your server.
Sadly, chunk-component-b.js is not known, because you renamed component B to component Z. The webserver serving the JS only knowns about 'chunk-component-z.js' after the redeployment. Consequently, the lazy load of '/abc' fails.
Note: For ease of understanding I ignored that Vite does not produce chunks in the form of chunk-[component-name].js
. It uses the first few characters of the sha256 - a hash of content of the file that is to be lazy loaded. This means that any change to your file will result in a different chunk filename and thus lead to stale references in code loaded prior to deployment.
In essence, the index.js contains a map of lazy imports('some-file.js') statements to files on you server (example.com/chunk-xxxx.js). That map becomes stale in redeployments because the chunk filenames for components differ.
That's also why choosing explicit chunk filenames can relieve the problem, as you can choose chunk filenames that will remain correct between deployments.
Caches won't help when redeployments change your filename -- but they do make it worse, as they prolong the span in which errors occur if you do not invalidate the cache.
The full solution to this problem is to keep past deployment chunk-xxxx.js files around. Because they are shorted sha256 hashes, it serves like a content-addressable filesystem and thus new files only overwrite old deployment files if the content of the files are the same, in which case we do not care.
Hope that helps everyone wrap their head around the problem. Have a nice day!
I am using a aws infrastructure with vue3, vue router, and vite.
The workaround from vite (https://vitejs.dev/guide/build#load-error-handling) does not solve the problem.
Every time the refresh is triggered, the error does not disappear and i am not able to navigate with the router ...
Blank page and refresh on navigation click.
Any progress / help?
The errors is actually kinda misleading. If you open the files that failed to be imported, some may contain "Cannot find static asset".
{"url":"/_nuxt/9Ima4rhO.js","statusCode":404,"statusMessage":"Cannot find static asset /_nuxt/9Ima4rhO.js","message":"Cannot find static asset /_nuxt/9Ima4rhO.js","stack":""}
In my case, adding "routeRules" to ''nuxt.config.ts'' resolves the issue.
routeRules: {
"/**": { isr: true },
For me it was the server config. It was not recognizing .mjs extentions as javascript. .mjs is a new javascript extention that represents modules. So I updated my .htaccess to include this:
AddType application/javascript .mjs
We had a similar issue. It was caused by a workbox precache manifest and the cache eviction functionality of google chrome. In our app the service worker was caching opague responses, leading to exceeded storage quota.
This lead to the eviction of the dynamic module resulting in the error above.
If you are using service workers or had been using service workers:
check if the service worker is installed. If it is remove it and try to reproduce.
check your storage quota
check if you have opaque responses in your cache storage
update your browser (the latest version added some additional information regarding cache eviction)
hope this helps!
Quick update guys, for Angular with es-build, the issue was forgotten `"outputHashing": "all" in the angular.json (or project.json) for the production build. Without that the main.js was not with hashing in the output build and then it was cached when new deploy was done and it was looking in chunk files with the old hashings.
Was running into this too, and found that Vite now emits a vite:preloadError
event and they suggest a simple solution for this issue here to reload when this happens:
https://vitejs.dev/guide/build#load-error-handling
But it also seems like this issue has to do with your hosting service. In our case, we're using Heroku which seemingly isn't keeping older versions around, and perhaps there's a way to configure this to keep them for some time as an alternative workaround.
@IPWright83 Meanwhile, I also saw someone handling the problem this way
router.onError((error, to) => {
if (error.message.includes('Failed to fetch dynamically imported module')) {
window.location = to.fullPath