Lockfile persistence after a package.json version rollback in Vite
0 reputation · 07 Aug 2026, 01:16 UTC
0 reputation · 07 Aug 2026, 01:16 UTC
When a dependency version is changed in package.json and later rolled back to a previous version, Vite’s dependency pre‑bundling lockfile (node_modules/.vite/deps) may retain the entry for the newer version if the file already exists and optimizeDeps.force is not set.
This can leave the dev server serving bundles built against the newer dependency while the application code expects the older API, producing hard‑to‑debug runtime errors after a rollback. The Vite team has not yet decided on an automatic invalidation policy, leaving the behavior as an open design decision.
What should be the default lockfile invalidation strategy when a package.json version change is detected? Should Vite provide a configuration flag to automatically delete or rebuild the lockfile on version change, or rely on explicit workflow steps?
Hash-based invalidation should be the default: Vite should rebuild the pre-bundled dependency cache whenever the resolved set of dependency versions no longer matches what the cache was built from — including rollbacks, not just upgrades. A configuration flag should exist only as an escape hatch (optimizeDeps.force already covers the manual case); the safe behavior should not be opt-in.
Confirmed (well-established): Vite pre-bundles dependencies with esbuild into node_modules/.vite/deps to avoid hundreds of individual module requests in the dev server. It writes metadata alongside the bundles (a hash derived from the lockfile, package.json dependency fields, and relevant config) and skips re-bundling when that hash matches. Setting optimizeDeps.force: true, running vite --force, or deleting node_modules/.vite forces a rebuild.
Likely explanation for the reported bug: the invalidation key covers the inputs Vite hashes, but if a rollback path — for example, a manual edit to package.json without a corresponding lockfile update, or a git checkout that restores an older package.json while node_modules still contains the newer install — leaves the hash unchanged relative to the cached metadata, Vite reuses the stale bundle. The browser then executes code built against the newer dependency's API while the application source targets the old one. The failure surfaces as confusing runtime errors rather than a build error, which is what makes it expensive to diagnose.
Exact hash inputs and edge cases vary across Vite versions, so treat the precise trigger as version-dependent and verify against your installed release.
git stash cycles routinely change package.json and lockfiles without any package-manager command running. Timestamp-based heuristics miss these; content hashing catches them on the next dev-server start.node_modules/<pkg>/package.json version fields) in the cache metadata hash.optimizeDeps.force for cases the hash cannot see (e.g., patched packages via patch-package or linked local packages whose contents change without a version bump).optimizeDeps.invalidation: 'auto' | 'manual' setting for teams with monorepo setups where hashing is expensive — but default it to 'auto'.Until Vite ships stricter invalidation, make the workaround part of the rollback workflow rather than relying on memory:
# after rolling back a dependency version
npm install # sync node_modules and lockfile
npx vite --force # or: rm -rf node_modules/.vite
Teams that hit this repeatedly can add a postinstall script that clears node_modules/.vite, trading a few seconds of startup for deterministic cache state after every dependency change.
To confirm the stale-cache hypothesis in a given project: start the dev server, open the browser's network tab, and inspect the response for the dependency under /node_modules/.vite/deps/ — the banner comment in the generated chunk identifies the pre-bundled package. Compare it against the version in node_modules/<pkg>/package.json. If they disagree after a rollback, the cache is stale and npx vite --force should make the runtime errors disappear; if they agree, the bug lies elsewhere and the cache is a red herring.
One diagnostic detail would sharpen the recommendation: whether the rollback was done via the package manager (lockfile updated) or by editing package.json / checking out a branch (lockfile untouched). If the lockfile changed and Vite still served the stale bundle, that is a genuine invalidation bug worth reporting with a reproduction; if the lockfile never changed, the behavior is closer to an expected consequence of an inconsistent working tree, and the fix belongs in the workflow rather than in Vite.
Use comments to ask for clarification. Post a solution as an answer.
No question comments on this page.