From 1061bbdaf81c2808ed8a86946cf0e07a0d8e5b13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BF=A0=20/=20green?= Date: Sun, 5 Jun 2022 15:28:10 +0900 Subject: [PATCH] fix(optimizer): external require-import conversion (fixes #2492, #3409) (#8459) --- .../src/node/optimizer/esbuildDepPlugin.ts | 28 ++++++++++++++++++- .../__tests__/optimize-deps.spec.ts | 6 +++- .../optimize-deps/dep-cjs-with-assets/foo.css | 3 ++ .../dep-cjs-with-assets/index.js | 3 ++ .../dep-cjs-with-assets/package.json | 6 ++++ .../optimize-deps/dep-linked-include/test.css | 2 +- playground/optimize-deps/index.html | 8 ++++++ playground/optimize-deps/package.json | 1 + pnpm-lock.yaml | 11 ++++++++ 9 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 playground/optimize-deps/dep-cjs-with-assets/foo.css create mode 100644 playground/optimize-deps/dep-cjs-with-assets/index.js create mode 100644 playground/optimize-deps/dep-cjs-with-assets/package.json diff --git a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts index 0c32af75219438..ee2a6e18cf04c6 100644 --- a/packages/vite/src/node/optimizer/esbuildDepPlugin.ts +++ b/packages/vite/src/node/optimizer/esbuildDepPlugin.ts @@ -13,6 +13,10 @@ import { import { browserExternalId } from '../plugins/resolve' import type { ExportsData } from '.' +const externalWithConversionNamespace = + 'vite:dep-pre-bundle:external-conversion' +const convertedExternalPrefix = 'vite-dep-pre-bundle-external:' + const externalTypes = [ 'css', // supported pre-processor types @@ -80,20 +84,42 @@ export function esbuildDepPlugin( name: 'vite:dep-pre-bundle', setup(build) { // 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/__tests__/optimize-deps.spec.ts b/playground/optimize-deps/__tests__/optimize-deps.spec.ts index a32274dca25e0c..929455300ba555 100644 --- a/playground/optimize-deps/__tests__/optimize-deps.spec.ts +++ b/playground/optimize-deps/__tests__/optimize-deps.spec.ts @@ -77,7 +77,11 @@ test('dep with dynamic import', async () => { }) test('dep with css import', async () => { - expect(await getColor('h1')).toBe('red') + expect(await getColor('.dep-linked-include')).toBe('red') +}) + +test('CJS dep with css import', async () => { + expect(await getColor('.cjs-with-assets')).toBe('blue') }) test('dep w/ non-js files handled via plugin', async () => { 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-linked-include/test.css b/playground/optimize-deps/dep-linked-include/test.css index 60f1eab97137f7..20ae3263941d1e 100644 --- a/playground/optimize-deps/dep-linked-include/test.css +++ b/playground/optimize-deps/dep-linked-include/test.css @@ -1,3 +1,3 @@ -body { +.dep-linked-include { color: red; } diff --git a/playground/optimize-deps/index.html b/playground/optimize-deps/index.html index 3cd619f9ce9236..c70ab5b2f09322 100644 --- a/playground/optimize-deps/index.html +++ b/playground/optimize-deps/index.html @@ -35,6 +35,12 @@

Detecting linked src package and optimizing its deps (lodash-es)

Optimizing force included dep even when it's linked

+

Dep with CSS

+
This should be red
+ +

CJS Dep with CSS

+
This should be blue
+

import * as ...

@@ -91,6 +97,8 @@

Reused variable names

text('.import-star', `[success] ${keys.join(', ')}`) } + import 'dep-cjs-with-assets' + import { env } from 'dep-node-env' text('.node-env', env) diff --git a/playground/optimize-deps/package.json b/playground/optimize-deps/package.json index 055d23bc9ce597..d323ca77af0a29 100644 --- a/playground/optimize-deps/package.json +++ b/playground/optimize-deps/package.json @@ -13,6 +13,7 @@ "clipboard": "^2.0.11", "dep-cjs-compiled-from-cjs": "file:./dep-cjs-compiled-from-cjs", "dep-cjs-compiled-from-esm": "file:./dep-cjs-compiled-from-esm", + "dep-cjs-with-assets": "file:./dep-cjs-with-assets", "dep-esbuild-plugin-transform": "file:./dep-esbuild-plugin-transform", "dep-linked": "link:./dep-linked", "dep-linked-include": "link:./dep-linked-include", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index acef1fe7331aef..aa07fd3c5ae874 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -576,6 +576,7 @@ importers: clipboard: ^2.0.11 dep-cjs-compiled-from-cjs: file:./dep-cjs-compiled-from-cjs dep-cjs-compiled-from-esm: file:./dep-cjs-compiled-from-esm + dep-cjs-with-assets: file:./dep-cjs-with-assets dep-esbuild-plugin-transform: file:./dep-esbuild-plugin-transform dep-linked: link:./dep-linked dep-linked-include: link:./dep-linked-include @@ -596,6 +597,7 @@ importers: clipboard: 2.0.11 dep-cjs-compiled-from-cjs: file:playground/optimize-deps/dep-cjs-compiled-from-cjs dep-cjs-compiled-from-esm: file:playground/optimize-deps/dep-cjs-compiled-from-esm + dep-cjs-with-assets: file:playground/optimize-deps/dep-cjs-with-assets dep-esbuild-plugin-transform: file:playground/optimize-deps/dep-esbuild-plugin-transform dep-linked: link:dep-linked dep-linked-include: link:dep-linked-include @@ -620,6 +622,9 @@ importers: playground/optimize-deps/dep-cjs-compiled-from-esm: specifiers: {} + playground/optimize-deps/dep-cjs-with-assets: + specifiers: {} + playground/optimize-deps/dep-esbuild-plugin-transform: specifiers: {} @@ -8810,6 +8815,12 @@ packages: version: 0.0.0 dev: false + file:playground/optimize-deps/dep-cjs-with-assets: + resolution: {directory: playground/optimize-deps/dep-cjs-with-assets, type: directory} + name: dep-cjs-with-assets + version: 0.0.0 + dev: false + file:playground/optimize-deps/dep-esbuild-plugin-transform: resolution: {directory: playground/optimize-deps/dep-esbuild-plugin-transform, type: directory} name: dep-esbuild-plugin-transform