diff --git a/docs/guide/dep-pre-bundling.md b/docs/guide/dep-pre-bundling.md index 4ea53feac36cf6..e0cc12ccc41276 100644 --- a/docs/guide/dep-pre-bundling.md +++ b/docs/guide/dep-pre-bundling.md @@ -77,9 +77,10 @@ Both `include` and `exclude` can be used to deal with this. If the dependency is Vite caches the pre-bundled dependencies in `node_modules/.vite`. It determines whether it needs to re-run the pre-bundling step based on a few sources: -- The `dependencies` list in your `package.json`. -- Package manager lockfiles, e.g. `package-lock.json`, `yarn.lock`, or `pnpm-lock.yaml`. +- Package manager lockfile content, e.g. `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml` or `bun.lockb`. +- Patches folder modification time. - Relevant fields in your `vite.config.js`, if present. +- `NODE_ENV` value. The pre-bundling step will only need to be re-run when one of the above has changed. diff --git a/packages/vite/src/node/optimizer/index.ts b/packages/vite/src/node/optimizer/index.ts index caf4f2aa5efacf..7f904bc17bccc6 100644 --- a/packages/vite/src/node/optimizer/index.ts +++ b/packages/vite/src/node/optimizer/index.ts @@ -1042,14 +1042,36 @@ function isSingleDefaultExport(exports: readonly string[]) { } const lockfileFormats = [ - 'package-lock.json', - 'yarn.lock', - 'pnpm-lock.yaml', - 'bun.lockb' + { name: 'package-lock.json', patchesDirs: ['patches'] }, // Default of https://github.com/ds300/patch-package + { name: 'yarn.lock', patchesDirs: ['patches', '.yarn/patches'] }, // .yarn/patches for v2+ + { name: 'pnpm-lock.yaml', patchesDirs: [] }, // Included in lockfile + { name: 'bun.lockb', patchesDirs: ['patches'] } ] export function getDepHash(config: ResolvedConfig, ssr: boolean): string { - let content = lookupFile(config.root, lockfileFormats) || '' + const lockfilePath = lookupFile( + config.root, + lockfileFormats.map((l) => l.name), + { pathOnly: true } + ) + let content = lockfilePath ? fs.readFileSync(lockfilePath, 'utf-8') : '' + if (lockfilePath) { + const lockfileName = path.basename(lockfilePath) + const { patchesDirs } = lockfileFormats.find( + (f) => f.name === lockfileName + )! + const dependenciesRoot = path.dirname(lockfilePath) + for (const patchesDir of patchesDirs) { + const fullPath = path.join(dependenciesRoot, patchesDir) + if (fs.existsSync(fullPath)) { + const stats = fs.statSync(fullPath) + if (stats.isDirectory()) { + content += stats.mtimeMs.toString() + break + } + } + } + } // also take config into account // only a subset of config options that can affect dep optimization const optimizeDeps = getDepOptimizationConfig(config, ssr)