diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index 09c6e00adf9d6e..5fded668f295d0 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -48,7 +48,7 @@ import { ENV_ENTRY } from './constants' import type { InternalResolveOptions, ResolveOptions } from './plugins/resolve' -import { resolvePlugin } from './plugins/resolve' +import { resolvePlugin, tryNodeResolve } from './plugins/resolve' import type { LogLevel, Logger } from './logger' import { createLogger } from './logger' import type { DepOptimizationConfig, DepOptimizationOptions } from './optimizer' @@ -967,40 +967,33 @@ async function bundleConfigFile( { name: 'externalize-deps', setup(build) { - build.onResolve({ filter: /.*/ }, ({ path: id, importer }) => { + const options: InternalResolveOptions = { + root: path.dirname(fileName), + isBuild: true, + isProduction: true, + isRequire: !isESM, + preferRelative: false, + tryIndex: true, + mainFields: DEFAULT_MAIN_FIELDS, + browserField: false, + conditions: [], + dedupe: [], + extensions: DEFAULT_EXTENSIONS, + preserveSymlinks: false + } + + build.onResolve({ filter: /.*/ }, ({ path: id, importer, kind }) => { // externalize bare imports - if (id[0] !== '.' && !path.isAbsolute(id)) { + if (id[0] !== '.' && !isAbsolute(id)) { + let idFsPath = tryNodeResolve(id, importer, options, false)?.id + if (idFsPath && (isESM || kind === 'dynamic-import')) { + idFsPath = pathToFileURL(idFsPath).href + } return { + path: idFsPath, external: true } } - // bundle the rest and make sure that the we can also access - // it's third-party dependencies. externalize if not. - // monorepo/ - // ├─ package.json - // ├─ utils.js -----------> bundle (share same node_modules) - // ├─ vite-project/ - // │ ├─ vite.config.js --> entry - // │ ├─ package.json - // ├─ foo-project/ - // │ ├─ utils.js --------> external (has own node_modules) - // │ ├─ package.json - const idFsPath = path.resolve(path.dirname(importer), id) - const idPkgPath = lookupFile(idFsPath, [`package.json`], { - pathOnly: true - }) - if (idPkgPath) { - const idPkgDir = path.dirname(idPkgPath) - // if this file needs to go up one or more directory to reach the vite config, - // that means it has it's own node_modules (e.g. foo-project) - if (path.relative(idPkgDir, fileName).startsWith('..')) { - return { - // normalize actual import after bundled as a single vite config - path: isESM ? pathToFileURL(idFsPath).href : idFsPath, - external: true - } - } - } }) } }, @@ -1122,3 +1115,7 @@ export function isDepsOptimizerEnabled( (command === 'serve' && disabled === 'dev') ) } + +function isAbsolute(id: string) { + return path.isAbsolute(id) || path.posix.isAbsolute(id) +} diff --git a/playground/config/__tests__/load.spec.ts b/playground/config/__tests__/load.spec.ts new file mode 100644 index 00000000000000..e25ac224673a66 --- /dev/null +++ b/playground/config/__tests__/load.spec.ts @@ -0,0 +1,24 @@ +import { resolve } from 'node:path' +import { loadConfigFromFile } from 'vite' +import { expect, it } from 'vitest' + +it('loadConfigFromFile', async () => { + const { config } = await loadConfigFromFile( + {} as any, + resolve(__dirname, '../packages/entry/vite.config.ts') + ) + expect(config).toMatchInlineSnapshot(` + { + "array": [ + [ + 1, + 3, + ], + [ + 2, + 4, + ], + ], + } + `) +}) diff --git a/playground/config/__tests__/serve.ts b/playground/config/__tests__/serve.ts new file mode 100644 index 00000000000000..e8959c0a1eda19 --- /dev/null +++ b/playground/config/__tests__/serve.ts @@ -0,0 +1,3 @@ +export function serve() { + return +} diff --git a/playground/config/packages/entry/package.json b/playground/config/packages/entry/package.json new file mode 100644 index 00000000000000..c251a034716150 --- /dev/null +++ b/playground/config/packages/entry/package.json @@ -0,0 +1,3 @@ +{ + "name": "@vite/test-config-entry" +} diff --git a/playground/config/packages/entry/vite.config.ts b/playground/config/packages/entry/vite.config.ts new file mode 100644 index 00000000000000..a53828cb84cfd8 --- /dev/null +++ b/playground/config/packages/entry/vite.config.ts @@ -0,0 +1,5 @@ +import { array } from '../siblings/foo' + +export default { + array +} diff --git a/playground/config/packages/siblings/foo.ts b/playground/config/packages/siblings/foo.ts new file mode 100644 index 00000000000000..78a8912131faed --- /dev/null +++ b/playground/config/packages/siblings/foo.ts @@ -0,0 +1,3 @@ +import { partition } from 'lodash' + +export const array = partition([1, 2, 3, 4], (n) => n % 2) diff --git a/playground/config/packages/siblings/package.json b/playground/config/packages/siblings/package.json new file mode 100644 index 00000000000000..4cbdc81d2100ea --- /dev/null +++ b/playground/config/packages/siblings/package.json @@ -0,0 +1,7 @@ +{ + "name": "@vite/test-config-sibling", + "devDependencies": { + "@types/lodash": "^4.14.186", + "lodash": "^4.17.21" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ab25134fb26652..8349499bf4272b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -388,6 +388,17 @@ importers: playground/cli-module: specifiers: {} + playground/config/packages/entry: + specifiers: {} + + playground/config/packages/siblings: + specifiers: + '@types/lodash': ^4.14.186 + lodash: ^4.17.21 + devDependencies: + '@types/lodash': 4.14.186 + lodash: 4.17.21 + playground/css: specifiers: css-dep: link:./css-dep @@ -2516,6 +2527,10 @@ packages: resolution: {integrity: sha512-1YXyYH83h6We1djyoUEqTlVyQtCfJAFXELSKW2ZRtjHD4hQ82CC4lvrv5D0l0FLcKBaiPbXyi3MpMsI9ZRgKsw==} dev: true + /@types/lodash/4.14.186: + resolution: {integrity: sha512-eHcVlLXP0c2FlMPm56ITode2AgLMSa6aJ05JTTbYbI+7EMkCEE5qk2E41d5g2lCVTqRe0GnnRFurmlCsDODrPw==} + dev: true + /@types/micromatch/4.0.2: resolution: {integrity: sha512-oqXqVb0ci19GtH0vOA/U2TmHTcRY9kuZl4mqUxe0QmJAlIW13kzhuK5pi1i9+ngav8FjpSb9FVS/GE00GLX1VA==} dependencies: