@vitejs/plugin-legacy 3.0.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,7 +8,7 @@ By default, this plugin will:
8
8
 
9
9
  - Generate a polyfill chunk including SystemJS runtime, and any necessary polyfills determined by specified browser targets and **actual usage** in the bundle.
10
10
 
11
- - Inject `<script nomodule>` tags into generated HTML to conditionally load the polyfills and legacy bundle only in browsers without native ESM support.
11
+ - Inject `<script nomodule>` tags into generated HTML to conditionally load the polyfills and legacy bundle only in browsers without widely-available features support.
12
12
 
13
13
  - Inject the `import.meta.env.LEGACY` env variable, which will only be `true` in the legacy production build, and `false` in all other cases.
14
14
 
@@ -38,11 +38,11 @@ npm add -D terser
38
38
  ### `targets`
39
39
 
40
40
  - **Type:** `string | string[] | { [key: string]: string }`
41
- - **Default:** `'defaults'`
41
+ - **Default:** [`'last 2 versions and not dead, > 0.3%, Firefox ESR'`](https://browsersl.ist/#q=last+2+versions+and+not+dead%2C+%3E+0.3%25%2C+Firefox+ESR)
42
42
 
43
43
  If explicitly set, it's passed on to [`@babel/preset-env`](https://babeljs.io/docs/en/babel-preset-env#targets).
44
44
 
45
- The query is also [Browserslist compatible](https://github.com/browserslist/browserslist). The default value, `'defaults'`, is what is recommended by Browserslist. See [Browserslist Best Practices](https://github.com/browserslist/browserslist#best-practices) for more details.
45
+ The query is also [Browserslist compatible](https://github.com/browserslist/browserslist). See [Browserslist Best Practices](https://github.com/browserslist/browserslist#best-practices) for more details.
46
46
 
47
47
  ### `polyfills`
48
48
 
@@ -117,12 +117,18 @@ npm add -D terser
117
117
 
118
118
  Defaults to `false`. Enabling this option will exclude `systemjs/dist/s.min.js` inside polyfills-legacy chunk.
119
119
 
120
- ## Dynamic Import
120
+ ## Browsers that supports ESM but does not support widely-available features
121
121
 
122
- The legacy plugin offers a way to use native `import()` in the modern build while falling back to the legacy build in browsers with native ESM but without dynamic import support (e.g. Legacy Edge). This feature works by injecting a runtime check and loading the legacy bundle with SystemJs runtime if needed. There are the following drawbacks:
122
+ The legacy plugin offers a way to use widely-available features natively in the modern build, while falling back to the legacy build in browsers with native ESM but without those features supported (e.g. Legacy Edge). This feature works by injecting a runtime check and loading the legacy bundle with SystemJs runtime if needed. There are the following drawbacks:
123
123
 
124
124
  - Modern bundle is downloaded in all ESM browsers
125
- - Modern bundle throws `SyntaxError` in browsers without dynamic import
125
+ - Modern bundle throws `SyntaxError` in browsers without those features support
126
+
127
+ The following syntax are considered as widely-available:
128
+
129
+ - dynamic import
130
+ - `import.meta`
131
+ - async generator
126
132
 
127
133
  ## Polyfill Specifiers
128
134
 
package/dist/index.cjs CHANGED
@@ -9,8 +9,13 @@ const node_url = require('node:url');
9
9
  const vite = require('vite');
10
10
  const MagicString = require('magic-string');
11
11
  const require$$0 = require('tty');
12
+ const browserslist = require('browserslist');
12
13
 
13
- var picocolors = {exports: {}};
14
+ var picocolorsExports = {};
15
+ var picocolors = {
16
+ get exports(){ return picocolorsExports; },
17
+ set exports(v){ picocolorsExports = v; },
18
+ };
14
19
 
15
20
  let tty = require$$0;
16
21
 
@@ -69,12 +74,22 @@ let createColors = (enabled = isColorSupported) => ({
69
74
  });
70
75
 
71
76
  picocolors.exports = createColors();
72
- picocolors.exports.createColors = createColors;
77
+ picocolorsExports.createColors = createColors;
78
+
79
+ const safari10NoModuleFix = `!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();`;
80
+ const legacyPolyfillId = "vite-legacy-polyfill";
81
+ const legacyEntryId = "vite-legacy-entry";
82
+ const systemJSInlineCode = `System.import(document.getElementById('${legacyEntryId}').getAttribute('data-src'))`;
83
+ const detectModernBrowserVarName = "__vite_is_modern_browser";
84
+ const detectModernBrowserDetector = 'import.meta.url;import("_").catch(()=>1);async function* g(){};';
85
+ const detectModernBrowserCode = `${detectModernBrowserDetector}window.${detectModernBrowserVarName}=true;`;
86
+ const dynamicFallbackInlineCode = `!function(){if(window.${detectModernBrowserVarName})return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("${legacyPolyfillId}"),n=document.createElement("script");n.src=e.src,n.onload=function(){${systemJSInlineCode}},document.body.appendChild(n)}();`;
87
+ const modernChunkLegacyGuard = `export function __vite_legacy_guard(){${detectModernBrowserDetector}};`;
73
88
 
74
89
  let babel;
75
90
  async function loadBabel() {
76
91
  if (!babel) {
77
- babel = await import('@babel/standalone');
92
+ babel = await import('@babel/core');
78
93
  }
79
94
  return babel;
80
95
  }
@@ -125,21 +140,12 @@ function toAssetPathFromHtml(filename, htmlPath, config) {
125
140
  toRelative
126
141
  );
127
142
  }
128
- const safari10NoModuleFix = `!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();`;
129
- const legacyPolyfillId = "vite-legacy-polyfill";
130
- const legacyEntryId = "vite-legacy-entry";
131
- const systemJSInlineCode = `System.import(document.getElementById('${legacyEntryId}').getAttribute('data-src'))`;
132
- const detectModernBrowserVarName = "__vite_is_modern_browser";
133
- const detectModernBrowserCode = `try{import.meta.url;import("_").catch(()=>1);}catch(e){}window.${detectModernBrowserVarName}=true;`;
134
- const dynamicFallbackInlineCode = `!function(){if(window.${detectModernBrowserVarName})return;console.warn("vite: loading legacy build because dynamic import or import.meta.url is unsupported, syntax error above should be ignored");var e=document.getElementById("${legacyPolyfillId}"),n=document.createElement("script");n.src=e.src,n.onload=function(){${systemJSInlineCode}},document.body.appendChild(n)}();`;
135
- const forceDynamicImportUsage = `export function __vite_legacy_guard(){import('data:text/javascript,')};`;
136
143
  const legacyEnvVarMarker = `__VITE_IS_LEGACY__`;
137
144
  const _require = node_module.createRequire((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('index.cjs', document.baseURI).href)));
138
145
  function viteLegacyPlugin(options = {}) {
139
146
  let config;
140
- const targets = options.targets || "defaults";
147
+ let targets;
141
148
  const genLegacy = options.renderLegacyChunks !== false;
142
- const genDynamicFallback = genLegacy;
143
149
  const debugFlags = (process.env.DEBUG || "").split(",");
144
150
  const isDebug = debugFlags.includes("vite:*") || debugFlags.includes("vite:legacy");
145
151
  const facadeToLegacyChunkMap = /* @__PURE__ */ new Map();
@@ -188,7 +194,7 @@ function viteLegacyPlugin(options = {}) {
188
194
  "edge79",
189
195
  "firefox67",
190
196
  "chrome64",
191
- "safari11.1"
197
+ "safari12"
192
198
  ];
193
199
  }
194
200
  }
