Skip to content

perf: load webpack's own modules only when a build needs them - #21652

Merged
alexander-akait merged 9 commits into
mainfrom
perf/lazy-runtime-module-loading
Aug 10, 2026
Merged

alexander-akait merged 9 commits into
mainfrom
perf/lazy-runtime-module-loading

Conversation

@alexander-akait

@alexander-akait alexander-akait commented Aug 9, 2026 •

Copy link
Copy Markdown
Member

Summary

webpack(config) loaded and compiled 580 modules before any user code ran, including runtime modules a build never emits, the error hierarchy, watchpack, es-module-lexer and the browserslist/caniuse-lite tree — most builds use none of them. Deferring those to first use cuts a react production build by -4.3% instructions and -0.56MB setup heap (580 -> 504 modules), and by -5.0% / -1.42MB when the config names its target explicitly (504 -> 483); emitted output is byte-identical across five fixtures in both modes. Two plugin-facing APIs make the deferral possible — Compilation#addLazyRuntimeModule and the NormalModuleFactory hook prepareModuleType — and four require cycles that the deferral was hiding are now broken outright, so lib/ has no static require cycle left.

What kind of change does this PR introduce?

perf — it also adds the two plugin-facing APIs named above, which is why the changeset is a minor bump.

Did you add tests for your changes?

Yes — test/lazyModule.unittest.js, test/collectCjsRequireSpecifiers.unittest.js (differential against the acorn AST over every file in lib/), test/HotModuleReplacementPlugin.unittest.js, new Compilation.unittest.js cases, and test/configCases/plugins/prepare-module-type{,-error}.

Does this PR introduce a breaking change?

No.

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

Two additions for the plugin API docs: Compilation#addLazyRuntimeModule(chunk, load, create) for runtime modules whose class should load only when emitted, and NormalModuleFactory.hooks.prepareModuleType for warming what a module type's synchronous createParser/createGenerator taps read.

Use of AI

AI (Claude) was used throughout: to survey deferral candidates, apply the mechanical conversions across ~90 files, and build the measurement harnesses. Every claim here is from a deterministic measurement I ran and checked (callgrind instruction counts, used_heap_size after forced GC, sha256 of emitted output); several AI-proposed changes were measured and rejected — notably a lib/dependencies refactor that turned out to save nothing once base classes and template registrations were counted.


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Runtime modules, parsers, generators, and build components now load only when needed, improving startup efficiency.
    • Added asynchronous preparation support for custom module types with shared work and error reporting.
    • Added HTML head-tag generation for charset, base URLs, metadata, and escaped titles.
    • Improved CommonJS dependency detection and resource-hint classification.
    • Added public APIs for deferred runtime modules and module-type preparation.
  • Bug Fixes

    • Improved reporting of deferred runtime-module and module-preparation failures.
    • Preserved compatibility across multiple webpack instances for shared hooks.

@changeset-bot

changeset-bot Bot commented Aug 9, 2026 •

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 99ca00b

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

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

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

@coderabbitai

coderabbitai Bot commented Aug 9, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key: "tools"
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 9f573c6a-e2da-4485-bb0f-f1a93ffe0eb7

📥 Commits

Reviewing files that changed from the base of the PR and between a0d7e7a and 99ca00b.

📒 Files selected for processing (1)
  • lib/html/syntax.js
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • webpack/schema-utils (auto-detected)
  • webpack/tapable (auto-detected)
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/html/syntax.js

📝 Walkthrough

Walkthrough

The pull request adds deferred loading for runtime modules, parsers, generators, warnings, errors, and selected utilities. It also adds module-type preparation hooks, shared parser registries, CommonJS scanning, HTML syntax helpers, and integration tests.

Changes

Lazy loading and runtime preparation

