Skip to content

Commit 88b001b

Browse files
authoredNov 24, 2022
fix: preserve default export from externalized packages (fixes #10258) (#10406)
fixes #10258
1 parent d6b4ee5 commit 88b001b

File tree

15 files changed

+119
-55
lines changed

15 files changed

+119
-55
lines changed
 

‎packages/vite/src/node/optimizer/esbuildDepPlugin.ts

+31-11
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ const externalWithConversionNamespace =
1616
'vite:dep-pre-bundle:external-conversion'
1717
const convertedExternalPrefix = 'vite-dep-pre-bundle-external:'
1818

19+
const cjsExternalFacadeNamespace = 'vite:cjs-external-facade'
20+
const nonFacadePrefix = 'vite-cjs-external-facade:'
21+
1922
const externalTypes = [
2023
'css',
2124
// supported pre-processor types
@@ -268,19 +271,36 @@ export function esbuildCjsExternalPlugin(externals: string[]): Plugin {
268271
`^${text.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&')}$`
269272
const filter = new RegExp(externals.map(escape).join('|'))
270273

271-
build.onResolve({ filter: /.*/, namespace: 'external' }, (args) => ({
272-
path: args.path,
273-
external: true
274-
}))
274+
build.onResolve({ filter: new RegExp(`^${nonFacadePrefix}`) }, (args) => {
275+
return {
276+
path: args.path.slice(nonFacadePrefix.length),
277+
external: true
278+
}
279+
})
280+
281+
build.onResolve({ filter }, (args) => {
282+
if (args.kind === 'require-call') {
283+
return {
284+
path: args.path,
285+
namespace: cjsExternalFacadeNamespace
286+
}
287+
}
275288

276-
build.onResolve({ filter }, (args) => ({
277-
path: args.path,
278-
namespace: 'external'
279-
}))
289+
return {
290+
path: args.path,
291+
external: true
292+
}
293+
})
280294

281-
build.onLoad({ filter: /.*/, namespace: 'external' }, (args) => ({
282-
contents: `export * from ${JSON.stringify(args.path)}`
283-
}))
295+
build.onLoad(
296+
{ filter: /.*/, namespace: cjsExternalFacadeNamespace },
297+
(args) => ({
298+
contents:
299+
`import * as m from ${JSON.stringify(
300+
nonFacadePrefix + args.path
301+
)};` + `module.exports = m;`
302+
})
303+
)
284304
}
285305
}
286306
}

‎playground/external/__tests__/external.spec.ts

+6
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ test('importmap', () => {
77
)
88
})
99

10+
test('should have default exports', async () => {
11+
expect(await page.textContent('#imported-slash5-exists')).toBe('true')
12+
expect(await page.textContent('#imported-slash3-exists')).toBe('true')
13+
expect(await page.textContent('#required-slash3-exists')).toBe('true')
14+
})
15+
1016
describe.runIf(isBuild)('build', () => {
1117
test('should externalize imported packages', async () => {
1218
// If `vue` is successfully externalized, the page should use the version from the import map

‎playground/external/dep-that-imports-vue/index.js

-3
This file was deleted.

‎playground/external/dep-that-imports-vue/package.json

-8
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { version } from 'vue'
2+
import slash5 from 'slash5'
3+
import slash3 from 'slash3'
4+
5+
document.querySelector('#imported-vue-version').textContent = version
6+
document.querySelector('#imported-slash5-exists').textContent =
7+
!!slash5('foo/bar')
8+
document.querySelector('#imported-slash3-exists').textContent =
9+
!!slash3('foo/bar')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "@vitejs/dep-that-imports",
3+
"private": true,
4+
"version": "0.0.0",
5+
"dependencies": {
6+
"slash3": "npm:slash@^3.0.0",
7+
"slash5": "npm:slash@^5.0.0",
8+
"vue": "^3.2.45"
9+
}
10+
}

‎playground/external/dep-that-requires-vue/index.js

-3
This file was deleted.

‎playground/external/dep-that-requires-vue/package.json

-8
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
const { version } = require('vue')
2+
// require('slash5') // cannot require ESM
3+
const slash3 = require('slash3')
4+
5+
document.querySelector('#required-vue-version').textContent = version
6+
document.querySelector('#required-slash3-exists').textContent =
7+
!!slash3('foo/bar')
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"name": "@vitejs/dep-that-requires",
3+
"private": true,
4+
"version": "0.0.0",
5+
"dependencies": {
6+
"slash3": "npm:slash@^3.0.0",
7+
"slash5": "npm:slash@^5.0.0",
8+
"vue": "^3.2.45"
9+
}
10+
}

‎playground/external/index.html

+6-1
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,19 @@
77
<script type="importmap">
88
{
99
"imports": {
10-
"vue": "https://unpkg.com/vue@3.2.0/dist/vue.runtime.esm-browser.js"
10+
"vue": "https://unpkg.com/vue@3.2.0/dist/vue.runtime.esm-browser.js",
11+
"slash5": "https://unpkg.com/slash@5.0.0/index.js",
12+
"slash3": "https://esm.sh/slash@3.0.0"
1113
}
1214
}
1315
</script>
1416
</head>
1517
<body>
1618
<p>Imported Vue version: <span id="imported-vue-version"></span></p>
1719
<p>Required Vue version: <span id="required-vue-version"></span></p>
20+
<p>Imported slash5 exists: <span id="imported-slash5-exists"></span></p>
21+
<p>Imported slash3 exists: <span id="imported-slash3-exists"></span></p>
22+
<p>Required slash3 exists: <span id="required-slash3-exists"></span></p>
1823
<script type="module" src="/src/main.js"></script>
1924
</body>
2025
</html>

‎playground/external/package.json

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@
99
"preview": "vite preview"
1010
},
1111
"dependencies": {
12-
"@vitejs/dep-that-imports-vue": "file:./dep-that-imports-vue",
13-
"@vitejs/dep-that-requires-vue": "file:./dep-that-requires-vue"
12+
"@vitejs/dep-that-imports": "file:./dep-that-imports",
13+
"@vitejs/dep-that-requires": "file:./dep-that-requires"
1414
},
1515
"devDependencies": {
16+
"slash3": "npm:slash@^3.0.0",
17+
"slash5": "npm:slash@^5.0.0",
1618
"vite": "workspace:*",
1719
"vue": "^3.2.45"
1820
}

‎playground/external/src/main.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
import '@vitejs/dep-that-imports-vue'
2-
import '@vitejs/dep-that-requires-vue'
1+
import '@vitejs/dep-that-imports'
2+
import '@vitejs/dep-that-requires'

‎playground/external/vite.config.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import { defineConfig } from 'vite'
22

33
export default defineConfig({
4+
optimizeDeps: {
5+
include: ['dep-that-imports', 'dep-that-requires'],
6+
exclude: ['vue', 'slash5']
7+
},
48
build: {
59
minify: false,
610
rollupOptions: {
7-
external: ['vue']
11+
external: ['vue', 'slash3', 'slash5']
812
},
913
commonjsOptions: {
10-
esmExternals: ['vue']
14+
esmExternals: ['vue', 'slash5']
1115
}
1216
}
1317
})

‎pnpm-lock.yaml

+28-15
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)
Please sign in to comment.