diff --git a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts index 3370cec68a6383..2def9336e8a3d6 100644 --- a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts +++ b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts @@ -16,6 +16,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 @@ -268,19 +271,36 @@ 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 + )};` + `module.exports = m;` + }) + ) } } } diff --git a/playground/external/__tests__/external.spec.ts b/playground/external/__tests__/external.spec.ts index 029ffc8422a3ba..7504b6ae1c293c 100644 --- a/playground/external/__tests__/external.spec.ts +++ b/playground/external/__tests__/external.spec.ts @@ -7,6 +7,12 @@ test('importmap', () => { ) }) +test('should have default exports', async () => { + expect(await page.textContent('#imported-slash5-exists')).toBe('true') + expect(await page.textContent('#imported-slash3-exists')).toBe('true') + expect(await page.textContent('#required-slash3-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 diff --git a/playground/external/dep-that-imports-vue/index.js b/playground/external/dep-that-imports-vue/index.js deleted file mode 100644 index aa79957e9b3b49..00000000000000 --- a/playground/external/dep-that-imports-vue/index.js +++ /dev/null @@ -1,3 +0,0 @@ -import { version } from 'vue' - -document.querySelector('#imported-vue-version').textContent = version diff --git a/playground/external/dep-that-imports-vue/package.json b/playground/external/dep-that-imports-vue/package.json deleted file mode 100644 index 3a57f33cdf5eda..00000000000000 --- a/playground/external/dep-that-imports-vue/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "@vitejs/dep-that-imports-vue", - "private": true, - "version": "0.0.0", - "dependencies": { - "vue": "^3.2.45" - } -} diff --git a/playground/external/dep-that-imports/index.js b/playground/external/dep-that-imports/index.js new file mode 100644 index 00000000000000..096ea934cc4965 --- /dev/null +++ b/playground/external/dep-that-imports/index.js @@ -0,0 +1,9 @@ +import { version } from 'vue' +import slash5 from 'slash5' +import slash3 from 'slash3' + +document.querySelector('#imported-vue-version').textContent = version +document.querySelector('#imported-slash5-exists').textContent = + !!slash5('foo/bar') +document.querySelector('#imported-slash3-exists').textContent = + !!slash3('foo/bar') diff --git a/playground/external/dep-that-imports/package.json b/playground/external/dep-that-imports/package.json new file mode 100644 index 00000000000000..b688165c9fc521 --- /dev/null +++ b/playground/external/dep-that-imports/package.json @@ -0,0 +1,10 @@ +{ + "name": "@vitejs/dep-that-imports", + "private": true, + "version": "0.0.0", + "dependencies": { + "slash3": "npm:slash@^3.0.0", + "slash5": "npm:slash@^5.0.0", + "vue": "^3.2.45" + } +} diff --git a/playground/external/dep-that-requires-vue/index.js b/playground/external/dep-that-requires-vue/index.js deleted file mode 100644 index 0b573021a00b57..00000000000000 --- a/playground/external/dep-that-requires-vue/index.js +++ /dev/null @@ -1,3 +0,0 @@ -const { version } = require('vue') - -document.querySelector('#required-vue-version').textContent = version diff --git a/playground/external/dep-that-requires-vue/package.json b/playground/external/dep-that-requires-vue/package.json deleted file mode 100644 index b96a6e4f360abd..00000000000000 --- a/playground/external/dep-that-requires-vue/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "@vitejs/dep-that-requires-vue", - "private": true, - "version": "0.0.0", - "dependencies": { - "vue": "^3.2.45" - } -} diff --git a/playground/external/dep-that-requires/index.js b/playground/external/dep-that-requires/index.js new file mode 100644 index 00000000000000..6f0dd6124d829d --- /dev/null +++ b/playground/external/dep-that-requires/index.js @@ -0,0 +1,7 @@ +const { version } = require('vue') +// require('slash5') // cannot require ESM +const slash3 = require('slash3') + +document.querySelector('#required-vue-version').textContent = version +document.querySelector('#required-slash3-exists').textContent = + !!slash3('foo/bar') diff --git a/playground/external/dep-that-requires/package.json b/playground/external/dep-that-requires/package.json new file mode 100644 index 00000000000000..bc1195ccfc6add --- /dev/null +++ b/playground/external/dep-that-requires/package.json @@ -0,0 +1,10 @@ +{ + "name": "@vitejs/dep-that-requires", + "private": true, + "version": "0.0.0", + "dependencies": { + "slash3": "npm:slash@^3.0.0", + "slash5": "npm:slash@^5.0.0", + "vue": "^3.2.45" + } +} diff --git a/playground/external/index.html b/playground/external/index.html index 66a16c329c1fc5..e07492875bdc1d 100644 --- a/playground/external/index.html +++ b/playground/external/index.html @@ -7,7 +7,9 @@ @@ -15,6 +17,9 @@
Imported Vue version:
Required Vue version:
+Imported slash5 exists:
+Imported slash3 exists:
+Required slash3 exists: