From 3e2707122033a5be074d88dbeb244526dee85bb9 Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Fri, 14 Jun 2024 14:43:14 +0800 Subject: [PATCH] fix(build): handle preload treeshaking for commas (#17472) --- .../src/node/plugins/importAnalysisBuild.ts | 27 +++++++++---------- .../__tests__/dynamic-import.spec.ts | 6 +++++ playground/dynamic-import/nested/index.js | 26 +++++++++++++++--- .../nested/treeshaken/syntax.js | 6 +++++ .../nested/treeshaken/treeshaken.js | 3 +++ 5 files changed, 50 insertions(+), 18 deletions(-) create mode 100644 playground/dynamic-import/nested/treeshaken/syntax.js diff --git a/packages/vite/src/node/plugins/importAnalysisBuild.ts b/packages/vite/src/node/plugins/importAnalysisBuild.ts index 3386b1a5a4948b..fcf92bebd8b10f 100644 --- a/packages/vite/src/node/plugins/importAnalysisBuild.ts +++ b/packages/vite/src/node/plugins/importAnalysisBuild.ts @@ -42,7 +42,7 @@ const preloadMarkerRE = new RegExp(preloadMarker, 'g') const dynamicImportPrefixRE = /import\s*\(/ const dynamicImportTreeshakenRE = - /(\b(const|let|var)\s+(\{[^}.]+\})\s*=\s*await\s+import\([^)]+\))|(\(\s*await\s+import\([^)]+\)\s*\)(\??\.[^;[\s]+)+)|\bimport\([^)]+\)(\s*\.then\([^{]*?\(\s*\{([^}.]+)\})/g + /((?:\bconst\s+|\blet\s+|\bvar\s+|,\s*)(\{[^}.]+\})\s*=\s*await\s+import\([^)]+\))|(\(\s*await\s+import\([^)]+\)\s*\)(\??\.[\w$]+))|\bimport\([^)]+\)(\s*\.then\([^{]*?\(\s*\{([^}.]+)\})/g function toRelativePath(filename: string, importer: string) { const relPath = path.posix.relative(path.posix.dirname(importer), filename) @@ -252,48 +252,47 @@ export function buildImportAnalysisPlugin(config: ResolvedConfig): Plugin { /* handle `const {foo} = await import('foo')` * * match[1]: `const {foo} = await import('foo')` - * match[2]: `const` - * match[3]: `{foo}` + * match[2]: `{foo}` * import end: `const {foo} = await import('foo')_` * ^ */ if (match[1]) { dynamicImports[dynamicImportTreeshakenRE.lastIndex] = { - declaration: `${match[2]} ${match[3]}`, - names: match[3]?.trim(), + declaration: `const ${match[2]}`, + names: match[2]?.trim(), } continue } /* handle `(await import('foo')).foo` * - * match[4]: `(await import('foo')).foo` - * match[5]: `.foo` + * match[3]: `(await import('foo')).foo` + * match[4]: `.foo` * import end: `(await import('foo'))` * ^ */ - if (match[4]) { - let names = match[5].match(/\.([^.?]+)/)?.[1] || '' + if (match[3]) { + let names = match[4].match(/\.([^.?]+)/)?.[1] || '' // avoid `default` keyword error if (names === 'default') { names = 'default: __vite_default__' } dynamicImports[ - dynamicImportTreeshakenRE.lastIndex - match[5]?.length - 1 + dynamicImportTreeshakenRE.lastIndex - match[4]?.length - 1 ] = { declaration: `const {${names}}`, names: `{ ${names} }` } continue } /* handle `import('foo').then(({foo})=>{})` * - * match[6]: `.then(({foo}` - * match[7]: `foo` + * match[5]: `.then(({foo}` + * match[6]: `foo` * import end: `import('foo').` * ^ */ - const names = match[7]?.trim() + const names = match[6]?.trim() dynamicImports[ - dynamicImportTreeshakenRE.lastIndex - match[6]?.length + dynamicImportTreeshakenRE.lastIndex - match[5]?.length ] = { declaration: `const {${names}}`, names: `{ ${names} }` } } } diff --git a/playground/dynamic-import/__tests__/dynamic-import.spec.ts b/playground/dynamic-import/__tests__/dynamic-import.spec.ts index 217211eb85d286..b94b712de37c3e 100644 --- a/playground/dynamic-import/__tests__/dynamic-import.spec.ts +++ b/playground/dynamic-import/__tests__/dynamic-import.spec.ts @@ -193,6 +193,12 @@ test('dynamic import treeshaken log', async () => { expect(log).not.toContain('treeshaken removed') }) +test('dynamic import syntax parsing', async () => { + const log = browserLogs.join('\n') + expect(log).toContain('treeshaken syntax foo') + expect(log).toContain('treeshaken syntax default') +}) + test.runIf(isBuild)('dynamic import treeshaken file', async () => { expect(findAssetFile(/treeshaken.+\.js$/)).not.toContain('treeshaken removed') }) diff --git a/playground/dynamic-import/nested/index.js b/playground/dynamic-import/nested/index.js index 175dd3969d6d7f..8357cbc7afca42 100644 --- a/playground/dynamic-import/nested/index.js +++ b/playground/dynamic-import/nested/index.js @@ -138,6 +138,7 @@ import(`../nested/nested/${base}.js`).then((mod) => { ;(async function () { const { foo } = await import('./treeshaken/treeshaken.js') const { bar, default: tree } = await import('./treeshaken/treeshaken.js') + const default2 = (await import('./treeshaken/treeshaken.js')).default const baz1 = (await import('./treeshaken/treeshaken.js')).baz1 const baz2 = (await import('./treeshaken/treeshaken.js')).baz2.log const baz3 = (await import('./treeshaken/treeshaken.js')).baz3?.log @@ -145,18 +146,35 @@ import(`../nested/nested/${base}.js`).then((mod) => { ({ baz4 }) => baz4, ) const baz5 = await import('./treeshaken/treeshaken.js').then(function ({ - baz5, - }) { - return baz5 - }) + baz5, + }) { + return baz5 + }), + { baz6 } = await import('./treeshaken/treeshaken.js') foo() bar() tree() + ;(await import('./treeshaken/treeshaken.js')).default() + default2() baz1() baz2() baz3() baz4() baz5() + baz6() +})() +// Test syntax parsing only +;(async function () { + const default1 = await import('./treeshaken/syntax.js').then( + (mod) => mod.default, + ) + const default2 = (await import('./treeshaken/syntax.js')).default, + other = () => {} + const foo = await import('./treeshaken/syntax.js').then((mod) => mod.foo) + default1() + default2() + other() + foo() })() import(`../nested/static.js`).then((mod) => { diff --git a/playground/dynamic-import/nested/treeshaken/syntax.js b/playground/dynamic-import/nested/treeshaken/syntax.js new file mode 100644 index 00000000000000..7ee55ddefc403d --- /dev/null +++ b/playground/dynamic-import/nested/treeshaken/syntax.js @@ -0,0 +1,6 @@ +export const foo = () => { + console.log('treeshaken syntax foo') +} +export default () => { + console.log('treeshaken syntax default') +} diff --git a/playground/dynamic-import/nested/treeshaken/treeshaken.js b/playground/dynamic-import/nested/treeshaken/treeshaken.js index f56824fc996240..3fdc9ae7a7808f 100644 --- a/playground/dynamic-import/nested/treeshaken/treeshaken.js +++ b/playground/dynamic-import/nested/treeshaken/treeshaken.js @@ -23,6 +23,9 @@ export const baz4 = () => { export const baz5 = () => { console.log('treeshaken baz5') } +export const baz6 = () => { + console.log('treeshaken baz6') +} export const removed = () => { console.log('treeshaken removed') }