Skip to content

Commit 10cdeeb

Browse files
committed
perf(webpack-cli): hold cached argument metadata via WeakRef
The per-schema argument metadata cached for option parsing is large (~1MB for webpack, ~1.85MB including dev-server) but is only needed while setting up a command. Storing it via WeakRef lets the GC reclaim it once setup completes, which matters for long-running serve/watch sessions. A cache miss simply rebuilds it; in practice V8 keeps the target alive across the short setup window, so the dedup within a run (only one schema walk) is preserved. https://claude.ai/code/session_01PEtzv6Xqv2yXQaQsZaeoSF
1 parent 5b4e29e commit 10cdeeb

2 files changed

Lines changed: 8 additions & 5 deletions

File tree

.changeset/fast-pumas-cache.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
"webpack-cli": patch
33
---
44

5-
Cache CLI argument metadata built from the webpack/dev-server schema and apply CLI options using the cached name-keyed map directly, avoiding a redundant schema walk and the rebuild of a large options array and lookup map on every run. Default-config discovery now reads each candidate directory once instead of probing every `<name><ext>` combination with a separate `fs.access` call (up to ~100 sequential syscalls when no config file exists). Colors are also created lazily, so commands that don't need webpack (such as `version` and `info`) no longer load it. This reduces per-invocation CPU work, syscalls, and memory allocations.
5+
Cache CLI argument metadata built from the webpack/dev-server schema and apply CLI options using the cached name-keyed map directly, avoiding a redundant schema walk and the rebuild of a large options array and lookup map on every run. Default-config discovery now reads each candidate directory once instead of probing every `<name><ext>` combination with a separate `fs.access` call (up to ~100 sequential syscalls when no config file exists). Colors are also created lazily, so commands that don't need webpack (such as `version` and `info`) no longer load it. The cached argument metadata (~1MB per schema) is held via `WeakRef` so the garbage collector can reclaim it once command setup is done, which matters for long-running `serve`/`watch`. This reduces per-invocation CPU work, syscalls, and memory usage.

packages/webpack-cli/src/webpack-cli.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -923,10 +923,13 @@ class WebpackCLI {
923923

924924
// Building arguments from the webpack/dev-server schema walks a large JSON
925925
// schema and is repeated within a single run (e.g. once per command and again
926-
// in `loadConfig`). Cache the result per webpack module and schema.
926+
// in `loadConfig`). Cache the result per webpack module and schema. The values
927+
// are large (~1MB each) and only needed while setting up a command, so they are
928+
// held via `WeakRef` to let the GC reclaim them afterwards (important for
929+
// long-running `serve`/`watch`); a miss simply rebuilds them.
927930
#argumentsCache = new WeakMap<
928931
object,
929-
Map<Schema, ReturnType<(typeof webpack)["cli"]["getArguments"]>>
932+
Map<Schema, WeakRef<ReturnType<(typeof webpack)["cli"]["getArguments"]>>>
930933
>();
931934

932935
#getArguments(webpackMod: typeof webpack, schema: Schema) {
@@ -937,11 +940,11 @@ class WebpackCLI {
937940
this.#argumentsCache.set(webpackMod, perModuleCache);
938941
}
939942

940-
let args = perModuleCache.get(schema);
943+
let args = perModuleCache.get(schema)?.deref();
941944

942945
if (!args) {
943946
args = webpackMod.cli.getArguments(schema);
944-
perModuleCache.set(schema, args);
947+
perModuleCache.set(schema, new WeakRef(args));
945948
}
946949

947950
return args;

0 commit comments

Comments
 (0)