@vitejs/plugin-legacy 3.0.2 → 4.0.1

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,15 +74,26 @@ 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
  }
96
+ const { loadConfig: browserslistLoadConfig } = browserslist;
81
97
  function toOutputFilePathInHtml(filename, type, hostId, hostType, config, toRelative) {
82
98
  const { renderBuiltUrl } = config.experimental;
83
99
  let relative = config.base === "" || config.base === "./";
@@ -125,21 +141,12 @@ function toAssetPathFromHtml(filename, htmlPath, config) {
125
141
  toRelative
126
142
  );
127
143
  }
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
144
  const legacyEnvVarMarker = `__VITE_IS_LEGACY__`;
137
145
  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
146
  function viteLegacyPlugin(options = {}) {
139
147
  let config;
140
- const targets = options.targets || "defaults";
148
+ let targets;
141
149
  const genLegacy = options.renderLegacyChunks !== false;
142
- const genDynamicFallback = genLegacy;
143
150
  const debugFlags = (process.env.DEBUG || "").split(",");
144
151
  const isDebug = debugFlags.includes("vite:*") || debugFlags.includes("vite:legacy");
145
152
  const facadeToLegacyChunkMap = /* @__PURE__ */ new Map();
@@ -188,7 +195,7 @@ function viteLegacyPlugin(options = {}) {
188
195
  "edge79",
189
196
  "firefox67",
190
197
  "chrome64",
191
- "safari11.1"
198
+ "safari12"
192
199
  ];
193
200
  }
194
201
  }