@@ -201,7 +207,7 @@ function viteLegacyPlugin(options = {}) {
201
207
  configResolved(config2) {
202
208
  if (overriddenBuildTarget) {
203
209
  config2.logger.warn(
204
- picocolors.exports.yellow(
210
+ picocolorsExports.yellow(
205
211
  `plugin-legacy overrode 'build.target'. You should pass 'targets' as an option to this plugin with the list of legacy browsers to support instead.`
206
212
  )
207
213
  );
@@ -238,7 +244,7 @@ function viteLegacyPlugin(options = {}) {
238
244
  if (!genLegacy) {
239
245
  return;
240
246
  }
241
- if (legacyPolyfills.size || genDynamicFallback) {
247
+ if (legacyPolyfills.size) {
242
248
  await detectPolyfills(
243
249
  `Promise.resolve(); Promise.all();`,
244
250
  targets,
@@ -253,6 +259,8 @@ function viteLegacyPlugin(options = {}) {
253
259
  legacyPolyfills,
254
260
  bundle,
255
261
  facadeToLegacyPolyfillMap,
262
+ // force using terser for legacy polyfill minification, since esbuild
263
+ // isn't legacy-safe
256
264
  config.build,
257
265
  "iife",
258
266
  opts,
@@ -273,6 +281,8 @@ function viteLegacyPlugin(options = {}) {
273
281
  if (!genLegacy || config.build.ssr) {
274
282
  return;
275
283
  }
284
+ targets = options.targets || browserslist.loadConfig({ path: config.root }) || "last 2 versions and not dead, > 0.3%, Firefox ESR";
285
+ isDebug && console.log(`[@vitejs/plugin-legacy] targets:`, targets);
276
286
  const getLegacyOutputFileName = (fileNames, defaultFileName = "[name]-legacy-[hash].js") => {
277
287
  if (!fileNames) {
278
288
  return path.posix.join(config.build.assetsDir, defaultFileName);
@@ -312,8 +322,8 @@ function viteLegacyPlugin(options = {}) {
312
322
  await detectPolyfills(raw, { esmodules: true }, modernPolyfills);
313
323
  }
314
324
  const ms = new MagicString(raw);
315
- if (genDynamicFallback && chunk.isEntry) {
316
- ms.prepend(forceDynamicImportUsage);
325
+ if (genLegacy && chunk.isEntry) {
326
+ ms.prepend(modernChunkLegacyGuard);
317
327
  }
318
328
  if (raw.includes(legacyEnvVarMarker)) {
319
329
  const re = new RegExp(legacyEnvVarMarker, "g");
@@ -345,13 +355,16 @@ function viteLegacyPlugin(options = {}) {
345
355
  const needPolyfills = options.polyfills !== false && !Array.isArray(options.polyfills);
346
356
  const sourceMaps = !!config.build.sourcemap;
347
357
  const babel2 = await loadBabel();
348
- const { code, map } = babel2.transform(raw, {
358
+ const result = babel2.transform(raw, {
349
359
  babelrc: false,
350
360
  configFile: false,
351
361
  compact: !!config.build.minify,
352
362
  sourceMaps,
353
363
  inputSourceMap: void 0,
364
+ // sourceMaps ? chunk.map : undefined, `.map` TODO: moved to OutputChunk?
354
365
  presets: [
366
+ // forcing our plugin to run before preset-env by wrapping it in a
367
+ // preset so we can catch the injected import statements...
355
368
  [
356
369
  () => ({
357
370
  plugins: [
@@ -362,7 +375,7 @@ function viteLegacyPlugin(options = {}) {
362
375
  })
363
376
  ],
364
377
  [
365
- "env",
378
+ "@babel/preset-env",
366
379
  createBabelPresetEnvOptions(targets, {
367
380
  needPolyfills,
368
381
  ignoreBrowserslistConfig: options.ignoreBrowserslistConfig
@@ -370,8 +383,8 @@ function viteLegacyPlugin(options = {}) {
370
383
  ]
371
384
  ]
372
385
  });
373
- if (code)
374
- return { code, map };
386
+ if (result)
387
+ return { code: result.code, map: result.map };
375
388
  return null;
376
389
  },
377
390
  transformIndexHtml(html, { chunk }) {
@@ -447,6 +460,9 @@ function viteLegacyPlugin(options = {}) {
447
460
  attrs: {
448
461
  nomodule: true,
449
462
  crossorigin: true,
463
+ // we set the entry path on the element as an attribute so that the
464
+ // script content will stay consistent - which allows using a constant
465
+ // hash value for CSP.
450
466
  id: legacyEntryId,
451
467
  "data-src": toAssetPathFromHtml(
452
468
  legacyEntryFilename,
@@ -462,7 +478,7 @@ function viteLegacyPlugin(options = {}) {
462
478
  `No corresponding legacy entry chunk found for ${htmlFilename}`
463
479
  );
464
480
  }
465
- if (genDynamicFallback && legacyPolyfillFilename && legacyEntryFilename) {
481
+ if (genLegacy && legacyPolyfillFilename && legacyEntryFilename) {
466
482
  tags.push({
467
483
  tag: "script",
468
484
  attrs: { type: "module" },
@@ -487,7 +503,7 @@ function viteLegacyPlugin(options = {}) {
487
503
  }
488
504
  if (isLegacyBundle(bundle, opts)) {
489
505
  for (const name in bundle) {
490
- if (bundle[name].type === "asset") {
506
+ if (bundle[name].type === "asset" && !/.+\.map$/.test(name)) {
491
507
  delete bundle[name];
492
508
  }
493
509
  }
@@ -498,20 +514,20 @@ function viteLegacyPlugin(options = {}) {
498
514
  }
499
515
  async function detectPolyfills(code, targets, list) {
500
516
  const babel2 = await loadBabel();
501
- const { ast } = babel2.transform(code, {
517
+ const result = babel2.transform(code, {
502
518
  ast: true,
503
519
  babelrc: false,
504
520
  configFile: false,
505
521
  presets: [
506
522
  [
507
- "env",
523
+ "@babel/preset-env",
508
524
  createBabelPresetEnvOptions(targets, {
509
525
  ignoreBrowserslistConfig: true
510
526
  })
511
527
  ]
512
528
  ]
513
529
  });
514
- for (const node of ast.program.body) {
530
+ for (const node of result.ast.program.body) {
515
531
  if (node.type === "ImportDeclaration") {
516
532
  const source = node.source.value;
517
533
  if (source.startsWith("core-js/") || source.startsWith("regenerator-runtime/")) {
@@ -543,6 +559,7 @@ async function buildPolyfillChunk(mode, imports, bundle, facadeToChunkMap, build
543
559
  minify = minify ? "terser" : false;
544
560
  const res = await vite.build({
545
561
  mode,
562
+ // so that everything is resolved from here
546
563
  root: path.dirname(node_url.fileURLToPath((typeof document === 'undefined' ? new (require('u' + 'rl').URL)('file:' + __filename).href : (document.currentScript && document.currentScript.src || new URL('index.cjs', document.baseURI).href)))),
547
564
  configFile: false,
548
565
  logLevel: "error",
@@ -561,9 +578,15 @@ async function buildPolyfillChunk(mode, imports, bundle, facadeToChunkMap, build
561
578
  }
562
579
  }
563
580
  },
581
+ // Don't run esbuild for transpilation or minification
582
+ // because we don't want to transpile code.
564
583
  esbuild: false,
565
584
  optimizeDeps: {
566
585
  esbuildOptions: {
586
+ // If a value above 'es5' is set, esbuild injects helper functions which uses es2015 features.
587
+ // This limits the input code not to include es2015+ codes.
588
+ // But core-js is the only dependency which includes commonjs code
589
+ // and core-js doesn't include es2015+ codes.
567
590
  target: "es5"
568
591
  }
569
592
  }
@@ -613,7 +636,7 @@ function recordAndRemovePolyfillBabelPlugin(polyfills) {
613
636
  name: "vite-remove-polyfill-import",
614
637
  post({ path: path2 }) {
615
638
  path2.get("body").forEach((p) => {
616
- if (t.isImportDeclaration(p)) {
639
+ if (t.isImportDeclaration(p.node)) {
617
640
  polyfills.add(p.node.source.value);
618
641
  p.remove();
619
642
  }
@@ -648,11 +671,11 @@ function wrapIIFEBabelPlugin() {
648
671
  };
649
672
  }
650
673
  const cspHashes = [
651
- node_crypto.createHash("sha256").update(safari10NoModuleFix).digest("base64"),
652
- node_crypto.createHash("sha256").update(systemJSInlineCode).digest("base64"),
653
- node_crypto.createHash("sha256").update(detectModernBrowserCode).digest("base64"),
654
- node_crypto.createHash("sha256").update(dynamicFallbackInlineCode).digest("base64")
655
- ];
674
+ safari10NoModuleFix,
675
+ systemJSInlineCode,
676
+ detectModernBrowserCode,
677
+ dynamicFallbackInlineCode
678
+ ].map((i) => node_crypto.createHash("sha256").update(i).digest("base64"));
656
679
 
657
680
  module.exports = viteLegacyPlugin;
658
681
  module.exports.cspHashes = cspHashes;
package/dist/index.mjs CHANGED
@@ -5,8 +5,13 @@ import { fileURLToPath } from 'node:url';
5
5
  import { build, normalizePath } from 'vite';
6
6
  import MagicString from 'magic-string';
7
7
  import require$$0 from 'tty';
8
+ import { loadConfig } from 'browserslist';
8
9
 
9
- var picocolors = {exports: {}};
10
+ var picocolorsExports = {};
11
+ var picocolors = {
12
+ get exports(){ return picocolorsExports; },
13
+ set exports(v){ picocolorsExports = v; },
14
+ };
10
15
 
11
16
  let tty = require$$0;
12
17
 
@@ -65,12 +70,22 @@ let createColors = (enabled = isColorSupported) => ({
65
70
  });
66
71
 
67
72
  picocolors.exports = createColors();
68
- picocolors.exports.createColors = createColors;
73
+ picocolorsExports.createColors = createColors;
74
+
75
+ const safari10NoModuleFix = `!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();`;
76
+ const legacyPolyfillId = "vite-legacy-polyfill";
77
+ const legacyEntryId = "vite-legacy-entry";
78
+ const systemJSInlineCode = `System.import(document.getElementById('${legacyEntryId}').getAttribute('data-src'))`;
79
+ const detectModernBrowserVarName = "__vite_is_modern_browser";
80
+ const detectModernBrowserDetector = 'import.meta.url;import("_").catch(()=>1);async function* g(){};';
81
+ const detectModernBrowserCode = `${detectModernBrowserDetector}window.${detectModernBrowserVarName}=true;`;
82
+ const dynamicFallbackInlineCode = `!function(){if(window.${detectModernBrowserVarName})return;console.warn("vite: loading legacy chunks, syntax error above and the same error below should be ignored");var e=document.getElementById("${legacyPolyfillId}"),n=document.createElement("script");n.src=e.src,n.onload=function(){${systemJSInlineCode}},document.body.appendChild(n)}();`;
83
+ const modernChunkLegacyGuard = `export function __vite_legacy_guard(){${detectModernBrowserDetector}};`;
69
84
 
70
85
  let babel;
71
86
  async function loadBabel() {
72
87
  if (!babel) {
73
- babel = await import('@babel/standalone');
88
+ babel = await import('@babel/core');
74
89
  }
75
90
  return babel;
76
91
  }
@@ -121,21 +136,12 @@ function toAssetPathFromHtml(filename, htmlPath, config) {
121
136
  toRelative
122
137
  );
123
138
  }
124
- const safari10NoModuleFix = `!function(){var e=document,t=e.createElement("script");if(!("noModule"in t)&&"onbeforeload"in t){var n=!1;e.addEventListener("beforeload",(function(e){if(e.target===t)n=!0;else if(!e.target.hasAttribute("nomodule")||!n)return;e.preventDefault()}),!0),t.type="module",t.src=".",e.head.appendChild(t),t.remove()}}();`;
125
- const legacyPolyfillId = "vite-legacy-polyfill";
126
- const legacyEntryId = "vite-legacy-entry";
127
- const systemJSInlineCode = `System.import(document.getElementById('${legacyEntryId}').getAttribute('data-src'))`;
128
- const detectModernBrowserVarName = "__vite_is_modern_browser";
129
- const detectModernBrowserCode = `try{import.meta.url;import("_").catch(()=>1);}catch(e){}window.${detectModernBrowserVarName}=true;`;
130
- const dynamicFallbackInlineCode = `!function(){if(window.${detectModernBrowserVarName})return;console.warn("vite: loading legacy build because dynamic import or import.meta.url is unsupported, syntax error above should be ignored");var e=document.getElementById("${legacyPolyfillId}"),n=document.createElement("script");n.src=e.src,n.onload=function(){${systemJSInlineCode}},document.body.appendChild(n)}();`;
131
- const forceDynamicImportUsage = `export function __vite_legacy_guard(){import('data:text/javascript,')};`;
132
139
  const legacyEnvVarMarker = `__VITE_IS_LEGACY__`;
133
140
  const _require = createRequire(import.meta.url);
134
141
  function viteLegacyPlugin(options = {}) {
135
142
  let config;
136
- const targets = options.targets || "defaults";
143
+ let targets;
137
144
  const genLegacy = options.renderLegacyChunks !== false;
138
- const genDynamicFallback = genLegacy;
139
145
  const debugFlags = (process.env.DEBUG || "").split(",");
140
146
  const isDebug = debugFlags.includes("vite:*") || debugFlags.includes("vite:legacy");
141
147
  const facadeToLegacyChunkMap = /* @__PURE__ */ new Map();
@@ -184,7 +190,7 @@ function viteLegacyPlugin(options = {}) {
184
190
  "edge79",
185
191
  "firefox67",
186
192
  "chrome64",
187
- "safari11.1"
193
+ "safari12"
188
194
  ];
189
195
  }
190
196
  }
@@ -197,7 +203,7 @@ function viteLegacyPlugin(options = {}) {
197
203
  configResolved(config2) {
198
204
  if (overriddenBuildTarget) {
199
205
  config2.logger.warn(
200
- picocolors.exports.yellow(
206
+ picocolorsExports.yellow(
201
207
  `plugin-legacy overrode 'build.target'. You should pass 'targets' as an option to this plugin with the list of legacy browsers to support instead.`
202
208
  )
203
209
  );
@@ -234,7 +240,7 @@ function viteLegacyPlugin(options = {}) {
234
240
  if (!genLegacy) {
235
241
  return;
236
242
  }
237
- if (legacyPolyfills.size || genDynamicFallback) {
243
+ if (legacyPolyfills.size) {
238
244
  await detectPolyfills(
239
245
  `Promise.resolve(); Promise.all();`,
240
246
  targets,
@@ -249,6 +255,8 @@ function viteLegacyPlugin(options = {}) {
249
255
  legacyPolyfills,
250
256
  bundle,
251
257
  facadeToLegacyPolyfillMap,
258
+ // force using terser for legacy polyfill minification, since esbuild
259
+ // isn't legacy-safe
252
260
  config.build,
253
261
  "iife",
254
262
  opts,
@@ -269,6 +277,8 @@ function viteLegacyPlugin(options = {}) {
269
277
  if (!genLegacy || config.build.ssr) {
270
278
  return;
271
279
  }
280
+ targets = options.targets || loadConfig({ path: config.root }) || "last 2 versions and not dead, > 0.3%, Firefox ESR";
281
+ isDebug && console.log(`[@vitejs/plugin-legacy] targets:`, targets);
272
282
  const getLegacyOutputFileName = (fileNames, defaultFileName = "[name]-legacy-[hash].js") => {
273
283
  if (!fileNames) {
274
284
  return path.posix.join(config.build.assetsDir, defaultFileName);
@@ -308,8 +318,8 @@ function viteLegacyPlugin(options = {}) {
308
318
  await detectPolyfills(raw, { esmodules: true }, modernPolyfills);
309
319
  }
310
320
  const ms = new MagicString(raw);
311
- if (genDynamicFallback && chunk.isEntry) {
312
- ms.prepend(forceDynamicImportUsage);
321
+ if (genLegacy && chunk.isEntry) {
322
+ ms.prepend(modernChunkLegacyGuard);
313
323
  }
314
324
  if (raw.includes(legacyEnvVarMarker)) {
315
325
  const re = new RegExp(legacyEnvVarMarker, "g");
@@ -341,13 +351,16 @@ function viteLegacyPlugin(options = {}) {
341
351
  const needPolyfills = options.polyfills !== false && !Array.isArray(options.polyfills);
342
352
  const sourceMaps = !!config.build.sourcemap;
343
353
  const babel2 = await loadBabel();
344
- const { code, map } = babel2.transform(raw, {
354
+ const result = babel2.transform(raw, {
345
355
  babelrc: false,
346
356
  configFile: false,
347
357
  compact: !!config.build.minify,
348
358
  sourceMaps,
349
359
  inputSourceMap: void 0,
360
+ // sourceMaps ? chunk.map : undefined, `.map` TODO: moved to OutputChunk?
350
361
  presets: [
362
+ // forcing our plugin to run before preset-env by wrapping it in a
363
+ // preset so we can catch the injected import statements...
351
364
  [
352
365
  () => ({
353
366
  plugins: [
@@ -358,7 +371,7 @@ function viteLegacyPlugin(options = {}) {
358
371
  })
359
372
  ],
360
373
  [
361
- "env",
374
+ "@babel/preset-env",
362
375
  createBabelPresetEnvOptions(targets, {
363
376
  needPolyfills,
364
377
  ignoreBrowserslistConfig: options.ignoreBrowserslistConfig
@@ -366,8 +379,8 @@ function viteLegacyPlugin(options = {}) {
366
379
  ]
367
380
  ]
368
381
  });
369
- if (code)
370
- return { code, map };
382
+ if (result)
383
+ return { code: result.code, map: result.map };
371
384
  return null;
372
385
  },
373
386
  transformIndexHtml(html, { chunk }) {
@@ -443,6 +456,9 @@ function viteLegacyPlugin(options = {}) {
443
456
  attrs: {
444
457
  nomodule: true,
445
458
  crossorigin: true,
459
+ // we set the entry path on the element as an attribute so that the
460
+ // script content will stay consistent - which allows using a constant
461
+ // hash value for CSP.
446
462
  id: legacyEntryId,
447
463
  "data-src": toAssetPathFromHtml(
448
464
  legacyEntryFilename,
@@ -458,7 +474,7 @@ function viteLegacyPlugin(options = {}) {
458
474
  `No corresponding legacy entry chunk found for ${htmlFilename}`
459
475
  );
460
476
  }
461
- if (genDynamicFallback && legacyPolyfillFilename && legacyEntryFilename) {
477
+ if (genLegacy && legacyPolyfillFilename && legacyEntryFilename) {
462
478
  tags.push({
463
479
  tag: "script",
464
480
  attrs: { type: "module" },
@@ -483,7 +499,7 @@ function viteLegacyPlugin(options = {}) {
483
499
  }
484
500
  if (isLegacyBundle(bundle, opts)) {
485
501
  for (const name in bundle) {
486
- if (bundle[name].type === "asset") {
502
+ if (bundle[name].type === "asset" && !/.+\.map$/.test(name)) {
487
503
  delete bundle[name];
488
504
  }
489
505
  }
@@ -494,20 +510,20 @@ function viteLegacyPlugin(options = {}) {
494
510
  }
495
511
  async function detectPolyfills(code, targets, list) {
496
512
  const babel2 = await loadBabel();
497
- const { ast } = babel2.transform(code, {
513
+ const result = babel2.transform(code, {
498
514
  ast: true,
499
515
  babelrc: false,
500
516
  configFile: false,
501
517
  presets: [
502
518
  [
503
- "env",
519
+ "@babel/preset-env",
504
520
  createBabelPresetEnvOptions(targets, {
505
521
  ignoreBrowserslistConfig: true
506
522
  })
507
523
  ]
508
524
  ]
509
525
  });
510
- for (const node of ast.program.body) {
526
+ for (const node of result.ast.program.body) {
511
527
  if (node.type === "ImportDeclaration") {
512
528
  const source = node.source.value;
513
529
  if (source.startsWith("core-js/") || source.startsWith("regenerator-runtime/")) {
@@ -539,6 +555,7 @@ async function buildPolyfillChunk(mode, imports, bundle, facadeToChunkMap, build
539
555
  minify = minify ? "terser" : false;
540
556
  const res = await build({
541
557
  mode,
558
+ // so that everything is resolved from here
542
559
  root: path.dirname(fileURLToPath(import.meta.url)),
543
560
  configFile: false,
544
561
  logLevel: "error",
@@ -557,9 +574,15 @@ async function buildPolyfillChunk(mode, imports, bundle, facadeToChunkMap, build
557
574
  }
558
575
  }
559
576
  },
577
+ // Don't run esbuild for transpilation or minification
578
+ // because we don't want to transpile code.
560
579
  esbuild: false,
561
580
  optimizeDeps: {
562
581
  esbuildOptions: {
582
+ // If a value above 'es5' is set, esbuild injects helper functions which uses es2015 features.
583
+ // This limits the input code not to include es2015+ codes.
584
+ // But core-js is the only dependency which includes commonjs code
585
+ // and core-js doesn't include es2015+ codes.
563
586
  target: "es5"
564
587
  }
565
588
  }
@@ -609,7 +632,7 @@ function recordAndRemovePolyfillBabelPlugin(polyfills) {
609
632
  name: "vite-remove-polyfill-import",
610
633
  post({ path: path2 }) {
611
634
  path2.get("body").forEach((p) => {
612
- if (t.isImportDeclaration(p)) {
635
+ if (t.isImportDeclaration(p.node)) {
613
636
  polyfills.add(p.node.source.value);
614
637
  p.remove();
615
638
  }
@@ -644,10 +667,10 @@ function wrapIIFEBabelPlugin() {
644
667
  };
645
668
  }
646
669
  const cspHashes = [
647
- createHash("sha256").update(safari10NoModuleFix).digest("base64"),
648
- createHash("sha256").update(systemJSInlineCode).digest("base64"),
649
- createHash("sha256").update(detectModernBrowserCode).digest("base64"),
650
- createHash("sha256").update(dynamicFallbackInlineCode).digest("base64")
651
- ];
670
+ safari10NoModuleFix,
671
+ systemJSInlineCode,
672
+ detectModernBrowserCode,
673
+ dynamicFallbackInlineCode
674
+ ].map((i) => createHash("sha256").update(i).digest("base64"));
652
675
 
653
676
  export { cspHashes, viteLegacyPlugin as default, detectPolyfills };
package/package.json CHANGED
@@ -1,11 +1,17 @@
1
1
  {
2
2
  "name": "@vitejs/plugin-legacy",
3
- "version": "3.0.1",
3
+ "version": "4.0.0",
4
4
  "license": "MIT",
5
5
  "author": "Evan You",
6
6
  "files": [
7
7
  "dist"
8
8
  ],
9
+ "keywords": [
10
+ "frontend",
11
+ "vite",
12
+ "vite-plugin",
13
+ "@vitejs/plugin-legacy"
14
+ ],
9
15
  "main": "./dist/index.cjs",
10
16
  "module": "./dist/index.mjs",
11
17
  "types": "./dist/index.d.ts",
@@ -35,8 +41,10 @@
35
41
  },
36
42
  "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-legacy#readme",
37
43
  "dependencies": {
38
- "@babel/standalone": "^7.20.6",
39
- "core-js": "^3.26.1",
44
+ "@babel/core": "^7.20.12",
45
+ "@babel/preset-env": "^7.20.2",
46
+ "browserslist": "^4.21.4",
47
+ "core-js": "^3.27.2",
40
48
  "magic-string": "^0.27.0",
41
49
  "regenerator-runtime": "^0.13.11",
42
50
  "systemjs": "^6.13.0"
@@ -46,7 +54,7 @@
46
54
  "vite": "^4.0.0"
47
55
  },
48
56
  "devDependencies": {
49
- "@babel/core": "^7.20.5",
57
+ "acorn": "^8.8.2",
50
58
  "picocolors": "^1.0.0",
51
59
  "vite": "workspace:*"
52
60
  }