fix(hmr): use virtual module ids in import.meta.hot.accept() for vite 8 - #4065
Conversation
… 8 compatibility Vite 8 removed the import.meta.hot.accept() resolution fallback (vitejs/vite#21382). Previously, accept() could resolve filesystem-relative paths to the correct module in the module graph. In Vite 8, accept() requires the exact module ID as it appears in the import graph. The i18n module imports locale files and vue-i18n configs through virtual module IDs (#nuxt-i18n/<hash>) via the ResourcePlugin, but the HMR accept() calls were using filesystem-relative paths (e.g. '../i18n/locales/en-us.json'). This mismatch caused accept() to silently fail, making Vite fall back to a full-reload that would get stuck as a pending navigation request. This fix adds a virtualId property to the loader data and uses it in the generated import.meta.hot.accept() calls instead of the filesystem-relative path.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (4)
WalkthroughLoader and Vue I18n config metadata now includes virtual IDs derived from hashes. Generated HMR handlers for both locale loaders and Vue I18n configs use these virtual IDs in Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Thanks you for your contribution! We will need to check if HMR will still work for webpack/rspack with this change. |
|
Thanks @BobbieGoede! I just pushed an update that fixes the failed unit tests by updating the snapshots in Regarding webpack/rspack support: Since Let me know if you'd like me to add an end-to-end fixture or additional test cases for bundler validation! |
import.meta.hot.accept() for Vite 8 compatibilityimport.meta.hot.accept() for vite 8
BobbieGoede
left a comment
There was a problem hiding this comment.
I cleaned up the now unused logic and tested with vite 7 and 8 (I misremembered, we don't support HMR for webpack/rspack), LGTM!
🔗 Linked issue
📚 Description
Vite 8 removed the
import.meta.hot.accept()resolution fallback. Previously,accept()could resolve filesystem-relative paths to the correct module in the module graph. In Vite 8,accept()requires the exact module ID as it appears in the import graph.The i18n module imports locale files and vue-i18n configs through virtual module IDs (
#nuxt-i18n/<hash>) via theResourcePlugin, but the HMRaccept()calls ingenLocaleLoaderHMRandgenVueI18nConfigHMRwere using filesystem-relative paths (e.g.../i18n/locales/en-us.json). This mismatch causedaccept()to silently fail, making Vite fall back to sending{ type: "full-reload" }via WebSocket — which results in a navigation request that gets stuck in a pending state.Root Cause
In
src/gen.ts, thegenerateLoaderOptionsfunction creates loader objects with arelativeproperty usingrelative(nuxt.options.buildDir, meta.path), but the actualimport()usesasI18nVirtual(meta.hash):Then in
src/template.ts, the generated HMR code used the wrong identifier:Changes
src/gen.ts: AddedvirtualIdproperty toLocaleLoaderDatatype and populated it withasI18nVirtual(hash)in both locale loaders and vue-i18n config loaders.src/template.ts: Changedimport.meta.hot.accept()calls to usevirtualIdinstead ofrelativein bothgenLocaleLoaderHMRandgenVueI18nConfigHMR.How to Reproduce
@nuxtjs/i18nwith JSON locale fileshttp://localhost:3000/current-page) that stays in a pending state indefinitelySummary by CodeRabbit