From 9622b2cdd37bddf27a61e6e8f1143015e3a7fa48 Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Fri, 24 Oct 2025 18:21:03 +0900 Subject: [PATCH 1/2] feat: add `legacy.inconsistentCjsInterop` option --- packages/vite/src/node/config.ts | 4 ++++ .../vite/src/node/plugins/importAnalysis.ts | 4 +++- packages/vite/src/node/plugins/index.ts | 1 + packages/vite/src/node/plugins/resolve.ts | 22 ++++++++++++++++--- 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index a9249548aca131..cb5860f79e6e96 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -566,6 +566,10 @@ export interface LegacyOptions { * that security weakness.** */ skipWebSocketTokenCheck?: boolean + /** + * TODO: write description + */ + inconsistentCjsInterop?: boolean } export interface ResolvedWorkerOptions { diff --git a/packages/vite/src/node/plugins/importAnalysis.ts b/packages/vite/src/node/plugins/importAnalysis.ts index b2550eb6dd9c7f..6c470966473454 100644 --- a/packages/vite/src/node/plugins/importAnalysis.ts +++ b/packages/vite/src/node/plugins/importAnalysis.ts @@ -441,7 +441,9 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin { imports.length, ) - let _isNodeModeResult: boolean | undefined + let _isNodeModeResult = config.legacy?.inconsistentCjsInterop + ? false + : undefined const isNodeMode = () => { _isNodeModeResult ??= isFilePathESM(importer, config.packageCache) return _isNodeModeResult diff --git a/packages/vite/src/node/plugins/index.ts b/packages/vite/src/node/plugins/index.ts index a0cd0d2d80f5e2..dc3d66130525af 100644 --- a/packages/vite/src/node/plugins/index.ts +++ b/packages/vite/src/node/plugins/index.ts @@ -85,6 +85,7 @@ export async function resolvePlugins( asSrc: true, optimizeDeps: true, externalize: true, + legacyInconsistentCjsInterop: config.legacy?.inconsistentCjsInterop, }, isWorker ? { ...config, consumer: 'client', optimizeDepsPluginNames: [] } diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index d19320c42d6f5b..455a81f0bb5e59 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -167,6 +167,11 @@ interface ResolvePluginOptions { * @internal */ idOnly?: boolean + + /** + * TODO: write description + */ + legacyInconsistentCjsInterop?: boolean } export interface InternalResolveOptions @@ -283,6 +288,7 @@ export function oxcResolvePlugin( external: options.external, noExternal: noExternal, dedupe: options.dedupe, + legacyInconsistentCjsInterop: options.legacyInconsistentCjsInterop, finalizeBareSpecifier: !depsOptimizerEnabled ? undefined : (resolvedId, rawId, importer) => { @@ -553,6 +559,7 @@ export function resolvePlugin( id: ensureVersionQuery(res, id, options, depsOptimizer), packageJsonPath: findNearestPackagePath( res, + options.legacyInconsistentCjsInterop, options.packageCache, isBuild, ), @@ -573,6 +580,7 @@ export function resolvePlugin( id: ensureVersionQuery(res, id, options, depsOptimizer), packageJsonPath: findNearestPackagePath( res, + options.legacyInconsistentCjsInterop, options.packageCache, isBuild, ), @@ -629,7 +637,9 @@ export function resolvePlugin( return { id: res, moduleSideEffects: resPkg.hasSideEffects(res), - packageJsonPath: path.join(resPkg.dir, 'package.json'), + packageJsonPath: options.legacyInconsistentCjsInterop + ? undefined + : path.join(resPkg.dir, 'package.json'), } } } @@ -653,6 +663,7 @@ export function resolvePlugin( id: ensureVersionQuery(res, id, options, depsOptimizer), packageJsonPath: findNearestPackagePath( res, + options.legacyInconsistentCjsInterop, options.packageCache, isBuild, ), @@ -670,6 +681,7 @@ export function resolvePlugin( id: ensureVersionQuery(res, id, options, depsOptimizer), packageJsonPath: findNearestPackagePath( res, + options.legacyInconsistentCjsInterop, options.packageCache, isBuild, ), @@ -1169,6 +1181,7 @@ export function tryNodeResolve( moduleSideEffects: pkg.hasSideEffects(resolved), packageJsonPath: findNearestPackagePath( resolved, + options.legacyInconsistentCjsInterop, options.packageCache, isBuild, ), @@ -1518,7 +1531,9 @@ function tryResolveBrowserMapping( result = { id: res, moduleSideEffects: resPkg.hasSideEffects(res), - packageJsonPath: path.join(resPkg.dir, 'package.json'), + packageJsonPath: options.legacyInconsistentCjsInterop + ? undefined + : path.join(resPkg.dir, 'package.json'), } } } @@ -1654,10 +1669,11 @@ function isDirectory(path: string): boolean { function findNearestPackagePath( file: string, + legacyInconsistentCjsInterop: boolean | undefined, packageCache: PackageCache | undefined, isBuild: boolean, ) { - if (!isBuild) return + if (!isBuild || legacyInconsistentCjsInterop) return const pkgData = findNearestPackageData(file, packageCache) return pkgData ? path.join(pkgData.dir, 'package.json') : null } From b5e5a67d75226250706d3b2ae65d3c5c030610a1 Mon Sep 17 00:00:00 2001 From: sapphi-red <49056869+sapphi-red@users.noreply.github.com> Date: Mon, 27 Oct 2025 12:42:34 +0900 Subject: [PATCH 2/2] chore: update comment --- packages/vite/src/node/config.ts | 9 ++++++++- packages/vite/src/node/plugins/resolve.ts | 2 +- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index cb5860f79e6e96..0242d6a9a5bb23 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -567,7 +567,14 @@ export interface LegacyOptions { */ skipWebSocketTokenCheck?: boolean /** - * TODO: write description + * Opt-in to the pre-Vite 8 CJS interop behavior, which was inconsistent. + * + * In pre-Vite 8 versions, Vite had inconsistent CJS interop behavior. This was due to + * the different behavior of esbuild and the Rollup commonjs plugin. + * Vite 8+ uses Rolldown for both the dependency optimization in dev and the production build, + * which aligns the behavior to esbuild. + * + * See the Vite 8 migration guide for more details. */ inconsistentCjsInterop?: boolean } diff --git a/packages/vite/src/node/plugins/resolve.ts b/packages/vite/src/node/plugins/resolve.ts index 455a81f0bb5e59..281273871bd360 100644 --- a/packages/vite/src/node/plugins/resolve.ts +++ b/packages/vite/src/node/plugins/resolve.ts @@ -169,7 +169,7 @@ interface ResolvePluginOptions { idOnly?: boolean /** - * TODO: write description + * Enable when `legacy.inconsistentCjsInterop` is true. See that option for more details. */ legacyInconsistentCjsInterop?: boolean }