diff --git a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts index 0c32af75219438..78d1d5112d50d0 100644 --- a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts +++ b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts @@ -79,21 +79,47 @@ export function esbuildDepPlugin( return { name: 'vite:dep-pre-bundle', setup(build) { + const externalWithConversionNamespace = + 'vite:dep-pre-bundle:external-conversion' + const convertedExternalPrefix = 'vite-dep-pre-bundle-external:' + // externalize assets and commonly known non-js file types + // See #8459 for more details about this require-import conversion build.onResolve( { filter: new RegExp(`\\.(` + allExternalTypes.join('|') + `)(\\?.*)?$`) }, async ({ path: id, importer, kind }) => { + // if the prefix exist, it is already converted to `import`, so set `external: true` + if (id.startsWith(convertedExternalPrefix)) { + return { + path: id.slice(convertedExternalPrefix.length), + external: true + } + } + const resolved = await resolve(id, importer, kind) if (resolved) { + // here it is not set to `external: true` to convert `require` to `import` return { path: resolved, - external: true + namespace: externalWithConversionNamespace } } } ) + build.onLoad( + { filter: /./, namespace: externalWithConversionNamespace }, + (args) => { + // import itself with prefix (this is the actual part of require-import conversion) + return { + contents: + `export { default } from "${convertedExternalPrefix}${args.path}";` + + `export * from "${convertedExternalPrefix}${args.path}";`, + loader: 'js' + } + } + ) function resolveEntry(id: string) { const flatId = flattenId(id) diff --git a/playground/optimize-deps/dep-cjs-with-assets/foo.css b/playground/optimize-deps/dep-cjs-with-assets/foo.css new file mode 100644 index 00000000000000..8347f9fb0c358e --- /dev/null +++ b/playground/optimize-deps/dep-cjs-with-assets/foo.css @@ -0,0 +1,3 @@ +.cjs-with-assets { + color: blue; +} diff --git a/playground/optimize-deps/dep-cjs-with-assets/index.js b/playground/optimize-deps/dep-cjs-with-assets/index.js new file mode 100644 index 00000000000000..26b296af650d88 --- /dev/null +++ b/playground/optimize-deps/dep-cjs-with-assets/index.js @@ -0,0 +1,3 @@ +require('./foo.css') + +exports.a = 11 diff --git a/playground/optimize-deps/dep-cjs-with-assets/package.json b/playground/optimize-deps/dep-cjs-with-assets/package.json new file mode 100644 index 00000000000000..2e4f6e68c7510c --- /dev/null +++ b/playground/optimize-deps/dep-cjs-with-assets/package.json @@ -0,0 +1,6 @@ +{ + "name": "dep-cjs-with-assets", + "private": true, + "version": "0.0.0", + "main": "index.js" +} diff --git a/playground/optimize-deps/dep-esm-with-assets/foo.css b/playground/optimize-deps/dep-esm-with-assets/foo.css new file mode 100644 index 00000000000000..95157ddd9d348b --- /dev/null +++ b/playground/optimize-deps/dep-esm-with-assets/foo.css @@ -0,0 +1,3 @@ +.esm-with-assets { + color: blue; +} diff --git a/playground/optimize-deps/dep-esm-with-assets/index.js b/playground/optimize-deps/dep-esm-with-assets/index.js new file mode 100644 index 00000000000000..6823943a000468 --- /dev/null +++ b/playground/optimize-deps/dep-esm-with-assets/index.js @@ -0,0 +1,3 @@ +import './foo.css' + +export const a = 11 diff --git a/playground/optimize-deps/dep-esm-with-assets/package.json b/playground/optimize-deps/dep-esm-with-assets/package.json new file mode 100644 index 00000000000000..69c6acf2be17c4 --- /dev/null +++ b/playground/optimize-deps/dep-esm-with-assets/package.json @@ -0,0 +1,7 @@ +{ + "name": "dep-esm-with-assets", + "type": "module", + "private": true, + "version": "0.0.0", + "main": "index.js" +} diff --git a/playground/optimize-deps/index.html b/playground/optimize-deps/index.html index 3cd619f9ce9236..4df7a790cd4662 100644 --- a/playground/optimize-deps/index.html +++ b/playground/optimize-deps/index.html @@ -68,6 +68,12 @@

Alias with colon

Reused variable names

This should show reused:
+

CJS Dep with assets

+
This should be blue
+ +

ESM Dep with assets

+
This should be blue
+