From 96502622f2c8d32c4f5c7826e9aa7ddec149b74b Mon Sep 17 00:00:00 2001 From: Hiroshi Ogawa Date: Mon, 6 Jan 2025 18:38:44 +0900 Subject: [PATCH] wip: support plugin-legacy --- packages/plugin-legacy/package.json | 2 + packages/plugin-legacy/src/index.ts | 67 +++++++++++++++++++++-------- playground/legacy/vite.config.js | 1 + pnpm-lock.yaml | 6 +++ 4 files changed, 57 insertions(+), 19 deletions(-) diff --git a/packages/plugin-legacy/package.json b/packages/plugin-legacy/package.json index a4988b0bea2918..cb6f25a1599ae1 100644 --- a/packages/plugin-legacy/package.json +++ b/packages/plugin-legacy/package.json @@ -42,6 +42,8 @@ "funding": "https://github.com/vitejs/vite?sponsor=1", "dependencies": { "@babel/core": "^7.26.0", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", "@babel/preset-env": "^7.26.0", "browserslist": "^4.24.3", "browserslist-to-esbuild": "^2.1.1", diff --git a/packages/plugin-legacy/src/index.ts b/packages/plugin-legacy/src/index.ts index d356793b231c72..da1651751f5806 100644 --- a/packages/plugin-legacy/src/index.ts +++ b/packages/plugin-legacy/src/index.ts @@ -17,6 +17,7 @@ import type { OutputBundle, OutputChunk, OutputOptions, + PluginContext, PreRenderedChunk, RenderedChunk, } from 'rollup' @@ -174,6 +175,7 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { const legacyPolyfills = new Set() // When discovering polyfills in `renderChunk`, the hook may be non-deterministic, so we group the // modern and legacy polyfills in a sorted chunks map for each rendered outputs before merging them. + // TODO: options object is not identical, so Map won't work const outputToChunkFileNameToPolyfills = new WeakMap< NormalizedOutputOptions, Map; legacy: Set }> | null @@ -282,13 +284,14 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { return } - const chunkFileNameToPolyfills = - outputToChunkFileNameToPolyfills.get(opts) - if (chunkFileNameToPolyfills == null) { - throw new Error( - 'Internal @vitejs/plugin-legacy error: discovered polyfills should exist', - ) - } + // const chunkFileNameToPolyfills = + // outputToChunkFileNameToPolyfills.get(opts) + // if (chunkFileNameToPolyfills == null) { + // throw new Error( + // 'Internal @vitejs/plugin-legacy error: discovered polyfills should exist', + // ) + // } + const chunkFileNameToPolyfills = new Map() if (!isLegacyBundle(bundle, opts)) { // Merge discovered modern polyfills to `modernPolyfills` @@ -305,6 +308,7 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { ) } await buildPolyfillChunk( + this, config.mode, modernPolyfills, bundle, @@ -347,6 +351,7 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { } await buildPolyfillChunk( + this, config.mode, legacyPolyfills, bundle, @@ -434,7 +439,9 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { ): OutputOptions => { return { ...options, - format: 'system', + // TODO + format: 'esm', + // format: 'system', entryFileNames: getLegacyOutputFileName(options.entryFileNames), chunkFileNames: getLegacyOutputFileName(options.chunkFileNames), } @@ -455,7 +462,8 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { } }, - async renderChunk(raw, chunk, opts, { chunks }) { + // TODO: meta.chunks not supported + async renderChunk(raw, chunk, opts, { chunks } = { chunks: {} }) { if (config.build.ssr) { return null } @@ -472,11 +480,15 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { } outputToChunkFileNameToPolyfills.set(opts, chunkFileNameToPolyfills) } - const polyfillsDiscovered = chunkFileNameToPolyfills.get(chunk.fileName) - if (polyfillsDiscovered == null) { - throw new Error( - `Internal @vitejs/plugin-legacy error: discovered polyfills for ${chunk.fileName} should exist`, - ) + // const polyfillsDiscovered = chunkFileNameToPolyfills.get(chunk.fileName) + // if (polyfillsDiscovered == null) { + // throw new Error( + // `Internal @vitejs/plugin-legacy error: discovered polyfills for ${chunk.fileName} should exist`, + // ) + // } + const polyfillsDiscovered = { + modern: new Set(), + legacy: new Set(), } if (!isLegacyChunk(chunk, opts)) { @@ -545,6 +557,12 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { // transform the legacy chunk with @babel/preset-env const sourceMaps = !!config.build.sourcemap const babel = await loadBabel() + const systemJsPlugins = [ + // @ts-ignore + (await import('@babel/plugin-transform-dynamic-import')).default, + // @ts-ignore + (await import('@babel/plugin-transform-modules-systemjs')).default, + ] const result = babel.transform(raw, { babelrc: false, configFile: false, @@ -557,6 +575,7 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { [ () => ({ plugins: [ + ...systemJsPlugins, recordAndRemovePolyfillBabelPlugin(polyfillsDiscovered.legacy), replaceLegacyEnvBabelPlugin(), wrapIIFEBabelPlugin(), @@ -718,7 +737,8 @@ function viteLegacyPlugin(options: Options = {}): Plugin[] { // avoid emitting duplicate assets for (const name in bundle) { if (bundle[name].type === 'asset' && !/.+\.map$/.test(name)) { - delete bundle[name] + // TODO: don't delete polyfil chunk emitted as asset + // delete bundle[name] } } } @@ -781,6 +801,7 @@ function createBabelPresetEnvOptions( } async function buildPolyfillChunk( + ctx: PluginContext, mode: string, imports: Set, bundle: OutputBundle, @@ -846,8 +867,15 @@ async function buildPolyfillChunk( } } + // TODO: adding a whole new chunk to `bundle` is not supported by rolldown. + // can we use `emitFile(asset)` instead? + ctx.emitFile({ + type: 'asset', + fileName: polyfillChunk.fileName, + source: polyfillChunk.code, + }) // add the chunk to the bundle - bundle[polyfillChunk.fileName] = polyfillChunk + // bundle[polyfillChunk.fileName] = polyfillChunk if (polyfillChunk.sourcemapFileName) { const polyfillChunkMapAsset = _polyfillChunk.output.find( (chunk) => @@ -855,7 +883,7 @@ async function buildPolyfillChunk( chunk.fileName === polyfillChunk.sourcemapFileName, ) as OutputAsset | undefined if (polyfillChunkMapAsset) { - bundle[polyfillChunk.sourcemapFileName] = polyfillChunkMapAsset + // bundle[polyfillChunk.sourcemapFileName] = polyfillChunkMapAsset } } } @@ -907,14 +935,15 @@ function prependModenChunkLegacyGuardPlugin(): Plugin { } function isLegacyChunk(chunk: RenderedChunk, options: NormalizedOutputOptions) { - return options.format === 'system' && chunk.fileName.includes('-legacy') + return chunk.fileName.includes('-legacy') + // return options.format === 'system' && chunk.fileName.includes('-legacy') } function isLegacyBundle( bundle: OutputBundle, options: NormalizedOutputOptions, ) { - if (options.format === 'system') { + if (true || options.format === 'system') { const entryChunk = Object.values(bundle).find( (output) => output.type === 'chunk' && output.isEntry, ) diff --git a/playground/legacy/vite.config.js b/playground/legacy/vite.config.js index d07d295a0a27d8..8f2a52154c310b 100644 --- a/playground/legacy/vite.config.js +++ b/playground/legacy/vite.config.js @@ -13,6 +13,7 @@ export default defineConfig({ ], build: { + minify: false, cssCodeSplit: false, manifest: true, sourcemap: true, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2b04cd0b85c29d..eb52107f40a81c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -186,6 +186,12 @@ importers: '@babel/core': specifier: ^7.26.0 version: 7.26.0 + '@babel/plugin-transform-dynamic-import': + specifier: ^7.25.9 + version: 7.25.9(@babel/core@7.26.0) + '@babel/plugin-transform-modules-systemjs': + specifier: ^7.25.9 + version: 7.25.9(@babel/core@7.26.0) '@babel/preset-env': specifier: ^7.26.0 version: 7.26.0(@babel/core@7.26.0)