Layer / File(s) Summary
Lazy loading foundations and runtime lifecycle
lib/util/lazyModule.js, lib/util/preloadModuleType.js, lib/NormalModuleFactory.js, lib/Compilation.js, types.d.ts
Adds lazy module access, module-type preparation, deferred runtime-module attachment, runtime-module hashing and generation, and public API declarations.
Runtime-module integrations
lib/RuntimePlugin.js, lib/css/*, lib/asset/*, lib/esm/*, lib/prefetch/*, lib/runtime/*, lib/wasm-*/*, lib/web/*, lib/webworker/*
Runtime modules, parsers, and generators now load only when required. Module-type preparation preloads implementations before synchronous hooks use them.

Shared infrastructure and dependency updates

Layer / File(s) Summary
Shared hooks and syntax utilities
lib/hmr/*, lib/HotModuleReplacementPlugin.js, lib/container/*, lib/javascript/syntax.js, lib/prefetch/*, lib/util/globUtils.js
Adds shared HMR and Module Federation hook registries, static CommonJS require scanning, resource-hint classification, and direct plugin-hook access.
Lazy errors and platform integrations
lib/Compiler.js, lib/NormalModule.js, lib/FileSystemInfo.js, lib/node/*, lib/util/*, lib/dependencies/*, lib/url/*, lib/schemes/*, lib/sharing/*
Defers loading of warnings, errors, watchers, MIME tables, serialization components, network modules, and parser dependencies. Selected direct imports replace cycle-prone lazy accessors.

Validation

Layer / File(s) Summary
Integration and unit tests
test/lazyModule.unittest.js, test/collectCjsRequireSpecifiers.unittest.js, test/HotModuleReplacementPlugin.unittest.js, test/configCases/plugins/*, test/HtmlEntryWrapper.unittest.js
Tests lazy-loader caching, CommonJS scanning, HMR hook identity, deferred runtime-module errors and attachment, module-type preparation, and HTML entry wrapping.
Release metadata
.changeset/510-lazy-runtime-module-loading.md
Adds a minor changeset for on-demand runtime-module, parser, and generator loading.

Suggested labels: area: build-perf

🚥 Pre-merge checks | ✅ 3 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title uses valid Conventional Commit syntax and accurately describes the performance change, but the branch prefix is not provided for verification. Provide the branch name or confirm that its prefix is perf.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 8

🧹 Nitpick comments (9)
lib/HotModuleReplacementPlugin.js (1)

113-113: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Internal call now bypasses the static method.

createAcceptHandler calls the module function directly. Before, the call went through HotModuleReplacementPlugin.getParserHooks. Both resolve to the same implementation, so behavior is unchanged today.

The difference matters only if a downstream tool replaces the static property to intercept hook creation. That interception no longer reaches internal callers. If preserving that seam is not a goal, keep the direct call.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/HotModuleReplacementPlugin.js` at line 113, The internal call in
createAcceptHandler should preserve the
HotModuleReplacementPlugin.getParserHooks override seam by routing hook creation
through the static method rather than invoking the module-level function
directly; update only this call and keep the existing behavior otherwise
unchanged.
lib/FileSystemInfo.js (1)

2249-2264: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

The added set is now redundant.

collectCjsRequireSpecifiers returns a Set, so each specifier already appears once. The added set at Line 2248 and the added.has(...) check at Line 2254 can be removed. This is a small cleanup only.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/FileSystemInfo.js` around lines 2249 - 2264, Remove the redundant added
set and its added.has(dependency) guard from the loop over
collectCjsRequireSpecifiers in the CJS dependency handling flow; retain the
existing node: and builtinModules filtering and dependency push behavior.
lib/hmr/parserHooks.js (1)

9-9: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Validation style differs from createHooksRegistry.

lib/util/createHooksRegistry.js was changed in this same PR to replace instanceof with a constructor-name check, so a compilation from another webpack copy passes. This module keeps instanceof JavascriptParser, so a parser from another webpack copy is rejected.

The behavior matches what HotModuleReplacementPlugin did before, so this is not a regression. Consider aligning the two checks if cross-copy support is intended for parsers as well. The eager require of JavascriptParser exists only to support this check; a name check would also remove that import.

Also applies to: 33-37

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/hmr/parserHooks.js` at line 9, Align the parser validation in the
relevant hook registration logic with createHooksRegistry by replacing the
instanceof JavascriptParser check with the established constructor-name check.
Remove the now-unused eager JavascriptParser require while preserving rejection
of non-parser values and acceptance of parsers from other webpack copies.
test/collectCjsRequireSpecifiers.unittest.js (2)

92-96: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Two case names describe behavior the assertions do not check.

The case at Line 92 is named "template specifier is static", and the case at Line 94 is named "template specifier with substitution". In both, require(\./a`)produces an empty set from the Acorn reference, because the argument is aTemplateLiteraland not aLiteral`. The scanner also produces an empty set. The test therefore asserts that neither collects a template specifier, which is the opposite of "is static".

Rename to state the checked behavior, for example "template specifier is not collected".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/collectCjsRequireSpecifiers.unittest.js` around lines 92 - 96, Rename
the two test cases in the collectCjsRequireSpecifiers suite so their names
accurately state that template-literal require specifiers are not collected,
including both the static template and substituted template cases. Leave the
test inputs and assertions unchanged.

125-125: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Replace the file-count floor with a looser value.

toBeGreaterThan(400) couples the test to the current size of lib/. The guard exists to catch a broken directory walk, and a much lower floor serves that purpose without needing an update whenever the tree shrinks.

♻️ Proposed change
-		expect(files.length).toBeGreaterThan(400);
+		expect(files.length).toBeGreaterThan(100);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/collectCjsRequireSpecifiers.unittest.js` at line 125, Lower the
file-count floor in the test assertion using toBeGreaterThan so it still detects
a broken lib directory walk without coupling the test to the current file count;
leave the surrounding collection behavior unchanged.
test/HotModuleReplacementPlugin.unittest.js (1)

6-17: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add an assertion that pins the delegation to the shared module.

This PR moves hook storage into lib/hmr/parserHooks.js. The tests confirm the static method still works, but nothing confirms both entry points share one WeakMap. If a future change gives HotModuleReplacementPlugin its own registry again, these tests still pass while plugins that call the module directly get different hooks.

💚 Proposed additional assertion
 	it("attaches the hooks once per parser", () => {
 		const parser = new JavascriptParser();
 		const hooks = HotModuleReplacementPlugin.getParserHooks(parser);
 
 		expect(typeof hooks.hotAcceptCallback.tap).toBe("function");
 		expect(typeof hooks.hotAcceptWithoutCallback.tap).toBe("function");
 		expect(HotModuleReplacementPlugin.getParserHooks(parser)).toBe(hooks);
+		expect(require("../lib/hmr/parserHooks")(parser)).toBe(hooks);
 		expect(
 			HotModuleReplacementPlugin.getParserHooks(new JavascriptParser())
 		).not.toBe(hooks);
 	});

As per coding guidelines: "Cover every changed line and branch with tests".

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/HotModuleReplacementPlugin.unittest.js` around lines 6 - 17, Extend the
“attaches the hooks once per parser” test to import or reference the shared
parser-hooks module and assert that
HotModuleReplacementPlugin.getParserHooks(parser) returns the same hooks as the
module’s direct entry point for that parser, confirming both APIs use the same
WeakMap-backed registry.

Source: Coding guidelines

lib/node/nodeConsole.js (1)

9-10: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Keep the CLI dependency lazy on the custom-console path.

NodeEnvironmentPlugin can use infrastructureLogging.console without calling nodeConsole. The top-level require("../cli") still loads the CLI module when nodeConsole.js is loaded. This removes the previous lazy boundary on a supported path.

Keep the require inside the factory unless the eager load is intentional and measured for this performance PR.

Suggested fix
-const Cli = require("../cli");
+const memoize = require("../util/memoize");
+const getCli = memoize(() => require("../cli"));
...
-	const c = Cli.createColors({ useColor: Boolean(colors) });
+	const c = getCli().createColors({ useColor: Boolean(colors) });

Also applies to: 60-60

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/node/nodeConsole.js` around lines 9 - 10, Keep the CLI dependency lazy by
removing the top-level require of “../cli” and loading it inside the nodeConsole
factory only when the CLI-backed console path is used. Preserve the existing
custom-console behavior and avoid changing the unrelated truncateArgs import.
lib/Compilation.js (1)

4418-4423: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Drain the queue until it is empty.

addRuntimeModule calls the runtimeModule hook. A tap on that hook can call addLazyRuntimeModule again, which refills _pendingRuntimeModules after this method cleared it. Those entries are never attached, and the runtime module is dropped without an error.

Repeat the load-and-attach pass while the queue is non-empty, or throw when the queue is refilled after the pass.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/Compilation.js` around lines 4418 - 4423, Update the pending
runtime-module processing around addRuntimeModule so it drains
_pendingRuntimeModules completely: after each load-and-attach pass, detect
entries added by the runtimeModule hook and repeat processing until the queue is
empty, or explicitly throw if refilling is unsupported. Ensure every module
queued through addLazyRuntimeModule is attached before invoking callback.
test/lazyModule.unittest.js (1)

6-17: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test concurrent lazy-module access.

Lines 13-15 await the first load before the second call. This does not verify that concurrent get() calls share one in-flight load. Call get() twice before awaiting either result. Assert one loader call and identical resolved values.

As per coding guidelines, test/**/*.{js,json} requires coverage of every changed line and branch.

