diff --git a/docs/config/index.md b/docs/config/index.md index 55dc13f82cbcbf..5cd1a23774400c 100644 --- a/docs/config/index.md +++ b/docs/config/index.md @@ -718,7 +718,7 @@ createServer() ```js export default defineConfig({ optimizeDeps: { - include: ['esm-dep/node_modules/cjs-dep'] + include: ['esm-dep > cjs-dep'] } }) ``` diff --git a/packages/playground/nested-deps/vite.config.js b/packages/playground/nested-deps/vite.config.js index c58fa180dc06a5..cc3bcb2ada226b 100644 --- a/packages/playground/nested-deps/vite.config.js +++ b/packages/playground/nested-deps/vite.config.js @@ -8,7 +8,7 @@ module.exports = { 'test-package-b', 'test-package-c', 'test-package-c/side', - 'test-package-d/node_modules/test-package-d-nested' + 'test-package-d > test-package-d-nested' ], exclude: ['test-package-d'] } diff --git a/packages/playground/optimize-deps/vite.config.js b/packages/playground/optimize-deps/vite.config.js index 45a8d44db96487..94c308a000cfab 100644 --- a/packages/playground/optimize-deps/vite.config.js +++ b/packages/playground/optimize-deps/vite.config.js @@ -13,7 +13,7 @@ module.exports = { 'dep-linked-include', // required since it isn't in node_modules and is ignored by the optimizer otherwise 'dep-esbuild-plugin-transform', - 'nested-exclude/node_modules/nested-include' + 'nested-exclude>nested-include' ], exclude: ['nested-exclude'], esbuildOptions: { diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 5b899b758ccd33..274f7634dea2ae 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -10,7 +10,8 @@ import { lookupFile, normalizePath, writeFile, - flattenId + flattenId, + normalizeId } from '../utils' import { esbuildDepPlugin } from './esbuildDepPlugin' import { ImportSpecifier, init, parse } from 'es-module-lexer' @@ -184,10 +185,13 @@ export async function optimizeDeps( if (include) { const resolve = config.createResolver({ asSrc: false }) for (const id of include) { - if (!deps[id]) { + // normalize 'foo >bar` as 'foo > bar' to prevent same id being added + // and for pretty printing + const normalizedId = normalizeId(id) + if (!deps[normalizedId]) { const entry = await resolve(id) if (entry) { - deps[id] = entry + deps[normalizedId] = entry } else { throw new Error( `Failed to resolve force included dependency: ${chalk.cyan(id)}` diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 8b9baf149c3d12..8b03d363ad40f4 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -391,10 +391,12 @@ export function tryNodeResolve( ): PartialResolvedId | undefined { const { root, dedupe, isBuild } = options - // split id by "node_modules" to get actual nested package name - const nodeModulesMatch = id.match(/(.+)\/node_modules\/(.+)/) - const nestedRoot = nodeModulesMatch ? nodeModulesMatch[1] : '' - const nestedPath = nodeModulesMatch ? nodeModulesMatch[2] : id + // split id by last '>' for nested selected packages, for example: + // 'foo > bar > baz' => 'foo > bar' & 'baz' + // 'foo' => '' & 'foo' + const lastArrowIndex = id.lastIndexOf('>') + const nestedRoot = id.substring(0, lastArrowIndex).trim() + const nestedPath = id.substring(lastArrowIndex + 1).trim() // check for deep import, e.g. "my-lib/foo" const deepMatch = nestedPath.match(deepImportRE) @@ -415,7 +417,7 @@ export function tryNodeResolve( } // nested node module, step-by-step resolve to the basedir of the nestedPath - if (nodeModulesMatch) { + if (nestedRoot) { basedir = nestedResolveFrom(nestedRoot, basedir) } @@ -509,7 +511,7 @@ export function tryOptimizedResolve( for (const [pkgPath, optimizedData] of Object.entries(depData.optimized)) { // check for scenarios, e.g. - // pkgPath => "my-lib/node_modules/foo" + // pkgPath => "my-lib > foo" // id => "foo" // this narrows the need to do a full resolve if (!pkgPath.endsWith(id)) continue diff --git a/packages/vite/src/node/utils.ts b/packages/vite/src/node/utils.ts index e436adfaa4eecd..3b4b8c34545913 100644 --- a/packages/vite/src/node/utils.ts +++ b/packages/vite/src/node/utils.ts @@ -31,7 +31,10 @@ export function unwrapId(id: string): string { } export const flattenId = (id: string): string => - id.replace(/\/node_modules\//g, '__').replace(/[\/\.]/g, '_') + id.replace(/(\s*>\s*)/g, '__').replace(/[\/\.]/g, '_') + +export const normalizeId = (id: string): string => + id.replace(/(\s*>\s*)/g, ' > ') export function isBuiltin(id: string): boolean { return builtins.includes(id) @@ -57,10 +60,11 @@ export function resolveFrom(id: string, basedir: string, ssr = false): string { } /** - * like `resolveFrom` but supports resolving `node_modules` path in `id` + * like `resolveFrom` but supports resolving `>` path in `id`, + * for example: `foo > bar > baz` */ export function nestedResolveFrom(id: string, basedir: string): string { - const pkgs = id.split('/node_modules/') + const pkgs = id.split('>').map((pkg) => pkg.trim()) try { for (const pkg of pkgs) { basedir = resolveFrom(pkg, basedir)