Skip to content

fix: delete no longer referenced files from the filesystem cache directory - #21528

Merged
alexander-akait merged 16 commits into
mainfrom
fix/cache-cleanup-unused-files
Jul 28, 2026
Merged

fix: delete no longer referenced files from the filesystem cache directory#21528
alexander-akait merged 16 commits into
mainfrom
fix/cache-cleanup-unused-files

Conversation

@bjohansebas

@bjohansebas bjohansebas commented Jul 27, 2026

Copy link
Copy Markdown
Member

Summary

Fixes #13291. The filesystem cache directory grows without bound because files orphaned by cache invalidations (version/config changes, compression changes, stale index.pack.old) are never removed — up to 27 GB reported on CI. After a successful store, the strategy now deletes files that are no longer reachable from the stored index: it collects written and retained file names during serialization (decoding retained lazy pointers, the part that blocked #14661), walks retained files on disk for nested references (header + pointer ranges only, memoized across stores), and unlinks unreferenced files older than a 30-minute grace period so concurrent builds sharing the directory are never disturbed. Any walk error aborts the whole cleanup (never delete with an incomplete live set), and the cleanup runs in the idle store phase, off the build's critical path (~100 µs per deleted file, one-time; build times unchanged in benchmarks).

What kind of change does this PR introduce?

fix

Did you add tests for your changes?

Yes — integration cases in test/PersistentCaching.test.js (orphan deleted, fresh files kept, cache restores fully afterwards), direct strategy tests in test/PackFileCacheStrategyCleanup.test.js (nested retained walk, grace period, memoization/invalidation), and walker unit tests in test/FileMiddleware.unittest.js (pointer parsing, compression variants, truncated/corrupt files); all verified via mutation testing to fail when the fix is removed.

Does this PR introduce a breaking change?

No — only files unreachable from the just-stored cache index are deleted, so no valid cache is ever invalidated; filesystems without unlink skip the cleanup entirely. Known limitation: compressed packs > 2 GB abort the cleanup with a warning (uncompressed packs are read by byte range and have no such limit).

If relevant, what needs to be documented once your changes are merged or what have you already documented?

n/a

Use of AI

