From 72eaef5300d20b7163050461733c3208a4013e1e Mon Sep 17 00:00:00 2001 From: Bjorn Lu Date: Fri, 1 Nov 2024 15:15:36 +0800 Subject: [PATCH] fix(config): write temporary vite config to node_modules (#18509) --- packages/vite/src/node/config.ts | 26 +++++++++++++++++--------- packages/vite/src/node/packages.ts | 15 +++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/packages/vite/src/node/config.ts b/packages/vite/src/node/config.ts index d9f8c4083c65c1..3938da88a7f5a6 100644 --- a/packages/vite/src/node/config.ts +++ b/packages/vite/src/node/config.ts @@ -84,7 +84,7 @@ import { createLogger } from './logger' import type { DepOptimizationOptions } from './optimizer' import type { JsonOptions } from './plugins/json' import type { PackageCache } from './packages' -import { findNearestPackageData } from './packages' +import { findNearestNodeModules, findNearestPackageData } from './packages' import { loadEnv, resolveEnvPrefix } from './env' import type { ResolvedSSROptions, SSROptions } from './ssr' import { resolveSSROptions } from './ssr' @@ -1717,16 +1717,24 @@ async function loadConfigFromBundledFile( // with --experimental-loader themselves, we have to do a hack here: // write it to disk, load it with native Node ESM, then delete the file. if (isESM) { - const fileBase = `${fileName}.timestamp-${Date.now()}-${Math.random() - .toString(16) - .slice(2)}` - const fileNameTmp = `${fileBase}.mjs` - const fileUrl = `${pathToFileURL(fileBase)}.mjs` - await fsp.writeFile(fileNameTmp, bundledCode) + const nodeModulesDir = findNearestNodeModules(path.dirname(fileName)) + if (nodeModulesDir) { + await fsp.mkdir(path.resolve(nodeModulesDir, '.vite-temp/'), { + recursive: true, + }) + } + const hash = `timestamp-${Date.now()}-${Math.random().toString(16).slice(2)}` + const tempFileName = nodeModulesDir + ? path.resolve( + nodeModulesDir, + `.vite-temp/${path.basename(fileName)}.${hash}.mjs`, + ) + : `${fileName}.${hash}.mjs` + await fsp.writeFile(tempFileName, bundledCode) try { - return (await import(fileUrl)).default + return (await import(pathToFileURL(tempFileName).href)).default } finally { - fs.unlink(fileNameTmp, () => {}) // Ignore errors + fs.unlink(tempFileName, () => {}) // Ignore errors } } // for cjs, we can register a custom loader via `_require.extensions` diff --git a/packages/vite/src/node/packages.ts b/packages/vite/src/node/packages.ts index f03a3f1a3d058b..468fc4cbb0595b 100644 --- a/packages/vite/src/node/packages.ts +++ b/packages/vite/src/node/packages.ts @@ -235,6 +235,21 @@ function getResolveCacheKey(key: string, options: InternalResolveOptions) { ].join('|') } +export function findNearestNodeModules(basedir: string): string | null { + while (basedir) { + const pkgPath = path.join(basedir, 'node_modules') + if (tryStatSync(pkgPath)?.isDirectory()) { + return pkgPath + } + + const nextBasedir = path.dirname(basedir) + if (nextBasedir === basedir) break + basedir = nextBasedir + } + + return null +} + export function watchPackageDataPlugin(packageCache: PackageCache): Plugin { // a list of files to watch before the plugin is ready const watchQueue = new Set()