Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(build): handle preload treeshaking for commas #17472

Merged
merged 1 commit into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 13 additions & 14 deletions packages/vite/src/node/plugins/importAnalysisBuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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} }` }
}
}
Expand Down
6 changes: 6 additions & 0 deletions playground/dynamic-import/__tests__/dynamic-import.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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')
})
Expand Down
26 changes: 22 additions & 4 deletions playground/dynamic-import/nested/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,25 +138,43 @@ 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
const baz4 = await import('./treeshaken/treeshaken.js').then(
({ 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) => {
Expand Down
6 changes: 6 additions & 0 deletions playground/dynamic-import/nested/treeshaken/syntax.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export const foo = () => {
console.log('treeshaken syntax foo')
}
export default () => {
console.log('treeshaken syntax default')
}
3 changes: 3 additions & 0 deletions playground/dynamic-import/nested/treeshaken/treeshaken.js
Original file line number Diff line number Diff line change
Expand Up @@ -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')
}
Expand Down