This PR was developed with the assistance of Claude Code (Anthropic): investigation of the issue and prior PRs (#13875, #14661), implementation, tests, benchmarks, and mutation-testing verification were done by the AI under my direction and review; I validated the approach and results.


Note

Medium Risk
Touches persistent cache on disk and concurrent shared cache dirs; mistakes could delete still-needed packs, though abort-on-error and the grace period mitigate that.

Overview
Fixes unbounded growth of the filesystem cache directory by deleting pack files that are no longer reachable from the index after a successful store.

PackFileCacheStrategy now runs post-store cleanup when the filesystem supports unlink: it builds a live file set from the new index, files written in that store, and retained lazy segments (plus a BFS walk of nested references via getReferencedFilenames). Anything else in the cache dir that is a regular file and older than a 30-minute grace period is unlinked. Walk/parse failures abort the whole cleanup (warning only, no partial deletes); failed stores clear the reference memo.

FileMiddleware records writtenFiles / retainedFiles during serialization (including names from reused lazy pointer buffers) and exports getReferencedFilenames to read pointer targets from pack headers without full deserialization (byte-range reads for uncompressed packs; full decompress for .gz/.br/.zst, with corrupt-file guards).

Integration and strategy tests cover orphans, grace period, nested retention, memoization, concurrent in-place rewrites, and entry-churn pack expiry.

Reviewed by Cursor Bugbot for commit c310c1a. Bugbot is set up for automated code reviews on this repo. Configure here.

@changeset-bot

changeset-bot Bot commented Jul 27, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: c310c1a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
webpack Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

This PR is packaged and the instant preview is available (964bbfa).

Install it locally:

  • npm
npm i -D webpack@https://pkg.pr.new/webpack@964bbfa
  • yarn
yarn add -D webpack@https://pkg.pr.new/webpack@964bbfa
  • pnpm
pnpm add -D webpack@https://pkg.pr.new/webpack@964bbfa

@codecov

codecov Bot commented Jul 27, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 94.35897% with 11 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.81%. Comparing base (fbcbe3e) to head (c310c1a).
⚠️ Report is 13 commits behind head on main.

Files with missing lines Patch % Lines
lib/serialization/FileMiddleware.js 91.40% 11 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #21528      +/-   ##
==========================================
+ Coverage   93.79%   93.81%   +0.02%     
==========================================
  Files         620      620              
  Lines       73798    73504     -294     
  Branches    21306    21251      -55     
==========================================
- Hits        69220    68961     -259     
+ Misses       4578     4543      -35     
Flag Coverage Δ
css-parsing 25.59% <ø> (+0.05%) ⬆️
html5lib 27.02% <ø> (+0.05%) ⬆️
integration 89.59% <76.92%> (-0.01%) ⬇️
test262 43.37% <ø> (+0.09%) ⬆️
unit 47.24% <48.20%> (-0.20%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@codspeed-hq

codspeed-hq Bot commented Jul 27, 2026

Copy link
Copy Markdown

Merging this PR will regress 2 benchmarks

⚠️ Different runtime environments detected

Some benchmarks with significant performance changes were compared across different runtime environments,
which may affect the accuracy of the results.

Open the report in CodSpeed to investigate

⚡ 1 improved benchmark
❌ 2 regressed benchmarks
✅ 213 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Memory benchmark "many-modules-esm", scenario '{"name":"mode-production","mode":"production"}' 7.5 MB 9.6 MB -21.86%
Memory benchmark "many-chunks-commonjs", scenario '{"name":"mode-production","mode":"production"}' 8 MB 10.1 MB -21.14%
Memory benchmark "devtool-eval", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 3.1 MB 1.3 MB ×2.4

Tip

Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.


Comparing fix/cache-cleanup-unused-files (c310c1a) with main (ec39088)

Open in CodSpeed

@bjohansebas
bjohansebas marked this pull request as ready for review July 27, 2026 03:03
@cursor

cursor Bot commented Jul 27, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
Post-store deletion touches the persistent cache directory and must keep the reference graph complete; mitigations include the grace period, abort-on-walk-error, and only deleting files not in the live set.

Overview
Fixes unbounded growth of the filesystem cache by removing pack files that are no longer reachable from the index after a successful store.

Serialization now records which pack segments were written in the current run and which were retained via existing lazy pointers (without re-writing them). getReferencedFilenames in FileMiddleware walks those on-disk files to discover nested references (header/pointer sections only, with gzip/brotli/zstd support and guards against corrupt huge sections).

Cleanup (_cleanupUnusedFiles) builds the live file set from the index plus written/retained names and transitive references (memoized across stores), then unlinks other cache files only if they are regular files and older than a 30-minute grace period (to avoid racing concurrent CI builds). Walk or readdir failures abort deletion; failed stores clear the reference memo; filesystems without unlink skip cleanup entirely.

Reviewed by Cursor Bugbot for commit 00002f0. Bugbot is set up for automated code reviews on this repo. Configure here.

@alexander-akait alexander-akait left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed the cache-cleanup logic end to end (serialize instrumentation, the on-disk reference walker, and _cleanupUnusedFiles). The design is careful and fail-safe by construction — retained packs are correctly detected via their existing lazy pointer (getLazySerializedValue), the walk is transitive and memoized, and walk/readdir errors abort the whole cleanup. I could not find a data-loss or crash bug in the common paths. Two observations below.

1. Compressed reference walker can under-report silently (defense-in-depth). See the inline comment on parsePointerNames: unlike the uncompressed path, it doesn't bounds-check sections, so an internally-inconsistent-but-decompressable file yields an incomplete name list without erroring — which can let _cleanupUnusedFiles delete a still-referenced pack. Narrow window, but it breaks the "never delete with an incomplete live set" invariant for that path. Fix suggestion is in the inline comment.

2. Grace period vs. cache-restore mtime (question, not a blocker). The 30-min grace period keys off mtimeMs. If a CI cache restore refreshes file mtimes to "now" (some restore mechanisms do; tar-based ones preserve them), orphans in a restored cache look fresh, so a build shorter than 30 min would never age them past the grace period and the directory would keep growing across runs — the exact scenario #13291 is about. The code comment shows you considered this; could you confirm the intended behavior for sub-30-min CI builds that restore the cache each run? If restore preserves mtimes this is a non-issue.

Non-blocking notes:

  • Version bump — patch is correct. No schema/config/public-API change; this is a behavioral bug fix for unbounded cache growth (#13291), and it's not breaking (only files unreachable from the just-stored index are removed; unlink-less filesystems skip cleanup). It's not minor (no new capability/option) nor major (no breaking change).
  • CodSpeed memory regression looks like noise. The flagged benchmark (many-modules-commonjs, production) configures no filesystem cache, so none of this PR's code runs in it; combined with CodSpeed's own "different runtime environments"/"7 commits behind" warnings, the 8.5→11.3 MB delta almost certainly isn't from this change. Worth a re-run / acknowledge rather than a code change.

Generated by Claude Code

Comment thread lib/serialization/FileMiddleware.js Outdated
const length = buf.readInt32LE(8 + i * 4);
if (length < 0) {
// pointer section: u64 size + utf-8 file name
names.push(buf.toString("utf8", offset + 8, offset - length));

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Compressed walker can silently under-report references → risk of deleting a still-referenced pack.

parsePointerNames walks the section table but never validates that a section stays inside buf, whereas getReferencedFilenamesUncompressed does (it fail()s on EOF / oversize reads). So the two paths diverge on a file that decompresses cleanly but whose section header is internally inconsistent (e.g. a positive content length larger than the actual bytes present): the running offset drifts past the end, and here buf.toString("utf8", offset + 8, offset - length) just clamps to the buffer end and pushes "" instead of the real name — no error is thrown.

Reproduced against this exact function (2 sections: a content length that lies + one real pointer to REFERENCED-FILE):

compressed   -> [""]                              // real reference MISSED, no throw
uncompressed -> throws "Unexpected end of file"   // fail-safe, aborts cleanup

Because _cleanupUnusedFiles deletes every file not in the live set, an under-reported list from a retained compressed pack can drop a genuinely-referenced file from liveFiles and unlink it once it's past the grace period. That contradicts the PR's own invariant ("Any walk error aborts the whole cleanup — never delete with an incomplete live set"): for the compressed path the walk can produce an incomplete set without erroring.

It's a narrow window (the compression layer's own integrity checks make internal inconsistency unlikely), but given the whole feature is about the safety of deletion it's worth closing. Suggestion: make parsePointerNames validate as it walks and throw on any inconsistency, mirroring the uncompressed path — e.g. reject when offset would move past buf.length, when a pointer's end (offset - length) exceeds buf.length, or when the final offset !== buf.length. Then a corrupt compressed file aborts the cleanup instead of quietly shrinking the live set.

A second, lower-severity note on the same walker: MAX_HEADER_OR_POINTER_SIZE is applied to the section-lengths read (readAt(8, sectionCount * 4)) in the uncompressed path, so a file with a genuinely huge sectionCount is rejected as Invalid section size — fail-safe, but the message is misleading; a dedicated sectionCount sanity check would read clearer.


Generated by Claude Code

@alexander-akait alexander-akait left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Posted the concrete fix for the compressed-walker under-reporting issue as an applicable suggestion on parsePointerNames (click "Apply suggestion" to commit it). It adds bounds validation so a corrupt-but-decompressable file aborts the cleanup instead of quietly handing back an incomplete live set — upholding the "never delete with an incomplete live set" invariant on the compressed path too.


Generated by Claude Code

Comment thread lib/serialization/FileMiddleware.js
@alexander-akait

Copy link
Copy Markdown
Member

@bjohansebas let’s fix and we can merge

Comment thread lib/serialization/FileMiddleware.js Outdated

@alexander-akait alexander-akait left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed the Cursor Bugbot finding ("Uncompressed walker skips size check") with an applicable suggestion on getReferencedFilenamesUncompressed. It's the mirror of the compressed-path fix that already landed: verify the section table sums to exactly the file size before trusting pointer offsets, so the default (no-compression) path also fails safe instead of under-reporting the live set. Click "Apply suggestion" to commit it.


Generated by Claude Code

Comment thread lib/serialization/FileMiddleware.js
Comment thread test/FileMiddleware.unittest.js

@alexander-akait alexander-akait left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The size-check I suggested earlier introduced the two CI failures — here are the fixes as applicable suggestions:

  • lint (Prettier): the inline-cast if (…) line runs ~87 cols over the 80 printWidth. Suggestion 1 extracts the cast to a local (76 cols).
  • basic / unit tests: getReferencedFilenamesUncompressed now calls fs.stat, but the fsWithFile mock has no stat, so every uncompressed case throws fs.stat is not a function. Suggestion 2 adds a stat returning the buffer's real size (equal to the section-table total for a valid file, so existing cases stay green).
  • codecov/patch: Suggestion 3 adds two cases covering the new size-mismatch and stat-error branches.

Apply all three, then a yarn lint / yarn test:unit locally should come back clean. I couldn't run the suite in my environment to fully verify formatting (dependency install is blocked here), so a quick yarn fix before pushing will catch any stray Prettier nit.


Generated by Claude Code

Comment thread lib/serialization/FileMiddleware.js
Comment thread test/FileMiddleware.unittest.js
Comment thread test/FileMiddleware.unittest.js
Comment thread lib/cache/PackFileCacheStrategy.js

@alexander-akait alexander-akait left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The lint failure this round is lint:types-test (tsc), not Prettier: the two new coverage tests assign fs.stat = (…) where fs is typed IntermediateFileSystem, so _file: string isn't assignable to Stat's PathLike param (TS2322 at lines 227 and 239). The two suggestions cast each fs handle to EXPECTED_ANY — the same pattern fsWithFile and the "rejects on read errors" test already use — which clears both errors without touching the assertions. unit, basic, codecov/patch, and integration are all green on this commit.

I'll follow up separately on the new Bugbot review (the stale-memo finding).


Generated by Claude Code

Comment thread test/FileMiddleware.unittest.js Outdated
Comment thread test/FileMiddleware.unittest.js

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fd01272. Configure here.

Comment thread test/FileMiddleware.unittest.js
alexander-akait and others added 2 commits July 27, 2026 18:36
Restore the missing content binding and drop the duplicated fs
declaration that a mis-anchored suggestion left in the stat-error case.
@bjohansebas
bjohansebas force-pushed the fix/cache-cleanup-unused-files branch from eaba921 to c310c1a Compare July 27, 2026 22:54
@github-actions

Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging fix/cache-cleanup-unused-files into main will be
99.32%
Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
bin
   webpack.js98.82%100%100%98.82%103
examples
   build-common.js100%100%100%100%
   buildAll.js100%100%100%100%
   examples.js100%100%100%100%
   template-common.js98.21%100%100%98.21%72
examples/custom-javascript-parser
   test.filter.js100%100%100%100%
examples/custom-javascript-parser/internals
   acorn-parse.js100%100%100%100%
   meriyah-parse.js100%100%100%100%
   oxc-parse.js100%100%100%100%
examples/markdown
   webpack.config.mjs100%100%100%100%
examples/module-federation
   test.filter.js100%100%100%100%
examples/reexport-components
   test.filter.js100%100%100%100%
examples/typescript
   test.filter.js100%100%100%100%
examples/typescript-non-erasable
   test.filter.js50%100%100%50%5
examples/virtual-modules
   test.filter.js100%100%100%100%
examples/wasm-bindgen-esm
   test.filter.js100%100%100%100%
examples/wasm-complex
   test.filter.js100%100%100%100%
examples/wasm-emscripten
   test.filter.js100%100%100%100%
examples/wasm-simple
   test.filter.js100%100%100%100%
examples/wasm-simple-source-phase
   test.filter.js100%100%100%100%
lib
   APIPlugin.js100%100%100%100%
   AsyncDependenciesBlock.js100%100%100%100%
   AutomaticPrefetchPlugin.js100%100%100%100%
   BannerPlugin.js100%100%100%100%
   Cache.js98.21%100%100%98.21%101
   CacheFacade.js100%100%100%100%
   Chunk.js99.72%100%100%99.72%39
   ChunkGraph.js100%100%100%100%
   ChunkGroup.js100%100%100%100%
   ChunkTemplate.js100%100%100%100%
   CircularModulesPlugin.js98.81%100%100%98.81%136
   CleanPlugin.js99.12%100%100%99.12%207, 227
   CodeGenerationResults.js100%100%100%100%
   CompatibilityPlugin.js100%100%100%100%
   Compilation.js98.42%100%100%98.42%1639, 1958, 1965, 1973, 1995, 1998, 2937, 3416–3417, 3449, 4153, 4183, 4236–4237, 4241, 4246, 4262–4263, 4277–4278, 4283–4284, 4764, 4790, 527, 532, 5598, 5630, 5647, 5663, 5679, 5694, 5719–5720, 5722, 6052, 6057, 6063, 6066, 6073, 6085, 6087, 6091, 6107, 6122, 6154, 6208, 6232, 6347, 778–779
   Compiler.js99.56%100%100%99.56%1147–1148, 1156
   ConcatenationScope.js98.65%100%100%98.65%195
   ConditionalInitFragment.js100%100%100%100%
   ConstPlugin.js100%100%100%100%
   ContextExclusionPlugin.js100%100%100%100%
   ContextModule.js99.88%100%100%99.88%1461
   ContextModuleFactory.js97.20%100%100%97.20%266, 435, 456, 461, 501, 512, 514, 518, 527–528
   ContextReplacementPlugin.js100%100%100%100%
   DefinePlugin.js99.08%100%100%99.08%1074, 176–177, 193, 212, 286
   DependenciesBlock.js100%100%100%100%
   Dependency.js98.51%100%100%98.51%479, 525
   DependencyTemplate.js100%100%100%100%
   DependencyTemplates.js100%100%100%100%
   DotenvPlugin.js98.41%100%100%98.41%378, 391–392
   DynamicEntryPlugin.js100%100%100%100%
   EntryOptionPlugin.js100%100%100%100%
   EntryPlugin.js100%100%100%100%
   Entrypoint.js100%100%100%100%
   EnvironmentPlugin.js97.14%100%100%97.14%49
   ErrorHelpers.js100%100%100%100%
   EvalDevToolModulePlugin.js100%100%100%100%
   EvalSourceMapDevToolPlugin.js100%100%100%100%
   ExportsInfo.js100%100%100%100%
   ExportsInfoApiPlugin.js100%100%100%100%
   ExternalModule.js98.65%100%100%98.65%1196, 1199, 514–518, 520, 666
   ExternalModuleFactoryPlugin.js100%100%100%100%
   ExternalsPlugin.js100%100%100%100%
   FileSystemInfo.js99.16%100%100%99.16%1267, 1269–1274, 1281, 1284, 182, 2502–2503, 2506, 2517, 2528, 2539, 280, 3976, 3991, 4015
   FlagAllModulesAsUsedPlugin.js100%100%100%100%
   FlagDependencyExportsPlugin.js98.21%100%100%98.21%448, 457, 460, 464, 476
   FlagDependencyUsagePlugin.js100%100%100%100%
   FlagEntryExportAsUsedPlugin.js100%100%100%100%
   Generator.js100%100%100%100%
   HotModuleReplacementPlugin.js100%100%100%100%
   HotUpdateChunk.js100%100%100%100%
   IgnorePlugin.js100%100%100%100%
   IgnoreWarningsPlugin.js100%100%100%100%
   InitFragment.js100%100%100%100%
   JavascriptMetaInfoPlugin.js100%100%100%100%
   LazyBarrel.js100%100%100%100%
   LibraryTemplatePlugin.js100%100%100%100%
   LoaderOptionsPlugin.js100%100%100%100%
   LoaderTargetPlugin.js100%100%100%100%
   MainTemplate.js100%100%100%100%
   ManifestPlugin.js100%100%100%100%
   Module.js98.50%100%100%98.50%1288, 1293, 1353, 1367, 1429, 1438
   ModuleFactory.js100%100%100%100%
   ModuleFilenameHelpers.js98.85%100%100%98.85%106, 108
   ModuleGraph.js99.73%100%100%99.73%1005
   ModuleGraphConnection.js100%100%100%100%
   ModuleInfoHeaderPlugin.js100%100%100%100%
   ModuleNotFoundError.js100%100%100%100%
   ModuleProfile.js100%100%100%100%
   ModuleSourceTypeConstants.js100%100%100%100%
   ModuleTemplate.js100%100%100%100%
   ModuleTypeConstants.js100%100%100%100%
   MultiCompiler.js99.70%100%100%99.70%663
   MultiStats.js100%100%100%100%
   MultiWatching.js100%100%100%100%
   NoEmitOnErrorsPlugin.js100%100%100%100%
   NodeStuffPlugin.js100%100%100%100%
   NormalModule.js97.98%100%100%97.98%1014, 1031, 1279, 1313, 1329, 1776, 2073, 2078–2088, 34, 994, 997
   NormalModuleFactory.js98.72%100%100%98.72%1117, 1385, 1396, 1406, 1457–1459, 1466, 520, 532
   NormalModuleReplacementPlugin.js100%100%100%100%
   NullFactory.js100%100%100%100%
   OptimizationStages.js100%100%100%100%
   OptionsApply.js100%100%100%100%
   Parser.js100%100%100%100%
   PlatformPlugin.js100%100%100%100%
   PrefetchPlugin.js100%100%100%100%
   ProgressPlugin.js99.80%100%100%99.80%691
   ProvidePlugin.js100%100%100%100%
   RawModule.js100%100%100%100%
   RecordIdsPlugin.js100%100%100%100%
   RequestShortener.js100%100%100%100%
   ResolverFactory.js100%100%100%100%
   RuntimeGlobals.js100%100%100%100%
   RuntimeModule.js100%100%100%100%
   RuntimePlugin.js100%100%100%100%
   RuntimeTemplate.js100%100%100%100%
   SelfModuleFactory.js100%100%100%100%
   SingleEntryPlugin.js100%100%100%100%
   SourceMapDevToolModuleOptionsPlugin.js100%100%100%100%
   SourceMapDevToolPlugin.js98.62%100%100%98.62%220, 224, 226, 419, 430, 889
   Stats.js100%100%100%100%
   Template.js100%100%100%100%
   TemplatedPathPlugin.js99.43%100%100%99.43%308–309
   UseStrictPlugin.js100%100%100%100%
   WarnCaseSensitiveModulesPlugin.js100%100%100%100%
   WarnDeprecatedOptionPlugin.js100%100%100%100%
   WarnNoModeSetPlugin.js100%100%100%100%
   WatchIgnorePlugin.js100%100%100%100%
   Watching.js100%100%100%100%
   WebpackError.js100%100%100%100%
   WebpackIsIncludedPlugin.js100%100%100%100%
   WebpackOptionsApply.js100%100%100%100%
   WebpackOptionsDefaulter.js100%100%100%100%
   buildChunkGraph.js99.87%100%100%99.87%371
   cli.js98.63%100%100%98.63%10, 119, 549, 581, 631, 905
   index.js99.72%100%100%99.72%184
   validateSchema.js94.67%100%100%94.67%100, 87, 89, 98
   webpack.js97.10%100%100%97.10%10, 263, 285, 287
lib/asset
   AssetBytesGenerator.js100%100%100%100%
   AssetBytesParser.js100%100%100%100%
   AssetGenerator.js100%100%100%100%
   AssetModule.js100%100%100%100%
   AssetModulesPlugin.js97.95%100%100%97.95%295, 319, 322, 42, 452, 47
   AssetParser.js100%100%100%100%
   AssetSourceGenerator.js100%100%100%100%
   AssetSourceParser.js100%100%100%100%
   RawDataUrlModule.js100%100%100%100%
   WebManifestGenerator.js100%100%100%100%
   WebManifestParser.js100%100%100%100%
lib/async-modules
   AsyncModuleHelpers.js100%100%100%100%
   AwaitDependenciesInitFragment.js100%100%100%100%
   InferAsyncModulesPlugin.js100%100%100%100%
   isGeneratorLowered.js100%100%100%100%
lib/bun
   BunTargetPlugin.js100%100%100%100%
lib/cache
   AddBuildDependenciesPlugin.js100%100%100%100%
   AddManagedPathsPlugin.js100%100%100%100%
   IdleFileCachePlugin.js97.92%100%100%97.92%75, 87, 95
   MemoryCachePlugin.js95.83%100%100%95.83%33
   MemoryWithGcCachePlugin.js93.15%100%100%93.15%107, 114–115, 123, 90
   PackFileCacheStrategy.js96.48%100%100%96.48%1268, 1368, 1372, 1434, 1699, 1716, 633, 652, 662–664, 666, 682–683, 688, 691, 693, 698, 703, 728, 734, 768, 774, 780, 785, 796, 805, 810–811, 813, 830, 836–837, 839
   ResolverCachePlugin.js100%100%100%100%
   getLazyHashedEtag.js100%100%100%100%
   mergeEtags.js100%100%100%100%
lib/config

@alexander-akait
alexander-akait merged commit 964bbfa into main Jul 28, 2026
63 checks passed
@alexander-akait
alexander-akait deleted the fix/cache-cleanup-unused-files branch July 28, 2026 10:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Can I purge old and outdated cache files?

2 participants