@vitejs/plugin-legacy 1.8.2 → 2.0.0-alpha.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/dist/index.mjs ADDED
@@ -0,0 +1,471 @@
1
+ import path from 'path';
2
+ import { createHash } from 'crypto';
3
+ import { build } from 'vite';
4
+ import MagicString from 'magic-string';
5
+
6
+ let babel;
7
+ async function loadBabel() {
8
+ if (!babel) {
9
+ babel = await import('@babel/standalone');
10
+ }
11
+ return babel;
12
+ }
13
+ 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()}}();`;
14
+ const legacyPolyfillId = "vite-legacy-polyfill";
15
+ const legacyEntryId = "vite-legacy-entry";
16
+ const systemJSInlineCode = `System.import(document.getElementById('${legacyEntryId}').getAttribute('data-src'))`;
17
+ const detectDynamicImportVarName = "__vite_is_dynamic_import_support";
18
+ const detectDynamicImportCode = `try{import("_").catch(()=>1);}catch(e){}window.${detectDynamicImportVarName}=true;`;
19
+ const dynamicFallbackInlineCode = `!function(){if(window.${detectDynamicImportVarName})return;console.warn("vite: loading legacy build because dynamic import 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)}();`;
20
+ const forceDynamicImportUsage = `export function __vite_legacy_guard(){import('data:text/javascript,')};`;
21
+ const legacyEnvVarMarker = `__VITE_IS_LEGACY__`;
22
+ function viteLegacyPlugin(options = {}) {
23
+ let config;
24
+ const targets = options.targets || "defaults";
25
+ const genLegacy = options.renderLegacyChunks !== false;
26
+ const genDynamicFallback = genLegacy;
27
+ const debugFlags = (process.env.DEBUG || "").split(",");
28
+ const isDebug = debugFlags.includes("vite:*") || debugFlags.includes("vite:legacy");
29
+ const facadeToLegacyChunkMap = /* @__PURE__ */ new Map();
30
+ const facadeToLegacyPolyfillMap = /* @__PURE__ */ new Map();
31
+ const facadeToModernPolyfillMap = /* @__PURE__ */ new Map();
32
+ const modernPolyfills = /* @__PURE__ */ new Set();
33
+ const DEFAULT_LEGACY_POLYFILL = [
34
+ "core-js/modules/es.promise",
35
+ "core-js/modules/es.array.iterator"
36
+ ];
37
+ const legacyPolyfills = new Set(DEFAULT_LEGACY_POLYFILL);
38
+ if (Array.isArray(options.modernPolyfills)) {
39
+ options.modernPolyfills.forEach((i) => {
40
+ modernPolyfills.add(i.includes("/") ? `core-js/${i}` : `core-js/modules/${i}.js`);
41
+ });
42
+ }
43
+ if (Array.isArray(options.polyfills)) {
44
+ options.polyfills.forEach((i) => {
45
+ if (i.startsWith(`regenerator`)) {
46
+ legacyPolyfills.add(`regenerator-runtime/runtime.js`);
47
+ } else {
48
+ legacyPolyfills.add(i.includes("/") ? `core-js/${i}` : `core-js/modules/${i}.js`);
49
+ }
50
+ });
51
+ }
52
+ if (Array.isArray(options.additionalLegacyPolyfills)) {
53
+ options.additionalLegacyPolyfills.forEach((i) => {
54
+ legacyPolyfills.add(i);
55
+ });
56
+ }
57
+ const legacyConfigPlugin = {
58
+ name: "vite:legacy-config",
59
+ apply: "build",
60
+ config(config2) {
61
+ if (!config2.build) {
62
+ config2.build = {};
63
+ }
64
+ if (!config2.build.cssTarget) {
65
+ config2.build.cssTarget = "chrome61";
66
+ }
67
+ }
68
+ };
69
+ const legacyGenerateBundlePlugin = {
70
+ name: "vite:legacy-generate-polyfill-chunk",
71
+ apply: "build",
72
+ async generateBundle(opts, bundle) {
73
+ if (config.build.ssr) {
74
+ return;
75
+ }
76
+ if (!isLegacyBundle(bundle, opts)) {
77
+ if (!modernPolyfills.size) {
78
+ return;
79
+ }
80
+ isDebug && console.log(`[@vitejs/plugin-legacy] modern polyfills:`, modernPolyfills);
81
+ await buildPolyfillChunk("polyfills-modern", modernPolyfills, bundle, facadeToModernPolyfillMap, config.build, options.externalSystemJS);
82
+ return;
83
+ }
84
+ if (!genLegacy) {
85
+ return;
86
+ }
87
+ if (legacyPolyfills.size || genDynamicFallback) {
88
+ if (!legacyPolyfills.has("es.promise")) {
89
+ await detectPolyfills(`Promise.resolve()`, targets, legacyPolyfills);
90
+ }
91
+ isDebug && console.log(`[@vitejs/plugin-legacy] legacy polyfills:`, legacyPolyfills);
92
+ await buildPolyfillChunk("polyfills-legacy", legacyPolyfills, bundle, facadeToLegacyPolyfillMap, config.build, options.externalSystemJS);
93
+ }
94
+ }
95
+ };
96
+ const legacyPostPlugin = {
97
+ name: "vite:legacy-post-process",
98
+ enforce: "post",
99
+ apply: "build",
100
+ configResolved(_config) {
101
+ if (_config.build.lib) {
102
+ throw new Error("@vitejs/plugin-legacy does not support library mode.");
103
+ }
104
+ config = _config;
105
+ if (!genLegacy || config.build.ssr) {
106
+ return;
107
+ }
108
+ const getLegacyOutputFileName = (fileNames, defaultFileName = "[name]-legacy.[hash].js") => {
109
+ if (!fileNames) {
110
+ return path.posix.join(config.build.assetsDir, defaultFileName);
111
+ }
112
+ return (chunkInfo) => {
113
+ let fileName = typeof fileNames === "function" ? fileNames(chunkInfo) : fileNames;
114
+ if (fileName.includes("[name]")) {
115
+ fileName = fileName.replace("[name]", "[name]-legacy");
116
+ } else {
117
+ fileName = fileName.replace(/(.+)\.(.+)/, "$1-legacy.$2");
118
+ }
119
+ return fileName;
120
+ };
121
+ };
122
+ const createLegacyOutput = (options2 = {}) => {
123
+ return {
124
+ ...options2,
125
+ format: "system",
126
+ entryFileNames: getLegacyOutputFileName(options2.entryFileNames),
127
+ chunkFileNames: getLegacyOutputFileName(options2.chunkFileNames)
128
+ };
129
+ };
130
+ const { rollupOptions } = config.build;
131
+ const { output } = rollupOptions;
132
+ if (Array.isArray(output)) {
133
+ rollupOptions.output = [...output.map(createLegacyOutput), ...output];
134
+ } else {
135
+ rollupOptions.output = [createLegacyOutput(output), output || {}];
136
+ }
137
+ },
138
+ async renderChunk(raw, chunk, opts) {
139
+ if (config.build.ssr) {
140
+ return null;
141
+ }
142
+ if (!isLegacyChunk(chunk, opts)) {
143
+ if (options.modernPolyfills && !Array.isArray(options.modernPolyfills)) {
144
+ await detectPolyfills(raw, { esmodules: true }, modernPolyfills);
145
+ }
146
+ const ms = new MagicString(raw);
147
+ if (genDynamicFallback && chunk.isEntry) {
148
+ ms.prepend(forceDynamicImportUsage);
149
+ }
150
+ if (raw.includes(legacyEnvVarMarker)) {
151
+ const re = new RegExp(legacyEnvVarMarker, "g");
152
+ let match;
153
+ while (match = re.exec(raw)) {
154
+ ms.overwrite(match.index, match.index + legacyEnvVarMarker.length, `false`);
155
+ }
156
+ }
157
+ if (config.build.sourcemap) {
158
+ return {
159
+ code: ms.toString(),
160
+ map: ms.generateMap({ hires: true })
161
+ };
162
+ }
163
+ return {
164
+ code: ms.toString()
165
+ };
166
+ }
167
+ if (!genLegacy) {
168
+ return null;
169
+ }
170
+ opts.__vite_skip_esbuild__ = true;
171
+ opts.__vite_force_terser__ = true;
172
+ opts.__vite_skip_asset_emit__ = true;
173
+ const needPolyfills = options.polyfills !== false && !Array.isArray(options.polyfills);
174
+ const sourceMaps = !!config.build.sourcemap;
175
+ const babel2 = await loadBabel();
176
+ const { code, map } = babel2.transform(raw, {
177
+ babelrc: false,
178
+ configFile: false,
179
+ compact: true,
180
+ sourceMaps,
181
+ inputSourceMap: sourceMaps ? chunk.map : void 0,
182
+ presets: [
183
+ [
184
+ () => ({
185
+ plugins: [
186
+ recordAndRemovePolyfillBabelPlugin(legacyPolyfills),
187
+ replaceLegacyEnvBabelPlugin(),
188
+ wrapIIFEBabelPlugin()
189
+ ]
190
+ })
191
+ ],
192
+ [
193
+ "env",
194
+ {
195
+ targets,
196
+ modules: false,
197
+ bugfixes: true,
198
+ loose: false,
199
+ useBuiltIns: needPolyfills ? "usage" : false,
200
+ corejs: needPolyfills ? {
201
+ version: require("core-js/package.json").version,
202
+ proposals: false
203
+ } : void 0,
204
+ shippedProposals: true,
205
+ ignoreBrowserslistConfig: options.ignoreBrowserslistConfig
206
+ }
207
+ ]
208
+ ]
209
+ });
210
+ if (code)
211
+ return { code, map };
212
+ return null;
213
+ },
214
+ transformIndexHtml(html, { chunk }) {
215
+ if (config.build.ssr)
216
+ return;
217
+ if (!chunk)
218
+ return;
219
+ if (chunk.fileName.includes("-legacy")) {
220
+ facadeToLegacyChunkMap.set(chunk.facadeModuleId, chunk.fileName);
221
+ return;
222
+ }
223
+ const tags = [];
224
+ const htmlFilename = chunk.facadeModuleId?.replace(/\?.*$/, "");
225
+ const modernPolyfillFilename = facadeToModernPolyfillMap.get(chunk.facadeModuleId);
226
+ if (modernPolyfillFilename) {
227
+ tags.push({
228
+ tag: "script",
229
+ attrs: {
230
+ type: "module",
231
+ src: `${config.base}${modernPolyfillFilename}`
232
+ }
233
+ });
234
+ } else if (modernPolyfills.size) {
235
+ throw new Error(`No corresponding modern polyfill chunk found for ${htmlFilename}`);
236
+ }
237
+ if (!genLegacy) {
238
+ return { html, tags };
239
+ }
240
+ tags.push({
241
+ tag: "script",
242
+ attrs: { nomodule: true },
243
+ children: safari10NoModuleFix,
244
+ injectTo: "body"
245
+ });
246
+ const legacyPolyfillFilename = facadeToLegacyPolyfillMap.get(chunk.facadeModuleId);
247
+ if (legacyPolyfillFilename) {
248
+ tags.push({
249
+ tag: "script",
250
+ attrs: {
251
+ nomodule: true,
252
+ id: legacyPolyfillId,
253
+ src: `${config.base}${legacyPolyfillFilename}`
254
+ },
255
+ injectTo: "body"
256
+ });
257
+ } else if (legacyPolyfills.size) {
258
+ throw new Error(`No corresponding legacy polyfill chunk found for ${htmlFilename}`);
259
+ }
260
+ const legacyEntryFilename = facadeToLegacyChunkMap.get(chunk.facadeModuleId);
261
+ if (legacyEntryFilename) {
262
+ tags.push({
263
+ tag: "script",
264
+ attrs: {
265
+ nomodule: true,
266
+ id: legacyEntryId,
267
+ "data-src": config.base + legacyEntryFilename
268
+ },
269
+ children: systemJSInlineCode,
270
+ injectTo: "body"
271
+ });
272
+ } else {
273
+ throw new Error(`No corresponding legacy entry chunk found for ${htmlFilename}`);
274
+ }
275
+ if (genDynamicFallback && legacyPolyfillFilename && legacyEntryFilename) {
276
+ tags.push({
277
+ tag: "script",
278
+ attrs: { type: "module" },
279
+ children: detectDynamicImportCode,
280
+ injectTo: "head"
281
+ });
282
+ tags.push({
283
+ tag: "script",
284
+ attrs: { type: "module" },
285
+ children: dynamicFallbackInlineCode,
286
+ injectTo: "head"
287
+ });
288
+ }
289
+ return {
290
+ html,
291
+ tags
292
+ };
293
+ },
294
+ generateBundle(opts, bundle) {
295
+ if (config.build.ssr) {
296
+ return;
297
+ }
298
+ if (isLegacyBundle(bundle, opts)) {
299
+ for (const name in bundle) {
300
+ if (bundle[name].type === "asset") {
301
+ delete bundle[name];
302
+ }
303
+ }
304
+ }
305
+ }
306
+ };
307
+ let envInjectionFailed = false;
308
+ const legacyEnvPlugin = {
309
+ name: "vite:legacy-env",
310
+ config(config2, env) {
311
+ if (env) {
312
+ return {
313
+ define: {
314
+ "import.meta.env.LEGACY": env.command === "serve" || config2.build?.ssr ? false : legacyEnvVarMarker
315
+ }
316
+ };
317
+ } else {
318
+ envInjectionFailed = true;
319
+ }
320
+ },
321
+ configResolved(config2) {
322
+ if (envInjectionFailed) {
323
+ config2.logger.warn(`[@vitejs/plugin-legacy] import.meta.env.LEGACY was not injected due to incompatible vite version (requires vite@^2.0.0-beta.69).`);
324
+ }
325
+ }
326
+ };
327
+ return [
328
+ legacyConfigPlugin,
329
+ legacyGenerateBundlePlugin,
330
+ legacyPostPlugin,
331
+ legacyEnvPlugin
332
+ ];
333
+ }
334
+ async function detectPolyfills(code, targets, list) {
335
+ const babel2 = await loadBabel();
336
+ const { ast } = babel2.transform(code, {
337
+ ast: true,
338
+ babelrc: false,
339
+ configFile: false,
340
+ presets: [
341
+ [
342
+ "env",
343
+ {
344
+ targets,
345
+ modules: false,
346
+ useBuiltIns: "usage",
347
+ corejs: { version: 3, proposals: false },
348
+ shippedProposals: true,
349
+ ignoreBrowserslistConfig: true
350
+ }
351
+ ]
352
+ ]
353
+ });
354
+ for (const node of ast.program.body) {
355
+ if (node.type === "ImportDeclaration") {
356
+ const source = node.source.value;
357
+ if (source.startsWith("core-js/") || source.startsWith("regenerator-runtime/")) {
358
+ list.add(source);
359
+ }
360
+ }
361
+ }
362
+ }
363
+ async function buildPolyfillChunk(name, imports, bundle, facadeToChunkMap, buildOptions, externalSystemJS) {
364
+ let { minify, assetsDir } = buildOptions;
365
+ minify = minify ? "terser" : false;
366
+ const res = await build({
367
+ root: __dirname,
368
+ configFile: false,
369
+ logLevel: "error",
370
+ plugins: [polyfillsPlugin(imports, externalSystemJS)],
371
+ build: {
372
+ write: false,
373
+ target: false,
374
+ minify,
375
+ assetsDir,
376
+ rollupOptions: {
377
+ input: {
378
+ [name]: polyfillId
379
+ },
380
+ output: {
381
+ format: name.includes("legacy") ? "iife" : "es",
382
+ manualChunks: void 0
383
+ }
384
+ }
385
+ }
386
+ });
387
+ const _polyfillChunk = Array.isArray(res) ? res[0] : res;
388
+ if (!("output" in _polyfillChunk))
389
+ return;
390
+ const polyfillChunk = _polyfillChunk.output[0];
391
+ for (const key in bundle) {
392
+ const chunk = bundle[key];
393
+ if (chunk.type === "chunk" && chunk.facadeModuleId) {
394
+ facadeToChunkMap.set(chunk.facadeModuleId, polyfillChunk.fileName);
395
+ }
396
+ }
397
+ bundle[polyfillChunk.name] = polyfillChunk;
398
+ }
399
+ const polyfillId = "\0vite/legacy-polyfills";
400
+ function polyfillsPlugin(imports, externalSystemJS) {
401
+ return {
402
+ name: "vite:legacy-polyfills",
403
+ resolveId(id) {
404
+ if (id === polyfillId) {
405
+ return id;
406
+ }
407
+ },
408
+ load(id) {
409
+ if (id === polyfillId) {
410
+ return [...imports].map((i) => `import "${i}";`).join("") + (externalSystemJS ? "" : `import "systemjs/dist/s.min.js";`);
411
+ }
412
+ }
413
+ };
414
+ }
415
+ function isLegacyChunk(chunk, options) {
416
+ return options.format === "system" && chunk.fileName.includes("-legacy");
417
+ }
418
+ function isLegacyBundle(bundle, options) {
419
+ if (options.format === "system") {
420
+ const entryChunk = Object.values(bundle).find((output) => output.type === "chunk" && output.isEntry);
421
+ return !!entryChunk && entryChunk.fileName.includes("-legacy");
422
+ }
423
+ return false;
424
+ }
425
+ function recordAndRemovePolyfillBabelPlugin(polyfills) {
426
+ return ({ types: t }) => ({
427
+ name: "vite-remove-polyfill-import",
428
+ post({ path: path2 }) {
429
+ path2.get("body").forEach((p) => {
430
+ if (t.isImportDeclaration(p)) {
431
+ polyfills.add(p.node.source.value);
432
+ p.remove();
433
+ }
434
+ });
435
+ }
436
+ });
437
+ }
438
+ function replaceLegacyEnvBabelPlugin() {
439
+ return ({ types: t }) => ({
440
+ name: "vite-replace-env-legacy",
441
+ visitor: {
442
+ Identifier(path2) {
443
+ if (path2.node.name === legacyEnvVarMarker) {
444
+ path2.replaceWith(t.booleanLiteral(true));
445
+ }
446
+ }
447
+ }
448
+ });
449
+ }
450
+ function wrapIIFEBabelPlugin() {
451
+ return ({ types: t, template }) => {
452
+ const buildIIFE = template(";(function(){%%body%%})();");
453
+ return {
454
+ name: "vite-wrap-iife",
455
+ post({ path: path2 }) {
456
+ if (!this.isWrapped) {
457
+ this.isWrapped = true;
458
+ path2.replaceWith(t.program(buildIIFE({ body: path2.node.body })));
459
+ }
460
+ }
461
+ };
462
+ };
463
+ }
464
+ const cspHashes = [
465
+ createHash("sha256").update(safari10NoModuleFix).digest("base64"),
466
+ createHash("sha256").update(systemJSInlineCode).digest("base64"),
467
+ createHash("sha256").update(detectDynamicImportCode).digest("base64"),
468
+ createHash("sha256").update(dynamicFallbackInlineCode).digest("base64")
469
+ ];
470
+
471
+ export { cspHashes, viteLegacyPlugin as default, detectPolyfills };
package/package.json CHANGED
@@ -1,16 +1,29 @@
1
1
  {
2
2
  "name": "@vitejs/plugin-legacy",
3
- "version": "1.8.2",
3
+ "version": "2.0.0-alpha.0",
4
4
  "license": "MIT",
5
5
  "author": "Evan You",
6
6
  "files": [
7
- "index.js",
8
- "index.d.ts"
7
+ "dist"
9
8
  ],
10
- "main": "index.js",
11
- "types": "index.d.ts",
9
+ "main": "./dist/index.cjs",
10
+ "module": "./dist/index.mjs",
11
+ "types": "./dist/index.d.ts",
12
+ "exports": {
13
+ ".": {
14
+ "types": "./dist/index.d.ts",
15
+ "import": "./dist/index.mjs",
16
+ "require": "./dist/index.cjs"
17
+ }
18
+ },
19
+ "scripts": {
20
+ "dev": "unbuild --stub",
21
+ "build": "unbuild && pnpm run patch-cjs",
22
+ "patch-cjs": "ts-node ../../scripts/patchCJS.ts",
23
+ "prepublishOnly": "npm run build"
24
+ },
12
25
  "engines": {
13
- "node": ">=12.0.0"
26
+ "node": ">=14.6.0"
14
27
  },
15
28
  "repository": {
16
29
  "type": "git",
@@ -23,12 +36,16 @@
23
36
  "homepage": "https://github.com/vitejs/vite/tree/main/packages/plugin-legacy#readme",
24
37
  "dependencies": {
25
38
  "@babel/standalone": "^7.17.11",
26
- "core-js": "^3.22.3",
39
+ "core-js": "^3.22.4",
27
40
  "magic-string": "^0.26.1",
28
41
  "regenerator-runtime": "^0.13.9",
29
42
  "systemjs": "^6.12.1"
30
43
  },
31
44
  "peerDependencies": {
32
- "vite": "^2.8.0"
45
+ "vite": "^3.0.0-alpha"
46
+ },
47
+ "devDependencies": {
48
+ "vite": "workspace:*",
49
+ "@babel/core": "^7.17.10"
33
50
  }
34
51
  }
package/index.d.ts DELETED
@@ -1,35 +0,0 @@
1
- import type { Plugin } from 'vite'
2
-
3
- export interface Options {
4
- /**
5
- * default: 'defaults'
6
- */
7
- targets?: string | string[] | { [key: string]: string }
8
- /**
9
- * default: false
10
- */
11
- ignoreBrowserslistConfig?: boolean
12
- /**
13
- * default: true
14
- */
15
- polyfills?: boolean | string[]
16
- additionalLegacyPolyfills?: string[]
17
- /**
18
- * default: false
19
- */
20
- modernPolyfills?: boolean | string[]
21
- /**
22
- * default: true
23
- */
24
- renderLegacyChunks?: boolean
25
- /**
26
- * default: false
27
- */
28
- externalSystemJS?: boolean
29
- }
30
-
31
- declare function createPlugin(options?: Options): Plugin
32
-
33
- export default createPlugin
34
-
35
- export const cspHashes: string[]