Proposed test update
-		const first = await get();
+		const firstPromise = get();
+		const secondPromise = get();
+		const first = await firstPromise;
 		expect(first).toEqual({ answer: 42 });
-		expect(await get()).toBe(first);
+		expect(await secondPromise).toBe(first);
 		expect(calls).toBe(1);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/lazyModule.unittest.js` around lines 6 - 17, Update the lazy-module test
around lazyModule and get() to start two get() calls before awaiting either
result, then await both and assert the loader runs once and both results are the
same resolved module object. Preserve the initial zero-call assertion and
existing module-value verification while covering concurrent in-flight access.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.changeset/510-lazy-runtime-module-loading.md:
- Around line 5-6: Rewrite the changeset description as one concise imperative
sentence of no more than 80 characters, ending with a period, while preserving
the core lazy runtime module loading change.

In `@lib/Compilation.js`:
- Around line 4414-4425: Update _attachPendingRuntimeModules so errors thrown by
create(loaded[i]) or addRuntimeModule during the fulfillment handler are routed
to callback, by attaching the error handler to the promise chain after the
attach loop rather than only passing it to the initial then call.
- Around line 6067-6069: Restore this.chunkGraph to its original value
immediately after processRuntimeRequirements returns and before calling
_attachPendingRuntimeModules. Keep the deferred callback responsible only for
handling the error and invoking the existing continuation, since the attach
logic uses its captured graph and does not require this.chunkGraph to remain
swapped.

In `@lib/html/HtmlModulesPlugin.js`:
- Line 439: Update the head-tag construction in HtmlModulesPlugin to use the
eagerly loaded HtmlParser module reference when calling buildHeadTags, rather
than invoking getHtmlParser.loaded() synchronously. Preserve the existing
htmlObj argument and ensure configurations with output.html and JavaScript
entries can build head tags before compilation.

In `@lib/javascript/syntax.js`:
- Around line 7174-7189: Update lib/javascript/syntax.js lines 7174-7189 in
startsRegExp by adding "await" to KEYWORDS_BEFORE_REGEXP, and document the
existing ) and ] limitation in its JSDoc without adding paren-context tracking.
Update test/collectCjsRequireSpecifiers.unittest.js lines 80-86 with an async
await-before-regexp case containing require("./nope") plus the existing trailing
require assertion; do not add a control-flow-`)` regexp case unless that
position is implemented.

In `@lib/NormalModuleFactory.js`:
- Around line 1536-1542: In the hook.callAsync completion handler, notify all
callbacks in the waiting loop before invoking the primary callback, so a
synchronous throw from callback cannot prevent queued factorize flows from
completing. Preserve the existing error normalization and module-type
preparation bookkeeping, and ensure every waiting callback is invoked once.

In `@lib/schemes/HttpUriPlugin.js`:
- Line 528: Update the validation diagnostic name in HttpUriPlugin to use "Http
Uri Plugin" instead of "getHttp() Uri Plugin", preserving the correct component
label and avoiding exposure of the internal loader name.

In `@lib/webpack.js`:
- Around line 14-15: Remove the eager top-level requires for MultiCompiler and
ProgressPlugin in lib/webpack.js, and restore memoized lazy getters for each
module or constructor. Resolve MultiCompiler only in the multi-compiler
conditional path and ProgressPlugin only when progress is enabled, preserving
cached reuse after the first lookup.

---

Nitpick comments:
In `@lib/Compilation.js`:
- Around line 4418-4423: Update the pending runtime-module processing around
addRuntimeModule so it drains _pendingRuntimeModules completely: after each
load-and-attach pass, detect entries added by the runtimeModule hook and repeat
processing until the queue is empty, or explicitly throw if refilling is
unsupported. Ensure every module queued through addLazyRuntimeModule is attached
before invoking callback.

In `@lib/FileSystemInfo.js`:
- Around line 2249-2264: Remove the redundant added set and its
added.has(dependency) guard from the loop over collectCjsRequireSpecifiers in
the CJS dependency handling flow; retain the existing node: and builtinModules
filtering and dependency push behavior.

In `@lib/hmr/parserHooks.js`:
- Line 9: Align the parser validation in the relevant hook registration logic
with createHooksRegistry by replacing the instanceof JavascriptParser check with
the established constructor-name check. Remove the now-unused eager
JavascriptParser require while preserving rejection of non-parser values and
acceptance of parsers from other webpack copies.

In `@lib/HotModuleReplacementPlugin.js`:
- Line 113: The internal call in createAcceptHandler should preserve the
HotModuleReplacementPlugin.getParserHooks override seam by routing hook creation
through the static method rather than invoking the module-level function
directly; update only this call and keep the existing behavior otherwise
unchanged.

In `@lib/node/nodeConsole.js`:
- Around line 9-10: Keep the CLI dependency lazy by removing the top-level
require of “../cli” and loading it inside the nodeConsole factory only when the
CLI-backed console path is used. Preserve the existing custom-console behavior
and avoid changing the unrelated truncateArgs import.

In `@test/collectCjsRequireSpecifiers.unittest.js`:
- Around line 92-96: Rename the two test cases in the
collectCjsRequireSpecifiers suite so their names accurately state that
template-literal require specifiers are not collected, including both the static
template and substituted template cases. Leave the test inputs and assertions
unchanged.
- Line 125: Lower the file-count floor in the test assertion using
toBeGreaterThan so it still detects a broken lib directory walk without coupling
the test to the current file count; leave the surrounding collection behavior
unchanged.

In `@test/HotModuleReplacementPlugin.unittest.js`:
- Around line 6-17: Extend the “attaches the hooks once per parser” test to
import or reference the shared parser-hooks module and assert that
HotModuleReplacementPlugin.getParserHooks(parser) returns the same hooks as the
module’s direct entry point for that parser, confirming both APIs use the same
WeakMap-backed registry.

In `@test/lazyModule.unittest.js`:
- Around line 6-17: Update the lazy-module test around lazyModule and get() to
start two get() calls before awaiting either result, then await both and assert
the loader runs once and both results are the same resolved module object.
Preserve the initial zero-call assertion and existing module-value verification
while covering concurrent in-flight access.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 603a0549-c0d5-476c-8d8d-fce45f284a60

📥 Commits

Reviewing files that changed from the base of the PR and between c63ac95 and c979501.

📒 Files selected for processing (92)
  • .changeset/510-lazy-runtime-module-loading.md
  • lib/ChunkTemplate.js
  • lib/Compilation.js
  • lib/Compiler.js
  • lib/ExternalModule.js
  • lib/FileSystemInfo.js
  • lib/HotModuleReplacementPlugin.js
  • lib/MainTemplate.js
  • lib/ModuleTemplate.js
  • lib/MultiCompiler.js
  • lib/NodeStuffPlugin.js
  • lib/NormalModule.js
  • lib/NormalModuleFactory.js
  • lib/ProgressPlugin.js
  • lib/RuntimePlugin.js
  • lib/RuntimeTemplate.js
  • lib/asset/AssetModulesPlugin.js
  • lib/buildChunkGraph.js
  • lib/config/target.js
  • lib/container/ContainerPlugin.js
  • lib/container/HoistContainerReferencesPlugin.js
  • lib/container/ModuleFederationPlugin.js
  • lib/container/moduleFederationHooks.js
  • lib/css/CssGenerator.js
  • lib/css/CssModulesPlugin.js
  • lib/css/CssParser.js
  • lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js
  • lib/dependencies/CommonJsFullRequireDependency.js
  • lib/dependencies/CommonJsImportsParserPlugin.js
  • lib/dependencies/CommonJsRequireDependency.js
  • lib/dependencies/ContextDependency.js
  • lib/dependencies/HarmonyDetectionParserPlugin.js
  • lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js
  • lib/dependencies/HarmonyImportDependencyParserPlugin.js
  • lib/dependencies/HarmonyImportGuard.js
  • lib/dependencies/HarmonyImportSpecifierDependency.js
  • lib/dependencies/ImportDependency.js
  • lib/dependencies/ImportMetaGlobHelpers.js
  • lib/dependencies/ImportParserPlugin.js
  • lib/dependencies/RequireHeaderDependency.js
  • lib/dependencies/WorkerAndWorkletPlugin.js
  • lib/esm/ModuleChunkLoadingPlugin.js
  • lib/hmr/parserHooks.js
  • lib/html/HtmlGenerator.js
  • lib/html/HtmlModulesPlugin.js
  • lib/html/HtmlParser.js
  • lib/javascript/JavascriptParserHelpers.js
  • lib/javascript/syntax.js
  • lib/loaders/loadLoader.js
  • lib/node/NodeEnvironmentPlugin.js
  • lib/node/NodeWatchFileSystem.js
  • lib/node/nodeConsole.js
  • lib/optimize/ConcatenatedModule.js
  • lib/optimize/SideEffectsFlagPlugin.js
  • lib/prefetch/ChunkPrefetchPreloadPlugin.js
  • lib/prefetch/ResourceHintPlugin.js
  • lib/prefetch/ResourceHintRuntimeModule.js
  • lib/prefetch/parseResourceHintOptions.js
  • lib/runtime/StartupChunkDependenciesPlugin.js
  • lib/schemes/HttpUriPlugin.js
  • lib/schemes/VirtualUrlPlugin.js
  • lib/sharing/ConsumeSharedPlugin.js
  • lib/sharing/resolveMatchedConfigs.js
  • lib/typescript/TypeScriptPlugin.js
  • lib/url/URLParserPlugin.js
  • lib/util/createHooksRegistry.js
  • lib/util/globUtils.js
  • lib/util/lazyModule.js
  • lib/util/mimeTypes.js
  • lib/util/parseJson.js
  • lib/util/preloadModuleType.js
  • lib/util/serialization.js
  • lib/wasm-async/AsyncWebAssemblyModulesPlugin.js
  • lib/wasm-async/AsyncWebAssemblyParser.js
  • lib/wasm-sync/WebAssemblyModulesPlugin.js
  • lib/web/JsonpChunkLoadingPlugin.js
  • lib/webpack.js
  • lib/webworker/ImportScriptsChunkLoadingPlugin.js
  • test/Compilation.unittest.js
  • test/HotModuleReplacementPlugin.unittest.js
  • test/collectCjsRequireSpecifiers.unittest.js
  • test/configCases/plugins/prepare-module-type-error/errors.js
  • test/configCases/plugins/prepare-module-type-error/file.custom
  • test/configCases/plugins/prepare-module-type-error/index.js
  • test/configCases/plugins/prepare-module-type-error/webpack.config.js
  • test/configCases/plugins/prepare-module-type/first.custom
  • test/configCases/plugins/prepare-module-type/index.js
  • test/configCases/plugins/prepare-module-type/second.custom
  • test/configCases/plugins/prepare-module-type/warnings.js
  • test/configCases/plugins/prepare-module-type/webpack.config.js
  • test/lazyModule.unittest.js
  • types.d.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • webpack/schema-utils (auto-detected)
  • webpack/tapable (auto-detected)

Comment thread lib/Compilation.js Resolved
Comment thread lib/Compilation.js Resolved
Comment thread lib/html/HtmlModulesPlugin.js Resolved
Comment thread lib/javascript/syntax.js Resolved
Comment thread lib/NormalModuleFactory.js Resolved
Comment thread lib/schemes/HttpUriPlugin.js Outdated
this.options,
{
name: "Http Uri Plugin",
name: "getHttp() Uri Plugin",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Restore the HttpUriPlugin name in the validation diagnostic.

The new "getHttp() Uri Plugin" label exposes an internal loader name and identifies the wrong component. Restore "Http Uri Plugin".

Proposed fix
-					name: "getHttp() Uri Plugin",
+					name: "Http Uri Plugin",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
name: "getHttp() Uri Plugin",
name: "Http Uri Plugin",
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/schemes/HttpUriPlugin.js` at line 528, Update the validation diagnostic
name in HttpUriPlugin to use "Http Uri Plugin" instead of "getHttp() Uri
Plugin", preserving the correct component label and avoiding exposure of the
internal loader name.

