Skip to content

Commit

Permalink
fix: preserve default export from externalized packages (fixes vitejs…
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red committed Nov 9, 2022
1 parent d5fe92c commit b1307d8
Show file tree
Hide file tree
Showing 12 changed files with 154 additions and 106 deletions.
44 changes: 33 additions & 11 deletions packages/vite/src/node/optimizer/esbuildDepPlugin.ts
Expand Up @@ -17,6 +17,9 @@ const externalWithConversionNamespace =
'vite:dep-pre-bundle:external-conversion'
const convertedExternalPrefix = 'vite-dep-pre-bundle-external:'

const cjsExternalFacadeNamespace = 'vite:cjs-external-facade'
const nonFacadePrefix = 'vite-cjs-external-facade:'

const externalTypes = [
'css',
// supported pre-processor types
Expand Down Expand Up @@ -270,19 +273,38 @@ export function esbuildCjsExternalPlugin(externals: string[]): Plugin {
`^${text.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')}$`
const filter = new RegExp(externals.map(escape).join('|'))

build.onResolve({ filter: /.*/, namespace: 'external' }, (args) => ({
path: args.path,
external: true
}))
build.onResolve({ filter: new RegExp(`^${nonFacadePrefix}`) }, (args) => {
return {
path: args.path.slice(nonFacadePrefix.length),
external: true
}
})

build.onResolve({ filter }, (args) => {
if (args.kind === 'require-call') {
return {
path: args.path,
namespace: cjsExternalFacadeNamespace
}
}

build.onResolve({ filter }, (args) => ({
path: args.path,
namespace: 'external'
}))
return {
path: args.path,
external: true
}
})

build.onLoad({ filter: /.*/, namespace: 'external' }, (args) => ({
contents: `export * from ${JSON.stringify(args.path)}`
}))
build.onLoad(
{ filter: /.*/, namespace: cjsExternalFacadeNamespace },
(args) => ({
contents:
`import * as m from ${JSON.stringify(
nonFacadePrefix + args.path
)};` +
`export default m.default;` +
`export * from ${JSON.stringify(nonFacadePrefix + args.path)};`
})
)
}
}
}
5 changes: 5 additions & 0 deletions playground/external/__tests__/external.spec.ts
Expand Up @@ -7,6 +7,11 @@ test('importmap', () => {
)
})

test('should have default exports', async () => {
expect(await page.textContent('#imported-slash-exists')).toBe('true')
expect(await page.textContent('#required-slash-exists')).toBe('true')
})

describe.runIf(isBuild)('build', () => {
test('should externalize imported packages', async () => {
// If `vue` is successfully externalized, the page should use the version from the import map
Expand Down
@@ -1,3 +1,5 @@
import { version } from 'vue'
import slash from 'slash'

document.querySelector('#imported-vue-version').textContent = version
document.querySelector('#imported-slash-exists').textContent = !!slash
@@ -1,8 +1,9 @@
{
"name": "@vitejs/dep-that-imports-vue",
"name": "@vitejs/dep-that-imports",
"private": true,
"version": "0.0.0",
"dependencies": {
"slash": "^5.0.0",
"vue": "^3.2.41"
}
}
3 changes: 0 additions & 3 deletions playground/external/dep-that-requires-vue/index.js

This file was deleted.

5 changes: 5 additions & 0 deletions playground/external/dep-that-requires/index.js
@@ -0,0 +1,5 @@
const { version } = require('vue')
const { default: slash } = require('slash')

document.querySelector('#required-vue-version').textContent = version
document.querySelector('#required-slash-exists').textContent = !!slash
@@ -1,8 +1,9 @@
{
"name": "@vitejs/dep-that-requires-vue",
"name": "@vitejs/dep-that-requires",
"private": true,
"version": "0.0.0",
"dependencies": {
"slash": "^5.0.0",
"vue": "^3.2.41"
}
}
5 changes: 4 additions & 1 deletion playground/external/index.html
Expand Up @@ -7,14 +7,17 @@
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3.2.0/dist/vue.runtime.esm-browser.js"
"vue": "https://unpkg.com/vue@3.2.0/dist/vue.runtime.esm-browser.js",
"slash": "https://unpkg.com/slash@5.0.0/index.js"
}
}
</script>
</head>
<body>
<p>Imported Vue version: <span id="imported-vue-version"></span></p>
<p>Required Vue version: <span id="required-vue-version"></span></p>
<p>Imported slash exists: <span id="imported-slash-exists"></span></p>
<p>Required slash exists: <span id="required-slash-exists"></span></p>
<script type="module" src="/src/main.js"></script>
</body>
</html>
5 changes: 3 additions & 2 deletions playground/external/package.json
Expand Up @@ -9,10 +9,11 @@
"preview": "vite preview"
},
"dependencies": {
"@vitejs/dep-that-imports-vue": "file:./dep-that-imports-vue",
"@vitejs/dep-that-requires-vue": "file:./dep-that-requires-vue"
"@vitejs/dep-that-imports": "file:./dep-that-imports",
"@vitejs/dep-that-requires": "file:./dep-that-requires"
},
"devDependencies": {
"slash": "^5.0.0",
"vite": "workspace:*",
"vue": "^3.2.41"
}
Expand Down
4 changes: 2 additions & 2 deletions playground/external/src/main.js
@@ -1,2 +1,2 @@
import '@vitejs/dep-that-imports-vue'
import '@vitejs/dep-that-requires-vue'
import '@vitejs/dep-that-imports'
import '@vitejs/dep-that-requires'
8 changes: 6 additions & 2 deletions playground/external/vite.config.js
@@ -1,13 +1,17 @@
import { defineConfig } from 'vite'

export default defineConfig({
optimizeDeps: {
include: ['dep-that-imports', 'dep-that-requires'],
exclude: ['vue', 'slash']
},
build: {
minify: false,
rollupOptions: {
external: ['vue']
external: ['vue', 'slash']
},
commonjsOptions: {
esmExternals: ['vue']
esmExternals: ['vue', 'slash']
}
}
})

0 comments on commit b1307d8

Please sign in to comment.