From ea11c3bf4c49574da3e5b04873e92c6d2253d3d7 Mon Sep 17 00:00:00 2001 From: patak Date: Mon, 27 Mar 2023 23:34:09 +0200 Subject: [PATCH 1/7] perf: back to temporal optimizer dirs --- packages/vite/src/node/optimizer/index.ts | 330 +++++++++--------- .../vite/src/node/plugins/optimizedDeps.ts | 12 +- .../src/node/server/middlewares/transform.ts | 5 +- 3 files changed, 177 insertions(+), 170 deletions(-) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 6b3441cd5d027d..8a5ee2b7df8cf7 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -1,6 +1,7 @@ import fs from 'node:fs' import fsp from 'node:fs/promises' import path from 'node:path' +import { promisify } from 'node:util' import { performance } from 'node:perf_hooks' import _debug from 'debug' import colors from 'picocolors' @@ -17,6 +18,7 @@ import { flattenId, getHash, isOptimizable, + isWindows, lookupFile, normalizeId, normalizePath, @@ -27,7 +29,6 @@ import { transformWithEsbuild } from '../plugins/esbuild' import { ESBUILD_MODULES_TARGET } from '../constants' import { resolvePackageData } from '../packages' import type { ViteDevServer } from '../server' -import type { Logger } from '../logger' import { esbuildCjsExternalPlugin, esbuildDepPlugin } from './esbuildDepPlugin' import { scanImports } from './scan' export { @@ -352,19 +353,19 @@ export async function loadCachedDepOptimizationMetadata( ): Promise { const log = asCommand ? config.logger.info : debug - // Before Vite 2.9, dependencies were cached in the root of the cacheDir - // For compat, we remove the cache if we find the old structure - if (fs.existsSync(path.join(config.cacheDir, '_metadata.json'))) { - emptyDir(config.cacheDir) - } + setTimeout(() => { + // Before Vite 2.9, dependencies were cached in the root of the cacheDir + // For compat, we remove the cache if we find the old structure + if (fs.existsSync(path.join(config.cacheDir, '_metadata.json'))) { + emptyDir(config.cacheDir) + } + // Fire a clean up of stale cache dirs, in case old processes didn't + // terminate correctly + cleanupDepsCacheStaleDirs(config) + }, 100) const depsCacheDir = getDepsCacheDir(config, ssr) - // If the lock timed out, we cancel and return undefined - if (!(await waitOptimizerWriteLock(depsCacheDir, config.logger))) { - return - } - if (!force) { let cachedMetadata: DepOptimizationMetadata | undefined try { @@ -482,6 +483,23 @@ export function runOptimizeDeps( } const depsCacheDir = getDepsCacheDir(resolvedConfig, ssr) + const processingCacheDir = getProcessingDepsCacheDir(resolvedConfig, ssr) + + // Create a temporal directory so we don't need to delete optimized deps + // until they have been processed. This also avoids leaving the deps cache + // directory in a corrupted state if there is an error + if (fs.existsSync(processingCacheDir)) { + emptyDir(processingCacheDir) + } else { + fs.mkdirSync(processingCacheDir, { recursive: true }) + } + + // a hint for Node.js + // all files in the cache directory should be recognized as ES modules + fs.writeFileSync( + path.resolve(processingCacheDir, 'package.json'), + `{\n "type": "module"\n}\n`, + ) const metadata = initDepsOptimizerMetadata(config, ssr) @@ -495,27 +513,64 @@ export function runOptimizeDeps( // the optimizedDepInfo.processing promise for each dep const qualifiedIds = Object.keys(depsInfo) + let cleaned = false + const cleanUp = () => { + if (!cleaned) { + cleaned = true + // No need to wait, we can clean up in the background because temp folders + // are unique per run + fsp.rm(processingCacheDir, { recursive: true, force: true }).catch(() => { + // Ignore errors + }) + } + } - const createEmptyProcessingResult = () => ({ + const succesfulResult: DepOptimizationResult = { metadata, - commit: async () => {}, - cancel: async () => {}, - }) + cancel: cleanUp, + commit: async () => { + // Write metadata file, delete `deps` folder and rename the `processing` folder to `deps` + // Processing is done, we can now replace the depsCacheDir with processingCacheDir + // Rewire the file paths from the temporal processing dir to the final deps cache dir + const temporalPath = depsCacheDir + getTempSuffix() + const depsCacheDirPresent = fs.existsSync(depsCacheDir) + + if (isWindows) { + depsCacheDirPresent && (await safeRename(depsCacheDir, temporalPath)) + await safeRename(processingCacheDir, depsCacheDir) + } else { + depsCacheDirPresent && fs.renameSync(depsCacheDir, temporalPath) + fs.renameSync(processingCacheDir, depsCacheDir) + } + + // Delete temporal path in the background + fsp.rm(temporalPath, { recursive: true, force: true }) + }, + } if (!qualifiedIds.length) { + // No deps to optimize, we still commit the processing cache dir to remove + // the previous optimized deps if they exist, and let the next server start + // skip the scanner step if the lockfile hasn't changed return { - result: Promise.resolve(createEmptyProcessingResult()), - cancel: async () => {}, + cancel: async () => cleanUp(), + result: Promise.resolve(succesfulResult), } } + const canceledResult: DepOptimizationResult = { + metadata, + commit: async () => cleanUp(), + cancel: cleanUp, + } + const start = performance.now() const preparedRun = prepareEsbuildOptimizerRun( resolvedConfig, depsInfo, ssr, - depsCacheDir, + processingCacheDir, optimizerContext, ) @@ -527,7 +582,7 @@ export function runOptimizeDeps( } if (!context || optimizerContext.cancelled) { disposeContext() - return createEmptyProcessingResult() + return canceledResult } return context @@ -538,11 +593,15 @@ export function runOptimizeDeps( // the paths in `meta.outputs` are relative to `process.cwd()` const processingCacheDirOutputPath = path.relative( process.cwd(), - depsCacheDir, + processingCacheDir, ) for (const id in depsInfo) { - const output = esbuildOutputFromId(meta.outputs, id, depsCacheDir) + const output = esbuildOutputFromId( + meta.outputs, + id, + processingCacheDir, + ) const { exportsData, ...info } = depsInfo[id] addOptimizedDepInfo(metadata, 'optimized', { @@ -589,96 +648,24 @@ export function runOptimizeDeps( } } + const dataPath = path.join(processingCacheDir, '_metadata.json') + fs.writeFileSync( + dataPath, + stringifyDepsOptimizerMetadata(metadata, depsCacheDir), + ) + debug( `Dependencies bundled in ${(performance.now() - start).toFixed(2)}ms`, ) - // Write this run of pre-bundled dependencies to the deps cache - async function commitFiles() { - // Get a list of old files in the deps directory to delete the stale ones - const oldFilesPaths: string[] = [] - // File used to tell other processes that we're writing the deps cache directory - const writingFilePath = path.resolve(depsCacheDir, '_writing') - - if ( - !fs.existsSync(depsCacheDir) || - !(await waitOptimizerWriteLock(depsCacheDir, config.logger)) // unlock timed out - ) { - fs.mkdirSync(depsCacheDir, { recursive: true }) - fs.writeFileSync(writingFilePath, '') - } else { - fs.writeFileSync(writingFilePath, '') - oldFilesPaths.push( - ...(await fsp.readdir(depsCacheDir)).map((f) => - path.join(depsCacheDir, f), - ), - ) - } - - const newFilesPaths = new Set() - newFilesPaths.add(writingFilePath) - const files: Promise[] = [] - const write = (filePath: string, content: string | Uint8Array) => { - newFilesPaths.add(filePath) - files.push(fsp.writeFile(filePath, content)) - } - - path.join(depsCacheDir, '_metadata.json'), - // a hint for Node.js - // all files in the cache directory should be recognized as ES modules - write( - path.resolve(depsCacheDir, 'package.json'), - '{\n "type": "module"\n}\n', - ) - - write( - path.join(depsCacheDir, '_metadata.json'), - stringifyDepsOptimizerMetadata(metadata, depsCacheDir), - ) - - for (const outputFile of result.outputFiles!) - write(outputFile.path, outputFile.contents) - - // Clean up old files in the background - for (const filePath of oldFilesPaths) - if (!newFilesPaths.has(filePath)) fs.unlink(filePath, () => {}) // ignore errors - - await Promise.all(files) - - // Successful write - fsp.unlink(writingFilePath) - - setTimeout(() => { - // Free up memory, these files aren't going to be re-requested because - // the requests are cached. If they do, then let them read from disk. - optimizedDepsCache.delete(metadata) - }, 5000) - } - - return { - metadata, - async commit() { - // Keep the output files in memory while we write them to disk in the - // background. These files are going to be sent right away to the browser - optimizedDepsCache.set( - metadata, - new Map( - result.outputFiles!.map((f) => [normalizePath(f.path), f.text]), - ), - ) - - // No need to wait, files are written in the background - setTimeout(commitFiles, 0) - }, - cancel: () => {}, - } + return succesfulResult }) .catch((e) => { if (e.errors && e.message.includes('The build was canceled')) { // esbuild logs an error when cancelling, but this is expected so // return an empty result instead - return createEmptyProcessingResult() + return canceledResult } throw e }) @@ -687,11 +674,16 @@ export function runOptimizeDeps( }) }) + runResult.catch(() => { + cleanUp() + }) + return { async cancel() { optimizerContext.cancelled = true const { context } = await preparedRun await context?.cancel() + cleanUp() }, result: runResult, } @@ -793,9 +785,6 @@ async function prepareEsbuildOptimizerRun( absWorkingDir: process.cwd(), entryPoints: Object.keys(flatIdDeps), bundle: true, - // Don't write to disk, we'll only write the files if the build isn't invalidated - // by newly discovered dependencies - write: false, // We can't use platform 'neutral', as esbuild has custom handling // when the platform is 'node' or 'browser' that can't be emulated // by using mainFields and conditions @@ -970,6 +959,21 @@ export function getDepsCacheDir(config: ResolvedConfig, ssr: boolean): string { return getDepsCacheDirPrefix(config) + getDepsCacheSuffix(config, ssr) } +function getProcessingDepsCacheDir(config: ResolvedConfig, ssr: boolean) { + return ( + getDepsCacheDirPrefix(config) + + getDepsCacheSuffix(config, ssr) + + getTempSuffix() + ) +} + +function getTempSuffix() { + return ( + '_temp_' + + getHash(Date.now().toString() + Math.random().toString(16).slice(8)) + ) +} + function getDepsCacheDirPrefix(config: ResolvedConfig): string { return normalizePath(path.resolve(config.cacheDir, 'deps')) } @@ -1330,63 +1334,69 @@ export async function optimizedDepNeedsInterop( return depInfo?.needsInterop } -const optimizedDepsCache = new WeakMap< - DepOptimizationMetadata, - Map ->() -export async function loadOptimizedDep( - file: string, - depsOptimizer: DepsOptimizer, -): Promise { - const outputFiles = optimizedDepsCache.get(depsOptimizer.metadata) - if (outputFiles) { - const outputFile = outputFiles.get(file) - if (outputFile) return outputFile - } - return fsp.readFile(file, 'utf-8') -} - -/** - * Processes that write to the deps cache directory adds a `_writing` lock to - * inform other processes of so. So before doing any work on it, they can wait - * for the file to be removed to know it's ready. - * - * Returns true if successfully waited for unlock, false if lock timed out. - */ -async function waitOptimizerWriteLock(depsCacheDir: string, logger: Logger) { - const writingPath = path.join(depsCacheDir, '_writing') - const tryAgainMs = 100 - - // if _writing exist, we wait for a maximum of 500ms before assuming something - // is not right - let maxWaitTime = 500 - let waited = 0 - let filesLength: number - - while (fs.existsSync(writingPath)) { - // on the first run, we check the number of files it started with for later use - filesLength ??= (await fsp.readdir(depsCacheDir)).length - - await new Promise((r) => setTimeout(r, tryAgainMs)) - waited += tryAgainMs - - if (waited >= maxWaitTime) { - const newFilesLength = (await fsp.readdir(depsCacheDir)).length - - // after 500ms, if the number of files is the same, assume previous process - // terminated and didn't cleanup `_writing` lock. clear the directory. - if (filesLength === newFilesLength) { - logger.info('Outdated deps cache, forcing re-optimization...') - await fsp.rm(depsCacheDir, { recursive: true, force: true }) - return false - } - // new files were saved, wait a bit longer to decide again. - else { - maxWaitTime += 500 - filesLength = newFilesLength +const MAX_TEMP_DIR_AGE_MS = 24 * 60 * 60 * 1000 +export async function cleanupDepsCacheStaleDirs( + config: ResolvedConfig, +): Promise { + try { + const cacheDir = path.resolve(config.cacheDir) + if (fs.existsSync(cacheDir)) { + const dirents = await fsp.readdir(cacheDir, { withFileTypes: true }) + for (const dirent of dirents) { + if (dirent.isDirectory() && dirent.name.includes('_temp_')) { + const tempDirPath = path.resolve(config.cacheDir, dirent.name) + const stats = await fsp.stat(tempDirPath).catch((_) => null) + if ( + stats?.mtime && + Date.now() - stats.mtime.getTime() > MAX_TEMP_DIR_AGE_MS + ) { + await fsp.rm(tempDirPath, { recursive: true, force: true }) + } + } } } + } catch (err) { + config.logger.error(err) } - - return true } + +// We found issues with renaming folders in some systems. This is a custom +// implementation for the optimizer. It isn't intended to be a general utility + +// Based on node-graceful-fs + +// The ISC License +// Copyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors +// https://github.com/isaacs/node-graceful-fs/blob/main/LICENSE + +// On Windows, A/V software can lock the directory, causing this +// to fail with an EACCES or EPERM if the directory contains newly +// created files. The original tried for up to 60 seconds, we only +// wait for 5 seconds, as a longer time would be seen as an error + +const GRACEFUL_RENAME_TIMEOUT = 5000 +const safeRename = promisify(function gracefulRename( + from: string, + to: string, + cb: (error: NodeJS.ErrnoException | null) => void, +) { + const start = Date.now() + let backoff = 0 + fs.rename(from, to, function CB(er) { + if ( + er && + (er.code === 'EACCES' || er.code === 'EPERM') && + Date.now() - start < GRACEFUL_RENAME_TIMEOUT + ) { + setTimeout(function () { + fs.stat(to, function (stater, st) { + if (stater && stater.code === 'ENOENT') fs.rename(from, to, CB) + else CB(er) + }) + }, backoff) + if (backoff < 100) backoff += 10 + return + } + if (cb) cb(er) + }) +}) diff --git a/packages/vite/src/node/plugins/optimizedDeps.ts b/packages/vite/src/node/plugins/optimizedDeps.ts index 134b8bf313db56..82a1c529adacf2 100644 --- a/packages/vite/src/node/plugins/optimizedDeps.ts +++ b/packages/vite/src/node/plugins/optimizedDeps.ts @@ -1,13 +1,10 @@ +import fsp from 'node:fs/promises' import colors from 'picocolors' import type { ResolvedConfig } from '..' import type { Plugin } from '../plugin' import { DEP_VERSION_RE } from '../constants' import { cleanUrl, createDebugger } from '../utils' -import { - getDepsOptimizer, - loadOptimizedDep, - optimizedDepInfoFromFile, -} from '../optimizer' +import { getDepsOptimizer, optimizedDepInfoFromFile } from '../optimizer' export const ERR_OPTIMIZE_DEPS_PROCESSING_ERROR = 'ERR_OPTIMIZE_DEPS_PROCESSING_ERROR' @@ -70,7 +67,7 @@ export function optimizedDepsPlugin(config: ResolvedConfig): Plugin { // load hooks to avoid race conditions, once processing is resolved, // we are sure that the file has been properly save to disk try { - return loadOptimizedDep(file, depsOptimizer) + return await fsp.readFile(file, 'utf-8') } catch (e) { // Outdated non-entry points (CHUNK), loaded after a rerun throwOutdatedRequest(id) @@ -130,8 +127,7 @@ export function optimizedDepsBuildPlugin(config: ResolvedConfig): Plugin { // Load the file from the cache instead of waiting for other plugin // load hooks to avoid race conditions, once processing is resolved, // we are sure that the file has been properly save to disk - - return loadOptimizedDep(file, depsOptimizer) + return fsp.readFile(file, 'utf-8') }, } } diff --git a/packages/vite/src/node/server/middlewares/transform.ts b/packages/vite/src/node/server/middlewares/transform.ts index 28923c0307f5df..51d92013a018d5 100644 --- a/packages/vite/src/node/server/middlewares/transform.ts +++ b/packages/vite/src/node/server/middlewares/transform.ts @@ -1,4 +1,5 @@ import path from 'node:path' +import fsp from 'node:fs/promises' import type { Connect } from 'dep-types/connect' import colors from 'picocolors' import type { ViteDevServer } from '..' @@ -33,7 +34,7 @@ import { ERR_OPTIMIZE_DEPS_PROCESSING_ERROR, ERR_OUTDATED_OPTIMIZED_DEP, } from '../../plugins/optimizedDeps' -import { getDepsOptimizer, loadOptimizedDep } from '../../optimizer' +import { getDepsOptimizer } from '../../optimizer' const debugCache = createDebugger('vite:cache') const isDebug = !!process.env.DEBUG @@ -80,7 +81,7 @@ export function transformMiddleware( ensureVolumeInPath(path.resolve(root, url.slice(1))), ) try { - const map = await loadOptimizedDep(mapFile, depsOptimizer) + const map = await fsp.readFile(mapFile, 'utf-8') return send(req, res, map, 'json', { headers: server.config.server.headers, }) From a9aa822520b57704a15f791fad7b9f3fb323304f Mon Sep 17 00:00:00 2001 From: patak Date: Mon, 27 Mar 2023 23:50:47 +0200 Subject: [PATCH 2/7] chore: update --- packages/vite/src/node/optimizer/index.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 8a5ee2b7df8cf7..ea5a2ace1d4275 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -488,11 +488,7 @@ export function runOptimizeDeps( // Create a temporal directory so we don't need to delete optimized deps // until they have been processed. This also avoids leaving the deps cache // directory in a corrupted state if there is an error - if (fs.existsSync(processingCacheDir)) { - emptyDir(processingCacheDir) - } else { - fs.mkdirSync(processingCacheDir, { recursive: true }) - } + fs.mkdirSync(processingCacheDir, { recursive: true }) // a hint for Node.js // all files in the cache directory should be recognized as ES modules @@ -558,7 +554,7 @@ export function runOptimizeDeps( } } - const canceledResult: DepOptimizationResult = { + const cancelledResult: DepOptimizationResult = { metadata, commit: async () => cleanUp(), cancel: cleanUp, @@ -582,7 +578,7 @@ export function runOptimizeDeps( } if (!context || optimizerContext.cancelled) { disposeContext() - return canceledResult + return cancelledResult } return context @@ -665,7 +661,7 @@ export function runOptimizeDeps( if (e.errors && e.message.includes('The build was canceled')) { // esbuild logs an error when cancelling, but this is expected so // return an empty result instead - return canceledResult + return cancelledResult } throw e }) @@ -970,7 +966,7 @@ function getProcessingDepsCacheDir(config: ResolvedConfig, ssr: boolean) { function getTempSuffix() { return ( '_temp_' + - getHash(Date.now().toString() + Math.random().toString(16).slice(8)) + getHash(Date.now().toString() + Math.random().toString(16).slice(2)) ) } From acd699b927d8040bdf1c3d53703b022e5845f0c1 Mon Sep 17 00:00:00 2001 From: patak Date: Tue, 28 Mar 2023 00:24:52 +0200 Subject: [PATCH 3/7] fix: ensure there is a _metadata.json when there aren't deps --- packages/vite/src/node/optimizer/index.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index ea5a2ace1d4275..d4a68008845d5e 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -525,6 +525,12 @@ export function runOptimizeDeps( metadata, cancel: cleanUp, commit: async () => { + const dataPath = path.join(processingCacheDir, '_metadata.json') + fs.writeFileSync( + dataPath, + stringifyDepsOptimizerMetadata(metadata, depsCacheDir), + ) + // Write metadata file, delete `deps` folder and rename the `processing` folder to `deps` // Processing is done, we can now replace the depsCacheDir with processingCacheDir // Rewire the file paths from the temporal processing dir to the final deps cache dir @@ -644,12 +650,6 @@ export function runOptimizeDeps( } } - const dataPath = path.join(processingCacheDir, '_metadata.json') - fs.writeFileSync( - dataPath, - stringifyDepsOptimizerMetadata(metadata, depsCacheDir), - ) - debug( `Dependencies bundled in ${(performance.now() - start).toFixed(2)}ms`, ) From 4135c030acd62c2937665e55619bf2e41d06971c Mon Sep 17 00:00:00 2001 From: patak Date: Tue, 28 Mar 2023 17:58:59 +0200 Subject: [PATCH 4/7] chore: update --- packages/vite/src/node/optimizer/index.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index d4a68008845d5e..cdc0334e8ecf41 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -525,23 +525,30 @@ export function runOptimizeDeps( metadata, cancel: cleanUp, commit: async () => { + // Write metadata file, then commit the processing folder to the global deps cache + // Rewire the file paths from the temporal processing dir to the final deps cache dir + const dataPath = path.join(processingCacheDir, '_metadata.json') fs.writeFileSync( dataPath, stringifyDepsOptimizerMetadata(metadata, depsCacheDir), ) - // Write metadata file, delete `deps` folder and rename the `processing` folder to `deps` - // Processing is done, we can now replace the depsCacheDir with processingCacheDir - // Rewire the file paths from the temporal processing dir to the final deps cache dir + // In order to minimize the time where the deps folder isn't in a consistent state, + // we first rename the old depsCacheDir to a temporal path, then we rename the + // new processing cache dir to the depsCacheDir. In systems where doing so in sync + // is safe, we do an atomic operation (at least for this thread). For Windows, we + // found there are cases where the rename operation may finish before it's done + // so we do a graceful rename checking that the folder has been properly renamed. + // We found that the rename-rename (then delete the old folder in the background) + // is safer than a delete-rename operation. const temporalPath = depsCacheDir + getTempSuffix() const depsCacheDirPresent = fs.existsSync(depsCacheDir) - if (isWindows) { - depsCacheDirPresent && (await safeRename(depsCacheDir, temporalPath)) + if (depsCacheDirPresent) await safeRename(depsCacheDir, temporalPath) await safeRename(processingCacheDir, depsCacheDir) } else { - depsCacheDirPresent && fs.renameSync(depsCacheDir, temporalPath) + if (depsCacheDirPresent) fs.renameSync(depsCacheDir, temporalPath) fs.renameSync(processingCacheDir, depsCacheDir) } From fe382f06be8ca47ca29c8dcc9c8a0c49d1c864cb Mon Sep 17 00:00:00 2001 From: patak Date: Tue, 28 Mar 2023 20:16:47 +0200 Subject: [PATCH 5/7] chore: update Co-authored-by: Dominik G. --- packages/vite/src/node/optimizer/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index cdc0334e8ecf41..2e4b398b1bcb27 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -553,7 +553,7 @@ export function runOptimizeDeps( } // Delete temporal path in the background - fsp.rm(temporalPath, { recursive: true, force: true }) + if(depsCacheDirPresent) fsp.rm(temporalPath, { recursive: true, force: true }) }, } From b397addaab15f2ef2c202c1acffd6a9e93c36eeb Mon Sep 17 00:00:00 2001 From: patak Date: Tue, 28 Mar 2023 20:17:27 +0200 Subject: [PATCH 6/7] chore: lint --- packages/vite/src/node/optimizer/index.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index 2e4b398b1bcb27..e5daef42df44a7 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -553,7 +553,8 @@ export function runOptimizeDeps( } // Delete temporal path in the background - if(depsCacheDirPresent) fsp.rm(temporalPath, { recursive: true, force: true }) + if (depsCacheDirPresent) + fsp.rm(temporalPath, { recursive: true, force: true }) }, } From 7365f0f5cd1215c1865491efb11a15f715ef0804 Mon Sep 17 00:00:00 2001 From: patak Date: Tue, 28 Mar 2023 20:20:24 +0200 Subject: [PATCH 7/7] chore: use process.pid in temp hash --- packages/vite/src/node/optimizer/index.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index e5daef42df44a7..d2079064004c69 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -974,7 +974,11 @@ function getProcessingDepsCacheDir(config: ResolvedConfig, ssr: boolean) { function getTempSuffix() { return ( '_temp_' + - getHash(Date.now().toString() + Math.random().toString(16).slice(2)) + getHash( + `${process.pid}:${Date.now().toString()}:${Math.random() + .toString(16) + .slice(2)}`, + ) ) }