Comment thread lib/webpack.js Resolved
@github-actions github-actions Bot added area: wasm WebAssembly modules (lib/wasm-*) area: module-federation Module Federation (lib/container, lib/sharing) area: parser JavaScript parsing and dependency analysis (lib/javascript, lib/dependencies) area: config Options, defaults, validation (lib/config, schemas/) area: css CSS support (lib/css) area: html Experimental HTML support (lib/html) area: loaders Loader execution and loader API (lib/loaders) area: optimization Tree-shaking, splitChunks, concatenation, ids (lib/optimize, lib/ids) area: runtime Emitted runtime and chunk loading across targets (lib/runtime, lib/web, lib/node, lib/esm) area: types types.d.ts, JSDoc annotations, hand-maintained declarations area: watch Watching, HMR, lazy compilation (lib/hmr, hot/) labels Aug 9, 2026
@alexander-akait
alexander-akait force-pushed the perf/lazy-runtime-module-loading branch from 1b08795 to ac6c912 Compare August 9, 2026 19:20
@github-actions

github-actions Bot commented Aug 9, 2026 •

Copy link
Copy Markdown
Contributor

This PR is packaged and the instant preview is available (8e28763).

Install it locally:

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

@codecov

codecov Bot commented Aug 9, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.62955% with 42 lines in your changes missing coverage. Please review.
✅ Project coverage is 94.46%. Comparing base (5c5d009) to head (99ca00b).