@@ -201,7 +208,7 @@ function viteLegacyPlugin(options = {}) {
201
208
  configResolved(config2) {
202
209
  if (overriddenBuildTarget) {
203
210
  config2.logger.warn(
204
- picocolors.exports.yellow(
211
+ picocolorsExports.yellow(
205
212
  `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
213
  )
207
214
  );
@@ -238,7 +245,7 @@ function viteLegacyPlugin(options = {}) {
238
245
  if (!genLegacy) {
239
246
  return;
240
247
  }
241
- if (legacyPolyfills.size || genDynamicFallback) {
248
+ if (legacyPolyfills.size) {
242
249
  await detectPolyfills(
243
250
  `Promise.resolve(); Promise.all();`,
244
251
  targets,
@@ -253,6 +260,8 @@ function viteLegacyPlugin(options = {}) {
253
260
  legacyPolyfills,
254
261
  bundle,
255
262
  facadeToLegacyPolyfillMap,
263
+ // force using terser for legacy polyfill minification, since esbuild
264
+ // isn't legacy-safe
256
265
  config.build,
257
266
  "iife",
258
267
  opts,
@@ -273,6 +282,8 @@ function viteLegacyPlugin(options = {}) {
273
282
  if (!genLegacy || config.build.ssr) {
274
283
  return;
275
284
  }
285
+ targets = options.targets || browserslistLoadConfig({ path: config.root }) || "last 2 versions and not dead, > 0.3%, Firefox ESR";
286
+ isDebug && console.log(`[@vitejs/plugin-legacy] targets:`, targets);
276
287
  const getLegacyOutputFileName = (fileNames, defaultFileName = "[name]-legacy-[hash].js") => {
277
288
  if (!fileNames) {
278
289
  return path.posix.join(config.build.assetsDir, defaultFileName);
@@ -312,8 +323,8 @@ function viteLegacyPlugin(options = {}) {
312
323
  await detectPolyfills(raw, { esmodules: true }, modernPolyfills);
313
324
  }
314
325
  const ms = new MagicString(raw);
315
- if (genDynamicFallback && chunk.isEntry) {
316
- ms.prepend(forceDynamicImportUsage);
326
+ if (genLegacy && chunk.isEntry) {
327
+ ms.prepend(modernChunkLegacyGuard);
317
328
  }
318
329
  if (raw.includes(legacyEnvVarMarker)) {
319
330
  const re = new RegExp(legacyEnvVarMarker, "g");
@@ -345,13 +356,16 @@ function viteLegacyPlugin(options = {}) {
345
356
  const needPolyfills = options.polyfills !== false && !Array.isArray(options.polyfills);
346
357
  const sourceMaps = !!config.build.sourcemap;
347
358
  const babel2 = await loadBabel();
348
- const { code, map } = babel2.transform(raw, {
359
+ const result = babel2.transform(raw, {
349
360
  babelrc: false,
350
361
  configFile: false,
351
362
  compact: !!config.build.minify,
352
363
  sourceMaps,
353
364
  inputSourceMap: void 0,
365
+ // sourceMaps ? chunk.map : undefined, `.map` TODO: moved to OutputChunk?
354
366
  presets: [
367
+ // forcing our plugin to run before preset-env by wrapping it in a
368
+ // preset so we can catch the injected import statements...
355
369
  [
356
370
  () => ({
357
371
  plugins: [
@@ -362,7 +376,7 @@ function viteLegacyPlugin(options = {}) {
362
376
  })
363
377
  ],
364
378
  [
365
- "env",
379
+ "@babel/preset-env",
366
380
  createBabelPresetEnvOptions(targets, {
367
381
  needPolyfills,
368
382
  ignoreBrowserslistConfig: options.ignoreBrowserslistConfig
@@ -370,8 +384,8 @@ function viteLegacyPlugin(options = {}) {
370
384
  ]
371
385
  ]
372
386
  });
373
- if (code)
374
- return { code, map };
387
+ if (result)
388
+ return { code: result.code, map: result.map };
375
389
  return null;
376
390
  },
377
391
  transformIndexHtml(html, { chunk }) {
@@ -447,6 +461,9 @@ function viteLegacyPlugin(options = {}) {
447
461
  attrs: {
448
462
  nomodule: true,
449
463
  crossorigin: true,
464
+ // we set the entry path on the element as an attribute so that the
465
+ // script content will stay consistent - which allows using a constant
466
+ // hash value for CSP.
450
467
  id: legacyEntryId,
451
468
  "data-src": toAssetPathFromHtml(
452
469
  legacyEntryFilename,
@@ -462,7 +479,7 @@ function viteLegacyPlugin(options = {}) {
462
479
  `No corresponding legacy entry chunk found for ${htmlFilename}`
463
480
  );
464
481
  }
465
- if (genDynamicFallback && legacyPolyfillFilename && legacyEntryFilename) {
482
+ if (genLegacy && legacyPolyfillFilename && legacyEntryFilename) {
466
483
  tags.push({
467
484
  tag: "script",
468
485
  attrs: { type: "module" },
@@ -487,7 +504,7 @@ function viteLegacyPlugin(options = {}) {
487
504
  }
488
505
  if (isLegacyBundle(bundle, opts)) {
489
506
  for (const name in bundle) {
490
- if (bundle[name].type === "asset") {
507
+ if (bundle[name].type === "asset" && !/.+\.map$/.test(name)) {
491
508
  delete bundle[name];
492
509
  }
493
510
  }
@@ -498,20 +515,20 @@ function viteLegacyPlugin(options = {}) {
498
515
  }
499
516
  async function detectPolyfills(code, targets, list) {
500
517
  const babel2 = await loadBabel();
501
- const { ast } = babel2.transform(code, {
518
+ const result = babel2.transform(code, {
502
519
  ast: true,
503
520
  babelrc: false,
504
521
  configFile: false,
505
522
  presets: [
506
523
  [
507
- "env",
524
+ "@babel/preset-env",
508
525
  createBabelPresetEnvOptions(targets, {
509
526
  ignoreBrowserslistConfig: true
510
527
  })
511
528
  ]
512
529
  ]
513
530
  });
514
- for (const node of ast.program.body) {
531
+ for (const node of result.ast.program.body) {
515
532
  if (node.type === "ImportDeclaration") {
516
533
  const source = node.source.value;
517
534
  if (source.startsWith("core-js/") || source.startsWith("regenerator-runtime/")) {
@@ -543,6 +560,7 @@ async function buildPolyfillChunk(mode, imports, bundle, facadeToChunkMap, build
543
560
  minify = minify ? "terser" : false;
544
561
  const res = await vite.build({
545
562
  mode,
563
+ // so that everything is resolved from here
546
564
  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
565
  configFile: false,
548
566
  logLevel: "error",
@@ -561,9 +579,15 @@ async function buildPolyfillChunk(mode, imports, bundle, facadeToChunkMap, build
561
579
  }
562
580
  }
563
581
  },
582
+ // Don't run esbuild for transpilation or minification
583
+ // because we don't want to transpile code.
564
584
  esbuild: false,
565
585
  optimizeDeps: {
566
586
  esbuildOptions: {
587
+ // If a value above 'es5' is set, esbuild injects helper functions which uses es2015 features.
588
+ // This limits the input code not to include es2015+ codes.
589
+ // But core-js is the only dependency which includes commonjs code
590
+ // and core-js doesn't include es2015+ codes.
567
591
  target: "es5"
568
592
  }
569
593
  }
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 browserslist 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,15 +70,26 @@ 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
  }
92
+ const { loadConfig: browserslistLoadConfig } = browserslist;
77
93
  function toOutputFilePathInHtml(filename, type, hostId, hostType, config, toRelative) {
78
94
  const { renderBuiltUrl } = config.experimental;
79
95
  let relative = config.base === "" || config.base === "./";
@@ -121,21 +137,12 @@ function toAssetPathFromHtml(filename, htmlPath, config) {
121
137
  toRelative
122
138
  );
123
139
  }
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
140
  const legacyEnvVarMarker = `__VITE_IS_LEGACY__`;
133
141
  const _require = createRequire(import.meta.url);
134
142
  function viteLegacyPlugin(options = {}) {
135
143
  let config;
136
- const targets = options.targets || "defaults";
144
+ let targets;
137
145
  const genLegacy = options.renderLegacyChunks !== false;
138
- const genDynamicFallback = genLegacy;
139
146
  const debugFlags = (process.env.DEBUG || "").split(",");
140
147
  const isDebug = debugFlags.includes("vite:*") || debugFlags.includes("vite:legacy");
141
148
  const facadeToLegacyChunkMap = /* @__PURE__ */ new Map();
@@ -184,7 +191,7 @@ function viteLegacyPlugin(options = {}) {
184
191
  "edge79",
185
192
  "firefox67",
186
193
  "chrome64",
187
- "safari11.1"
194
+ "safari12"
188
195
  ];
189
196
  }
190
197
  }
@@ -197,7 +204,7 @@ function viteLegacyPlugin(options = {}) {
197
204
  configResolved(config2) {
198
205
  if (overriddenBuildTarget) {
199
206
  config2.logger.warn(
200
- picocolors.exports.yellow(
207
+ picocolorsExports.yellow(
201
208
  `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
209
  )
203
210
  );
@@ -234,7 +241,7 @@ function viteLegacyPlugin(options = {}) {
234
241
  if (!genLegacy) {
235
242
  return;
236
243
  }
237
- if (legacyPolyfills.size || genDynamicFallback) {
244
+ if (legacyPolyfills.size) {
238
245
  await detectPolyfills(
239
246
  `Promise.resolve(); Promise.all();`,
240
247
  targets,
@@ -249,6 +256,8 @@ function viteLegacyPlugin(options = {}) {
249
256
  legacyPolyfills,
250
257
  bundle,
251
258
  facadeToLegacyPolyfillMap,
259
+ // force using terser for legacy polyfill minification, since esbuild
260
+ // isn't legacy-safe
252
261
  config.build,
253
262
  "iife",
254
263
  opts,
@@ -269,6 +278,8 @@ function viteLegacyPlugin(options = {}) {
269
278
  if (!genLegacy || config.build.ssr) {
270
279
  return;
271
280
  }
281
+ targets = options.targets || browserslistLoadConfig({ path: config.root }) || "last 2 versions and not dead, > 0.3%, Firefox ESR";
282
+ isDebug && console.log(`[@vitejs/plugin-legacy] targets:`, targets);
272
283
  const getLegacyOutputFileName = (fileNames, defaultFileName = "[name]-legacy-[hash].js") => {
273
284
  if (!fileNames) {
274
285
  return path.posix.join(config.build.assetsDir, defaultFileName);
@@ -308,8 +319,8 @@ function viteLegacyPlugin(options = {}) {
308
319
  await detectPolyfills(raw, { esmodules: true }, modernPolyfills);
309
320
  }
310
321
  const ms = new MagicString(raw);
311
- if (genDynamicFallback && chunk.isEntry) {
312
- ms.prepend(forceDynamicImportUsage);
322
+ if (genLegacy && chunk.isEntry) {
323
+ ms.prepend(modernChunkLegacyGuard);
313
324
  }
314
325
  if (raw.includes(legacyEnvVarMarker)) {
315
326
  const re = new RegExp(legacyEnvVarMarker, "g");
@@ -341,13 +352,16 @@ function viteLegacyPlugin(options = {}) {
341
352
  const needPolyfills = options.polyfills !== false && !Array.isArray(options.polyfills);
342
353
  const sourceMaps = !!config.build.sourcemap;
343
354
  const babel2 = await loadBabel();
344
- const { code, map } = babel2.transform(raw, {
355
+ const result = babel2.transform(raw, {
345
356
  babelrc: false,
346
357
  configFile: false,
347
358
  compact: !!config.build.minify,
348
359
  sourceMaps,
349
360
  inputSourceMap: void 0,
361
+ // sourceMaps ? chunk.map : undefined, `.map` TODO: moved to OutputChunk?
350
362
  presets: [
363
+ // forcing our plugin to run before preset-env by wrapping it in a
364
+ // preset so we can catch the injected import statements...
351
365
  [
352
366
  () => ({
353
367
  plugins: [
@@ -358,7 +372,7 @@ function viteLegacyPlugin(options = {}) {
358
372
  })
359
373
  ],
360
374
  [
361
- "env",
375
+ "@babel/preset-env",
362
376
  createBabelPresetEnvOptions(targets, {
363
377
  needPolyfills,
364
378
  ignoreBrowserslistConfig: options.ignoreBrowserslistConfig
@@ -366,8 +380,8 @@ function viteLegacyPlugin(options = {}) {
366
380
  ]
367
381
  ]
368
382
  });
369
- if (code)
370
- return { code, map };
383
+ if (result)
384
+ return { code: result.code, map: result.map };
371
385
  return null;
372
386
  },
373
387
  transformIndexHtml(html, { chunk }) {
@@ -443,6 +457,9 @@ function viteLegacyPlugin(options = {}) {
443
457
  attrs: {
444
458
  nomodule: true,
445
459
  crossorigin: true,
460
+ // we set the entry path on the element as an attribute so that the
461
+ // script content will stay consistent - which allows using a constant
462
+ // hash value for CSP.
446
463
  id: legacyEntryId,
447
464
  "data-src": toAssetPathFromHtml(
448
465
  legacyEntryFilename,
@@ -458,7 +475,7 @@ function viteLegacyPlugin(options = {}) {
458
475
  `No corresponding legacy entry chunk found for ${htmlFilename}`
459
476
  );
460
477
  }
461
- if (genDynamicFallback && legacyPolyfillFilename && legacyEntryFilename) {
478
+ if (genLegacy && legacyPolyfillFilename && legacyEntryFilename) {
462
479
  tags.push({
463
480
  tag: "script",
464
481
  attrs: { type: "module" },
@@ -483,7 +500,7 @@ function viteLegacyPlugin(options = {}) {
483
500
  }
484
501
  if (isLegacyBundle(bundle, opts)) {
485
502
  for (const name in bundle) {
486
- if (bundle[name].type === "asset") {
503
+ if (bundle[name].type === "asset" && !/.+\.map$/.test(name)) {
487
504
  delete bundle[name];
488
505
  }
489
506
  }
@@ -494,20 +511,20 @@ function viteLegacyPlugin(options = {}) {
494
511
  }
495
512
  async function detectPolyfills(code, targets, list) {
496
513
  const babel2 = await loadBabel();
497
- const { ast } = babel2.transform(code, {
514
+ const result = babel2.transform(code, {
498
515
  ast: true,
499
516
  babelrc: false,
500
517
  configFile: false,
501
518
  presets: [
502
519
  [
503
- "env",
520
+ "@babel/preset-env",
504
521
  createBabelPresetEnvOptions(targets, {
505
522
  ignoreBrowserslistConfig: true
506
523
  })
507
524
  ]
508
525
  ]
509
526
  });
510
- for (const node of ast.program.body) {
527
+ for (const node of result.ast.program.body) {
511
528
  if (node.type === "ImportDeclaration") {
512
529
  const source = node.source.value;
513
530
  if (source.startsWith("core-js/") || source.startsWith("regenerator-runtime/")) {
@@ -539,6 +556,7 @@ async function buildPolyfillChunk(mode, imports, bundle, facadeToChunkMap, build
539
556
  minify = minify ? "terser" : false;
540
557
  const res = await build({
541
558
  mode,
559
+ // so that everything is resolved from here
542
560
  root: path.dirname(fileURLToPath(import.meta.url)),
543
561
  configFile: false,
544
562
  logLevel: "error",
@@ -557,9 +575,15 @@ async function buildPolyfillChunk(mode, imports, bundle, facadeToChunkMap, build
557
575
  }
558
576
  }
559
577
  },
578
+ // Don't run esbuild for transpilation or minification
579
+ // because we don't want to transpile code.
560
580
  esbuild: false,
561
581
  optimizeDeps: {
562
582
  esbuildOptions: {
583
+ // If a value above 'es5' is set, esbuild injects helper functions which uses es2015 features.
584
+ // This limits the input code not to include es2015+ codes.
585
+ // But core-js is the only dependency which includes commonjs code
586
+ // and core-js doesn't include es2015+ codes.
563
587
  target: "es5"
564
588
  }
565
589
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vitejs/plugin-legacy",
3
- "version": "3.0.2",
3
+ "version": "4.0.1",
4
4
  "license": "MIT",
5
5
  "author": "Evan You",
6
6
  "files": [
@@ -41,7 +41,9 @@
41
41
  },
42
42
  "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-legacy#readme",
43
43
  "dependencies": {
44
- "@babel/standalone": "^7.20.13",
44
+ "@babel/core": "^7.20.12",
45
+ "@babel/preset-env": "^7.20.2",
46
+ "browserslist": "^4.21.4",
45
47
  "core-js": "^3.27.2",
46
48
  "magic-string": "^0.27.0",
47
49
  "regenerator-runtime": "^0.13.11",
@@ -52,7 +54,7 @@
52
54
  "vite": "^4.0.0"
53
55
  },
54
56
  "devDependencies": {
55
- "@babel/core": "^7.20.12",
57
+ "acorn": "^8.8.2",
56
58
  "picocolors": "^1.0.0",
57
59
  "vite": "workspace:*"
58
60
  }