nuxt: @vitejs/plugin-legacy wrong work in nuxt
Environment
- Operating System:
Linux
- Node Version:
v16.17.1
- Nuxt Version:
3.0.0-rc.13
- Nitro Version:
0.6.1
- Package Manager:
pnpm@7.15.0
- Builder:
vite
- User Config:
runtimeConfig
,css
,vite
- Build Modules:
-
Reproduction
Describe the bug
Problem is polyfills load after entry file and System variable is undefined!
i install legacy plugin in pure vite project and don’t see this problem. i think nuxt problem!
Additional context
No response
Logs
Uncaught ReferenceError: System is not defined `entry-legacy.4e3349cb.js:1:12341`
About this issue
- Original URL
- State: closed
- Created 2 years ago
- Reactions: 7
- Comments: 16 (4 by maintainers)
FWIW, I published my recipe above as a Nuxt module:
https://www.npmjs.com/package/nuxt-vite-legacy
This collection of hacks is not something I’m exactly proud of, but it works. 😃
Just a heads up, I managed to deliver isomorphic build which runs both legacy and non-legacy code:
1. Put the polyfills chunk to 1st position and remove
module
attribute from legacy chunksmodules/vite-legacy.ts
:2. Mark legacy chunks as
nomodule
and removedefer
from themserver/plugins/vite-legacy.ts
:This leaves incompatibility window for legacy browsers that do support modules but don’t support modern features such as async generators (based on caniuse that would be e.g. Chrome 61-62). Vanilla vite-legacy-plugin injects special detection scripts into SSR HTML: https://github.com/vitejs/vite/blob/535795a8286e4a9525acd2340e1d1d1adfd70acf/packages/plugin-legacy/src/snippets.ts
Ideally, Nuxt should adopt that approach fully.
The temporary solution for this problem is to transfer the entry-legacy file to the end of the manifest file. You can solve the problem using a Nuxt hook in a module file:
The problem is that the polyfill bundle is loaded after the entry bundle, cause polyfills should always come first. I was inspired by Ilya’s comment to create a solution like this:
That’s the only change I needed to make, no need to adjust any build artifacts or anything.
Note: The polyfill bundle key might be different depending on the settings of the legacy plugin. I’m only using it to generate polyfills for modern bundles (renderLegacyChunks: false & modernPolyfills: true)
This is something that I feel should be documented somewhere. I have prior experience with Vite and polyfills from another project and expected to be able to add the legacy plugin to the the
vite.plugins
property in thenuxt.config.ts
file without issue. I went so far as writing the documentation for using this property in Nuxt before finding this issue.Quite shocked that we need to update the response on every request using the
render:response
, feels icky IMHO.Honestly this is something I’d like to see first class support however I understand there’s very little sense in re-inventing the wheel.
We’ve discussed as a team and I think we shouldn’t adopt within Nuxt itself as the incompatibility window is small and decreasing with time.
However, a module implementation would very much be welcome. Feel free to ping me if there’s anything you need or Nuxt does not provide as part of doing this.
Just in case if anyone lands here trying to make Nuxt work in Chrome 49 (Windows XP), I managed to achieve that by removing
defer
from the script tags:and then to fix this:
[nuxt] error caught during app initialization Error: Context conflict
the workaround is to remove modern chunks completely:and then some polyfills:
This makes it work in Windows XP.
This is all (without a doubt) very dirty and unpleasant, so if there are better workarounds please weigh in!
UPDATE: see better working solution below.
You just need to add a script tag to your app that loads the polyfill with the desired options. We have something like this in our default layout:
And the config (retrieved by
useConfig()
, our own composable for site config):As a workaround, we ended up configuring
config.vite.build.target
for legacy JS support, and are using a self-hosed https://polyfill.io/ for the polyfills. We’re self-hosting it because the online version is stuck in v3 for now, see https://github.com/Financial-Times/polyfill-service/issues/2734.To make configuring
config.vite.build.target
easier, we’re usingbrowserslist
along withesbuild-plugin-browserslist
: