diff --git a/packages/playground/legacy/__tests__/legacy.spec.ts b/packages/playground/legacy/__tests__/legacy.spec.ts index 787f2168cfc8ec..7263174e84b074 100644 --- a/packages/playground/legacy/__tests__/legacy.spec.ts +++ b/packages/playground/legacy/__tests__/legacy.spec.ts @@ -1,4 +1,4 @@ -import { isBuild } from '../../testUtils' +import { isBuild, untilUpdated } from '../../testUtils' test('should work', async () => { expect(await page.textContent('#app')).toMatch('Hello') @@ -18,3 +18,29 @@ test('wraps with iife', async () => { 'exposed babel helpers: false' ) }) + +test('generates assets', async () => { + await untilUpdated( + () => page.textContent('#assets'), + isBuild + ? [ + 'index: 404', + 'index-legacy: 404', + 'chunk-async: 404', + 'chunk-async-legacy: 404', + 'immutable-chunk: 200', + 'immutable-chunk-legacy: 200', + 'polyfills-legacy: 404' + ].join('\n') + : [ + 'index: 404', + 'index-legacy: 404', + 'chunk-async: 404', + 'chunk-async-legacy: 404', + 'immutable-chunk: 404', + 'immutable-chunk-legacy: 404', + 'polyfills-legacy: 404' + ].join('\n'), + true + ) +}) diff --git a/packages/playground/legacy/immutable-chunk.js b/packages/playground/legacy/immutable-chunk.js new file mode 100644 index 00000000000000..4227b718b98309 --- /dev/null +++ b/packages/playground/legacy/immutable-chunk.js @@ -0,0 +1,18 @@ +const chunks = [ + 'index', + 'index-legacy', + 'chunk-async', + 'chunk-async-legacy', + 'immutable-chunk', + 'immutable-chunk-legacy', + 'polyfills-legacy' +] + +export function fn() { + return Promise.all( + chunks.map(async (name) => { + const response = await fetch(`/assets/${name}.js`) + return `${name}: ${response.status}` + }) + ) +} diff --git a/packages/playground/legacy/index.html b/packages/playground/legacy/index.html index 0dcb9a6c4b2665..bdc2feac6b4fbe 100644 --- a/packages/playground/legacy/index.html +++ b/packages/playground/legacy/index.html @@ -2,4 +2,5 @@
+ diff --git a/packages/playground/legacy/main.js b/packages/playground/legacy/main.js index 78322d69455af0..dc458c199b8754 100644 --- a/packages/playground/legacy/main.js +++ b/packages/playground/legacy/main.js @@ -27,6 +27,13 @@ text( String.raw`exposed babel helpers: ${window._templateObject != null}` ) +// dynamic chunk names +import('./immutable-chunk.js') + .then(({ fn }) => fn()) + .then((assets) => { + text('#assets', assets.join('\n')) + }) + function text(el, text) { document.querySelector(el).textContent = text } diff --git a/packages/playground/legacy/vite.config.js b/packages/playground/legacy/vite.config.js index d4a5e4bd481b84..a8fc762cd501a4 100644 --- a/packages/playground/legacy/vite.config.js +++ b/packages/playground/legacy/vite.config.js @@ -11,7 +11,19 @@ module.exports = { build: { // make tests faster - minify: false + minify: false, + + rollupOptions: { + output: { + chunkFileNames(chunkInfo) { + if (chunkInfo.name === 'immutable-chunk') { + return `assets/${chunkInfo.name}.js` + } + + return `assets/chunk-[name].[hash].js` + } + } + } }, // special test only hook diff --git a/packages/plugin-legacy/index.js b/packages/plugin-legacy/index.js index d2ae6fb8f9d809..44d1bbc4e00ebc 100644 --- a/packages/plugin-legacy/index.js +++ b/packages/plugin-legacy/index.js @@ -99,7 +99,7 @@ function viteLegacyPlugin(options = {}) { }, async generateBundle(opts, bundle) { - if (!isLegacyOutput(opts)) { + if (!isLegacyBundle(bundle, opts)) { if (!modernPolyfills.size) { return } @@ -168,8 +168,9 @@ function viteLegacyPlugin(options = {}) { } /** - * @param {string|((chunkInfo: import('rollup').PreRenderedChunk)=>string)} fileNames + * @param {string | ((chunkInfo: import('rollup').PreRenderedChunk) => string)} fileNames * @param {string?} defaultFileName + * @returns {(chunkInfo: import('rollup').PreRenderedChunk) => string)} */ const getLegacyOutputFileName = ( fileNames, @@ -179,21 +180,20 @@ function viteLegacyPlugin(options = {}) { return path.posix.join(config.build.assetsDir, defaultFileName) } - // does not support custom functions. - if (typeof fileNames === 'function') { - throw new Error( - `@vitejs/plugin-legacy rollupOptions.output.entryFileNames and rollupOptions.output.chunkFileNames` + - ` does not support the function format.` - ) - } + return (chunkInfo) => { + let fileName = + typeof fileNames === 'function' ? fileNames(chunkInfo) : fileNames - let fileName = defaultFileName - // Custom string file return format. - if (fileNames && typeof fileNames === 'string') { - fileName = fileNames.replace(/\[name\]/, '[name]-legacy') - } + if (fileName.includes('[name]')) { + // [name]-[hash].[format] -> [name]-legacy-[hash].[format] + fileName = fileName.replace('[name]', '[name]-legacy') + } else { + // entry.js -> entry-legacy.js + fileName = fileName.replace(/(.+)\.(.+)/, '$1-legacy.$2') + } - return fileName + return fileName + } } /** @@ -219,7 +219,7 @@ function viteLegacyPlugin(options = {}) { }, renderChunk(raw, chunk, opts) { - if (!isLegacyOutput(opts)) { + if (!isLegacyChunk(chunk, opts)) { if ( options.modernPolyfills && !Array.isArray(options.modernPolyfills) @@ -399,7 +399,7 @@ function viteLegacyPlugin(options = {}) { }, generateBundle(opts, bundle) { - if (isLegacyOutput(opts)) { + if (isLegacyBundle(bundle, opts)) { // avoid emitting duplicate assets for (const name in bundle) { if (bundle[name].type === 'asset') { @@ -564,14 +564,27 @@ function polyfillsPlugin(imports) { } /** + * @param {import('rollup').RenderedChunk} chunk * @param {import('rollup').NormalizedOutputOptions} options */ -function isLegacyOutput(options) { - return ( - options.format === 'system' && - typeof options.entryFileNames === 'string' && - options.entryFileNames.includes('-legacy') - ) +function isLegacyChunk(chunk, options) { + return options.format === 'system' && chunk.fileName.includes('-legacy') +} + +/** + * @param {import('rollup').OutputBundle} bundle + * @param {import('rollup').NormalizedOutputOptions} options + */ +function isLegacyBundle(bundle, options) { + if (options.format === 'system') { + const entryChunk = Object.values(bundle).find( + (output) => output.type === 'chunk' && output.isEntry + ) + + return !!entryChunk && entryChunk.fileName.includes('-legacy') + } + + return false } /**