Files with missing lines Patch % Lines
lib/Compilation.js 86.20% 24 Missing ⚠️
lib/prefetch/parseResourceHintOptions.js 62.50% 6 Missing ⚠️
lib/typescript/TypeScriptPlugin.js 33.33% 4 Missing ⚠️
lib/NormalModuleFactory.js 94.87% 2 Missing ⚠️
lib/dependencies/WorkerAndWorkletPlugin.js 60.00% 2 Missing ⚠️
lib/schemes/VirtualUrlPlugin.js 50.00% 2 Missing ⚠️
lib/sharing/resolveMatchedConfigs.js 66.66% 1 Missing ⚠️
lib/url/URLParserPlugin.js 80.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main   #21652      +/-   ##
==========================================
+ Coverage   94.40%   94.46%   +0.06%     
==========================================
  Files         628      629       +1     
  Lines       80618    80967     +349     
  Branches    23812    23889      +77     
==========================================
+ Hits        76108    76487     +379     
+ Misses       4510     4480      -30     
Flag Coverage Δ
css-parsing 26.28% <36.10%> (+0.41%) ⬆️
html5lib 30.80% <34.08%> (+0.54%) ⬆️
integration 88.50% <77.93%> (-0.13%) ⬇️
test262 50.55% <42.77%> (+1.46%) ⬆️
unit 53.81% <56.76%> (+2.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.

@github-actions

github-actions Bot commented Aug 9, 2026 •

Copy link
Copy Markdown
Contributor

Generated code size

Comparing 99ca00b against 5c5d009. Merging this PR will change the code webpack generates.

Changed New Deleted Unchanged Raw change
Cases 6 4 0 1518 🔴 ↑ +507 B
Assets 7 2 0 5933 🔴 ↑ +507 B
Runtimes 0 1 0 1863 —
9 asset(s) changed size
Asset Before After Change Gzip (9) Brotli (11) Zstd (19)
➕ plugins/add-lazy-runtime-module bundle0.js — 352 B +352 B (new) new new new
➕ plugins/prepare-module-type bundle0.js — 155 B +155 B (new) new new new
🔴 ↑ asset-modules/data-url-broken bundle0.js 5.02 KiB 5.02 KiB 0 B (—) +0.06% — —
🔴 ↑ asset-modules/data-url-broken [hash] 1.11 KiB 1.11 KiB 0 B (—) — +0.27% —
🟢 ↓ container/container-reference bundle0.js 2.71 KiB 2.71 KiB 0 B (—) -0.14% -0.24% —
🔴 ↑ container/container-reference-override bundle0.js 2.75 KiB 2.75 KiB 0 B (—) +0.21% +0.39% +0.07%
🔴 ↑ container/module-federation bundle0.js 4.43 KiB 4.43 KiB 0 B (—) — +0.42% -0.06%
🟢 ↓ html/template-non-string bundle0.js 1.04 KiB 1.04 KiB 0 B (—) -0.24% -0.29% —
🔴 ↑ loaders/options bundle0.js 4.46 KiB 4.46 KiB 0 B (—) +0.08% — —
1 runtime(s) changed which runtime modules they carry
Runtime Modules Added Removed
➕ plugins/add-lazy-runtime-module main 0 → 2 global, lazy marker —

Built test/configCases with the defaults a user gets: 1528 case(s), 5942 asset(s), 40 emitted nothing.

@codspeed

codspeed Bot commented Aug 9, 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

⚡ 6 improved benchmarks
❌ 2 regressed benchmarks
✅ 212 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
❌ Memory benchmark "json-modules", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 410.7 KB 681.2 KB -39.7%
❌ Memory benchmark "three-long", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 721.9 KB 1,064 KB -32.15%
⚡ Memory benchmark "asset-modules-source", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 940.8 KB 649.6 KB +44.84%
⚡ Memory benchmark "asset-modules-resource", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 964.5 KB 669.8 KB +44%
⚡ Memory benchmark "cache-filesystem", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 1,162.8 KB 862.9 KB +34.76%
⚡ Memory benchmark "future-defaults", scenario '{"name":"mode-production","mode":"production"}' 10.2 MB 8.4 MB +22.11%
⚡ Memory benchmark "many-modules-commonjs", scenario '{"name":"mode-production","mode":"production"}' 10.7 MB 8.8 MB +21.54%
⚡ Memory benchmark "many-modules-interop-runtime", scenario '{"name":"mode-production","mode":"production"}', measure 'exec' 23 KB 19 KB +21.23%

Tip

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


Comparing perf/lazy-runtime-module-loading (99ca00b) with main (5c5d009)

Open in CodSpeed

Defer parsers, generators, runtime modules and error classes behind
`lazyModule`/`memoize` so a build only loads what it reaches. Adds
`Compilation#addLazyRuntimeModule` and the `NormalModuleFactory` hook
`prepareModuleType`, which awaits a type's loads at the factory's async
boundary because `createParser`/`createGenerator` are synchronous.
Replaces the acorn walk in `FileSystemInfo` with a CommonJS specifier
scanner.
The runtime module read the chunk's modules through an unordered cache,
so the emitted order was whichever comparator happened to sort them last.
Deferring runtime module attachment changes that, flipping the mapping.
The scanner reads whatever is on disk, so it must terminate on input the
acorn reference cannot parse — those branches need direct assertions
rather than the differential comparison.
Main removed test/Compilation.unittest.js while converting unit tests to
config cases; these drive the same two paths through a real build.
@alexander-akait
alexander-akait force-pushed the perf/lazy-runtime-module-loading branch from d53906c to 96eff54 Compare August 9, 2026 22:44
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot added the area: build-perf Build time and memory of webpack itself label Aug 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/FileSystemInfo.js`:
- Around line 2247-2249: Update the dependency collection around
collectCjsRequireSpecifiers so escaped static CommonJS string literals, such as
require("./a\\tb"), are retained and decoded correctly. Prefer fixing the shared
scanner used by collectCjsRequireSpecifiers; otherwise preserve the Acorn
fallback for this path, while keeping non-static or invalid specifiers excluded.

In `@lib/html/headTags.js`:
- Around line 42-47: Shorten the comment above the head-tag serialization logic
to no more than two brief lines, retaining only the non-obvious spec ordering
and the distinction between synthetic entries and authored pages.

In `@test/HtmlEntryWrapper.unittest.js`:
- Around line 9-12: Shorten the comment above the synthetic page setup to two
short lines, retaining only the non-obvious requirement that this is the first
build and no lazy loads have been warmed.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 50438b88-caf8-4292-8160-20ccb7327a92

📥 Commits

Reviewing files that changed from the base of the PR and between 5c5d009 and 96eff54.

⛔ Files ignored due to path filters (1)
  • types.d.ts is excluded by !types.d.ts
📒 Files selected for processing (97)
  • .changeset/510-lazy-runtime-module-loading.md
  • lib/ChunkTemplate.js
  • lib/Compilation.js
  • lib/Compiler.js
  • lib/ExternalModule.js
  • lib/FileSystemInfo.js
  • lib/HotModuleReplacementPlugin.js
  • lib/MainTemplate.js
  • lib/ModuleTemplate.js
  • lib/MultiCompiler.js
  • lib/NodeStuffPlugin.js
  • lib/NormalModule.js
  • lib/NormalModuleFactory.js
  • lib/ProgressPlugin.js
  • lib/RuntimePlugin.js
  • lib/RuntimeTemplate.js
  • lib/asset/AssetModulesPlugin.js
  • lib/buildChunkGraph.js
  • lib/config/target.js
  • lib/container/ContainerPlugin.js
  • lib/container/HoistContainerReferencesPlugin.js
  • lib/container/ModuleFederationPlugin.js
  • lib/container/RemoteRuntimeModule.js
  • lib/container/moduleFederationHooks.js
  • lib/css/CssGenerator.js
  • lib/css/CssModulesPlugin.js
  • lib/css/CssParser.js
  • lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js
  • lib/dependencies/CommonJsFullRequireDependency.js
  • lib/dependencies/CommonJsImportsParserPlugin.js
  • lib/dependencies/CommonJsRequireDependency.js
  • lib/dependencies/ContextDependency.js
  • lib/dependencies/HarmonyDetectionParserPlugin.js
  • lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js
  • lib/dependencies/HarmonyImportDependencyParserPlugin.js
  • lib/dependencies/HarmonyImportGuard.js
  • lib/dependencies/HarmonyImportSpecifierDependency.js
  • lib/dependencies/ImportDependency.js
  • lib/dependencies/ImportMetaGlobHelpers.js
  • lib/dependencies/ImportParserPlugin.js
  • lib/dependencies/RequireHeaderDependency.js
  • lib/dependencies/WorkerAndWorkletPlugin.js
  • lib/esm/ModuleChunkLoadingPlugin.js
  • lib/hmr/parserHooks.js
  • lib/html/HtmlGenerator.js
  • lib/html/HtmlModulesPlugin.js
  • lib/html/HtmlParser.js
  • lib/html/headTags.js
  • lib/javascript/JavascriptParserHelpers.js
  • lib/javascript/syntax.js
  • lib/loaders/loadLoader.js
  • lib/node/NodeWatchFileSystem.js
  • lib/optimize/ConcatenatedModule.js
  • lib/optimize/SideEffectsFlagPlugin.js
  • lib/prefetch/ChunkPrefetchPreloadPlugin.js
  • lib/prefetch/ResourceHintPlugin.js
  • lib/prefetch/ResourceHintRuntimeModule.js
  • lib/prefetch/parseResourceHintOptions.js
  • lib/runtime/StartupChunkDependenciesPlugin.js
  • lib/schemes/HttpUriPlugin.js
  • lib/schemes/VirtualUrlPlugin.js
  • lib/sharing/ConsumeSharedPlugin.js
  • lib/sharing/resolveMatchedConfigs.js
  • lib/typescript/TypeScriptPlugin.js
  • lib/url/URLParserPlugin.js
  • lib/util/createHooksRegistry.js
  • lib/util/globUtils.js
  • lib/util/lazyModule.js
  • lib/util/mimeTypes.js
  • lib/util/parseJson.js
  • lib/util/preloadModuleType.js
  • lib/util/serialization.js
  • lib/wasm-async/AsyncWebAssemblyModulesPlugin.js
  • lib/wasm-async/AsyncWebAssemblyParser.js
  • lib/wasm-sync/WebAssemblyModulesPlugin.js
  • lib/web/JsonpChunkLoadingPlugin.js
  • lib/webpack.js
  • lib/webworker/ImportScriptsChunkLoadingPlugin.js
  • test/HotModuleReplacementPlugin.unittest.js
  • test/HtmlEntryWrapper.unittest.js
  • test/collectCjsRequireSpecifiers.unittest.js
  • test/configCases/plugins/add-lazy-runtime-module-error/errors.js
  • test/configCases/plugins/add-lazy-runtime-module-error/index.js
  • test/configCases/plugins/add-lazy-runtime-module-error/webpack.config.js
  • test/configCases/plugins/add-lazy-runtime-module/MarkerRuntimeModule.js
  • test/configCases/plugins/add-lazy-runtime-module/index.js
  • test/configCases/plugins/add-lazy-runtime-module/webpack.config.js
  • test/configCases/plugins/prepare-module-type-error/errors.js
  • test/configCases/plugins/prepare-module-type-error/file.custom
  • test/configCases/plugins/prepare-module-type-error/index.js
  • test/configCases/plugins/prepare-module-type-error/webpack.config.js
  • test/configCases/plugins/prepare-module-type/first.custom
  • test/configCases/plugins/prepare-module-type/index.js
  • test/configCases/plugins/prepare-module-type/second.custom
  • test/configCases/plugins/prepare-module-type/warnings.js
  • test/configCases/plugins/prepare-module-type/webpack.config.js
  • test/lazyModule.unittest.js
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • webpack/schema-utils (auto-detected)
  • webpack/tapable (auto-detected)
🚧 Files skipped from review as they are similar to previous changes (80)
  • test/configCases/plugins/prepare-module-type/first.custom
  • lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js
  • lib/dependencies/HarmonyImportGuard.js
  • test/configCases/plugins/prepare-module-type-error/errors.js
  • test/configCases/plugins/prepare-module-type/warnings.js
  • test/configCases/plugins/prepare-module-type-error/file.custom
  • test/configCases/plugins/prepare-module-type/index.js
  • lib/util/preloadModuleType.js
  • lib/config/target.js
  • test/lazyModule.unittest.js
  • lib/html/HtmlModulesPlugin.js
  • test/configCases/plugins/prepare-module-type/second.custom
  • lib/javascript/JavascriptParserHelpers.js
  • lib/sharing/resolveMatchedConfigs.js
  • lib/util/parseJson.js
  • lib/dependencies/ImportDependency.js
  • lib/sharing/ConsumeSharedPlugin.js
  • lib/wasm-async/AsyncWebAssemblyParser.js
  • lib/web/JsonpChunkLoadingPlugin.js
  • lib/dependencies/RequireHeaderDependency.js
  • lib/util/globUtils.js
  • lib/schemes/VirtualUrlPlugin.js
  • lib/util/lazyModule.js
  • lib/MainTemplate.js
  • lib/dependencies/HarmonyDetectionParserPlugin.js
  • lib/css/CssGenerator.js
  • lib/webworker/ImportScriptsChunkLoadingPlugin.js
  • lib/prefetch/ResourceHintPlugin.js
  • lib/HotModuleReplacementPlugin.js
  • lib/dependencies/ImportMetaGlobHelpers.js
  • lib/dependencies/CommonJsRequireDependency.js
  • lib/NodeStuffPlugin.js
  • test/configCases/plugins/prepare-module-type-error/webpack.config.js
  • lib/container/HoistContainerReferencesPlugin.js
  • lib/buildChunkGraph.js
  • lib/ModuleTemplate.js
  • lib/dependencies/CommonJsFullRequireDependency.js
  • lib/util/createHooksRegistry.js
  • lib/prefetch/ResourceHintRuntimeModule.js
  • lib/url/URLParserPlugin.js
  • lib/hmr/parserHooks.js
  • lib/Compiler.js
  • lib/ProgressPlugin.js
  • lib/dependencies/ContextDependency.js
  • lib/container/ModuleFederationPlugin.js
  • lib/container/ContainerPlugin.js
  • lib/RuntimeTemplate.js
  • lib/html/HtmlGenerator.js
  • lib/prefetch/parseResourceHintOptions.js
  • lib/dependencies/WorkerAndWorkletPlugin.js
  • lib/runtime/StartupChunkDependenciesPlugin.js
  • lib/prefetch/ChunkPrefetchPreloadPlugin.js
  • lib/css/CssParser.js
  • lib/optimize/ConcatenatedModule.js
  • lib/javascript/syntax.js
  • lib/wasm-sync/WebAssemblyModulesPlugin.js
  • lib/NormalModuleFactory.js
  • lib/ChunkTemplate.js
  • lib/MultiCompiler.js
  • lib/esm/ModuleChunkLoadingPlugin.js
  • lib/dependencies/CommonJsImportsParserPlugin.js
  • lib/css/CssModulesPlugin.js
  • lib/dependencies/HarmonyImportSpecifierDependency.js
  • lib/typescript/TypeScriptPlugin.js
  • lib/NormalModule.js
  • lib/asset/AssetModulesPlugin.js
  • lib/schemes/HttpUriPlugin.js
  • lib/wasm-async/AsyncWebAssemblyModulesPlugin.js
  • lib/util/serialization.js
  • lib/ExternalModule.js
  • lib/html/HtmlParser.js
  • lib/dependencies/HarmonyImportDependencyParserPlugin.js
  • test/configCases/plugins/prepare-module-type/webpack.config.js
  • lib/loaders/loadLoader.js
  • lib/util/mimeTypes.js
  • lib/Compilation.js
  • lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js
  • lib/dependencies/ImportParserPlugin.js
  • lib/RuntimePlugin.js
  • test/configCases/plugins/prepare-module-type-error/index.js

Comment thread lib/FileSystemInfo.js
Comment on lines +2247 to +2249
for (const dependency of collectCjsRequireSpecifiers(
source
)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Keep escaped static CommonJS specifiers.

collectCjsRequireSpecifiers omits valid string literals with escapes. test/collectCjsRequireSpecifiers.unittest.js Lines 139-149 documents this behavior. On Bun, require("./a\\tb") is then absent from build dependencies, so changes to that module can miss cache invalidation.

Decode valid string escapes in the shared scanner, or retain the Acorn fallback for this path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/FileSystemInfo.js` around lines 2247 - 2249, Update the dependency
collection around collectCjsRequireSpecifiers so escaped static CommonJS string
literals, such as require("./a\\tb"), are retained and decoded correctly. Prefer
fixing the shared scanner used by collectCjsRequireSpecifiers; otherwise
preserve the Acorn fallback for this path, while keeping non-static or invalid
specifiers excluded.

Comment thread lib/html/headTags.js Outdated
Comment on lines +42 to +47
/**
* Serializes every head tag an `output.html` options object asks for, in
* spec order: charset, base, meta tags, title. Used where a page is created
* from scratch (HtmlModulesPlugin's synthetic entry wrapper); authored pages
* instead merge the options against their existing tags during `parse` —
* existing tags win.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Shorten this comment.

Keep the non-obvious behavior in at most two short lines.

As per coding guidelines, “Keep comments as short as possible, generally one line and no more than two short lines.” As per path instructions, “Comments must be at most two short lines and add non-obvious information.”

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/html/headTags.js` around lines 42 - 47, Shorten the comment above the
head-tag serialization logic to no more than two brief lines, retaining only the
non-obvious spec ordering and the distinction between synthetic entries and
authored pages.

Sources: Coding guidelines, Path instructions

Comment thread test/HtmlEntryWrapper.unittest.js Resolved
The scanner rejected any literal holding a backslash, so a specifier
written "..\\lib\\a" or hex-escaped by a minifier was dropped from Bun's
build dependencies. Cook escapes the way the ast it replaces did.
…require

Internal callers go back through HotModuleReplacementPlugin.getParserHooks,
so replacing it still intercepts. The parser is matched by class name like
createHooksRegistry does, which also stops parserHooks from loading
JavascriptParser eagerly on every ESM build.
They only build strings out of escapeAttribute/escapeText, so they belong
next to those rather than in a file of their own. Both callers already
reach the syntax module, so this drops a require instead of adding one.
The marker wrote through `globalThis`, which Node 10 does not have, so the
executed bundle threw there. Emit through RuntimeGlobals.global instead.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/html/syntax.js`:
- Around line 4645-4647: Reduce the block comment above the head-tag
serialization logic to exactly two short prose lines, preserving the spec order
and the distinction that authored pages merge options during parse with their
own tags taking precedence.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 16757ea7-f930-44c0-b5a5-a7ec9b0f568f

📥 Commits

Reviewing files that changed from the base of the PR and between 96eff54 and a0d7e7a.

⛔ Files ignored due to path filters (1)
  • types.d.ts is excluded by !types.d.ts
📒 Files selected for processing (12)
  • lib/HotModuleReplacementPlugin.js
  • lib/hmr/parserHooks.js
  • lib/html/HtmlModulesPlugin.js
  • lib/html/HtmlParser.js
  • lib/html/syntax.js
  • lib/javascript/syntax.js
  • test/HotModuleReplacementPlugin.unittest.js
  • test/HtmlEntryWrapper.unittest.js
  • test/collectCjsRequireSpecifiers.unittest.js
  • test/configCases/plugins/add-lazy-runtime-module/MarkerRuntimeModule.js
  • test/configCases/plugins/add-lazy-runtime-module/index.js
  • test/configCases/plugins/add-lazy-runtime-module/webpack.config.js
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • webpack/schema-utils (auto-detected)
  • webpack/tapable (auto-detected)
🚧 Files skipped from review as they are similar to previous changes (10)
  • test/configCases/plugins/add-lazy-runtime-module/MarkerRuntimeModule.js
  • test/configCases/plugins/add-lazy-runtime-module/index.js
  • test/HotModuleReplacementPlugin.unittest.js
  • test/collectCjsRequireSpecifiers.unittest.js
  • lib/HotModuleReplacementPlugin.js
  • lib/html/HtmlModulesPlugin.js
  • lib/hmr/parserHooks.js
  • lib/javascript/syntax.js
  • test/configCases/plugins/add-lazy-runtime-module/webpack.config.js
  • lib/html/HtmlParser.js

Comment thread lib/html/syntax.js Resolved
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging perf/lazy-runtime-module-loading into main will be
99.28%
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%214, 234
   CodeGenerationResults.js100%100%100%100%
   CompatibilityPlugin.js100%100%100%100%
   Compilation.js98.43%100%100%98.43%1673, 1992, 1999, 2007, 2029, 2032, 2971, 3450–3451, 3483, 4192, 4222, 4275–4276, 4280, 4285, 4301–4302, 4316–4317, 4322–4323, 4843, 4869, 549, 554, 5679, 5711, 5728, 5746, 5762, 5777, 5802–5803, 5805, 6139, 6144, 6150, 6153, 6160, 6172, 6174, 6178, 6196, 6211, 6245, 6301, 6325, 6441, 801–802
   Compiler.js99.56%100%100%99.56%1168–1169, 1177
   ConcatenationScope.js99.12%100%100%99.12%300
   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%1080, 176–177, 193, 212, 286
   DependenciesBlock.js100%100%100%100%
   Dependency.js98.51%100%100%98.51%480, 527
   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.67%100%100%98.67%1220, 1223, 519–523, 525, 671
   ExternalModuleFactoryPlugin.js100%100%100%100%
   ExternalsPlugin.js100%100%100%100%
   FileSystemInfo.js99.53%100%100%99.53%186, 2454–2455, 2458, 2469, 2480, 2491, 284, 3928, 3943, 3967
   FlagAllModulesAsUsedPlugin.js100%100%100%100%
   FlagDependencyExportsPlugin.js98.36%100%100%98.36%504, 513, 516, 520, 532
   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.51%100%100%98.51%1303, 1308, 1368, 1382, 1444, 1453
   ModuleFactory.js100%100%100%100%
   ModuleFilenameHelpers.js98.90%100%100%98.90%111, 113
   ModuleGraph.js99.78%100%100%99.78%1170
   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.72%100%100%99.72%721
   MultiStats.js100%100%100%100%
   MultiWatching.js100%100%100%100%
   NoEmitOnErrorsPlugin.js100%100%100%100%
   NodeStuffPlugin.js100%100%100%100%
   NormalModule.js97.99%100%100%97.99%1027, 1030, 1047, 1064, 1312, 1346, 1362, 1817, 2114, 2119–2129, 29
   NormalModuleFactory.js98.77%100%100%98.77%1142, 1410, 1421, 1431, 1482–1484, 1491, 536, 548
   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%690
   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.js95.61%100%100%95.61%318, 374, 383, 386, 410, 428, 449–450, 473, 493–494, 530–531, 554, 567–568, 621, 634, 655, 674
   RuntimeTemplate.js100%100%100%100%
   SelfModuleFactory.js100%100%100%100%
   SingleEntryPlugin.js100%100%100%100%
   SourceMapDevToolModuleOptionsPlugin.js100%100%100%100%
   SourceMapDevToolPlugin.js98.63%100%100%98.63%220, 224, 226, 420, 431, 890
   Stats.js100%100%100%100%
   Template.js100%100%100%100%
   TemplatedPathPlugin.js99.47%100%100%99.47%352–353
   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%376
   cli.js98.63%100%100%98.63%10, 119, 549, 581, 631, 905
   index.js99.73%100%100%99.73%184
   validateSchema.js94.67%100%100%94.67%100, 87, 89, 98
   webpack.js97.12%100%100%97.12%10, 267, 289, 291
lib/asset
   AssetBytesGenerator.js100%100%100%100%
   AssetBytesParser.js100%100%100%100%
   AssetGenerator.js100%100%100%100%
   AssetModule.js100%100%100%100%
   AssetModulesPlugin.js98.03%100%100%98.03%324, 348, 351, 43, 48, 481
   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.js92%100%100%92%34, 43
   MemoryWithGcCachePlugin.js93.42%100%100%93.42%108, 122–123, 132, 90
   PackFileCacheStrategy.js96.52%100%100%96.52%1310, 1410, 1414, 1476, 1712, 1796, 1819, 1851, 675, 694, 704–706, 708, 724–725, 730, 733, 735, 740, 745, 770, 776, 810, 816,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: build-perf Build time and memory of webpack itself area: config Options, defaults, validation (lib/config, schemas/) area: css CSS support (lib/css) area: html Experimental HTML support (lib/html) area: loaders Loader execution and loader API (lib/loaders) area: module-federation Module Federation (lib/container, lib/sharing) area: optimization Tree-shaking, splitChunks, concatenation, ids (lib/optimize, lib/ids) area: parser JavaScript parsing and dependency analysis (lib/javascript, lib/dependencies) area: runtime Emitted runtime and chunk loading across targets (lib/runtime, lib/web, lib/node, lib/esm) area: types types.d.ts, JSDoc annotations, hand-maintained declarations area: wasm WebAssembly modules (lib/wasm-*) area: watch Watching, HMR, lazy compilation (lib/hmr, hot/)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant