Skip to content

perf: reduce HTML parser memory and CPU with parser-level skip options#21323

Merged
alexander-akait merged 12 commits into
mainfrom
claude/html-parser-perf-compare-hcqefg
Jul 2, 2026
Merged

perf: reduce HTML parser memory and CPU with parser-level skip options#21323
alexander-akait merged 12 commits into
mainfrom
claude/html-parser-perf-compare-hcqefg

Conversation

@alexander-akait

Copy link
Copy Markdown
Member

Summary

The experimental HTML parser (experiments.html) built a full object-per-node DOM for every module and retained data the consumer never reads. This PR lets buildHtmlAst / the HTML SourceProcessor omit AST node kinds a consumer doesn't need, via a skip option ({ text, comments, doctype }), and wires HtmlParser to use it: it drops all Text nodes (reading <script>/<style> bodies by offset via a new contentEnd) and the doctype node, while keeping comments for magic comments. It also aligns the HTML parser entry with the CSS parser (the AST is built inside .process(...), so the consumer no longer calls buildHtmlAst or passes a pre-built ast — that unused process option is removed), adds a plain-text fast path under skip.text that avoids a slice + entity-decode of a string that is immediately discarded, and shares one frozen children array for void elements. Net on text-heavy documents: ~28% less parser heap and ~10%+ less CPU, with parse results unchanged.

What kind of change does this PR introduce?

perf (with the supporting refactor of the parser's process API).

Did you add tests for your changes?

Yes. test/buildHtmlAst.unittest.js gains a "skip options preserve element structure" block asserting the element tree + offsets are identical under every skip combination across construction edge cases (foster parenting, adoption agency, foreign content, quirks, and the skip.text whitespace fast-path fallbacks — character references, CR, NUL). test/HtmlParser.unittest.js was converted to drive the real parser on real HTML instead of mocking buildHtmlAst.

Does this PR introduce a breaking change?

No. The changes are internal to the experimental HTML support; the skip options are opt-in and default buildHtmlAst output is byte-identical (verified against the previous behavior).

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

n/a — internal parser change, no public config surface.

Use of AI

Yes. AI (Claude) was used to profile the parser, prototype and measure each optimization, and draft the implementation and tests. Every change was verified with byte-identical-AST comparisons against the prior behavior and the added guard tests; the full jest/html5lib/tsc/lint suites should be confirmed green by CI on this PR (they could not be run in the authoring environment).


Generated by Claude Code

Add an opt-in `rawText` mode to `buildHtmlAst` used by `HtmlParser`: text
nodes keep only their source offsets instead of a decoded/coalesced string,
which the walk never reads (bodies are re-sliced from offsets). Tree-
construction decisions still use the decoded value and merging mirrors the
default path, so node structure and offsets are unchanged. Cuts HTML parse
heap ~6% and time ~8% on text-heavy documents.
Align `HtmlParser` with `CssParser`: rather than calling `buildHtmlAst` and
passing a pre-built `ast`, it now calls `.process(source, { skipTextData: true })`
and the AST is built inside the processor's grammar. Rename the `rawText`
option to `skipTextData` and pass it through the process options object, like
the CSS `as` option. Node structure and offsets are unchanged.

Convert the HtmlParser unit tests to drive the real parser on real HTML
instead of mocking `buildHtmlAst`.
`options.ast` only existed so the old `HtmlParser` could pass a pre-built
tree; with AST building moved inside the processor's grammar nothing supplies
it, and the CSS `SourceProcessor` has no equivalent. `fragmentContext` stays:
it is the HTML analog of the CSS `as` parse-mode option and is exercised by the
html5lib fragment conformance tests.
Generalize the text-data optimization into a `skip` set on `buildHtmlAst` /
the HTML processor: `skip.text` (drop prose text, keep only raw-text element
bodies, offset-only), `skip.comments` (drop comment nodes) and `skip.doctype`
(drop the doctype node; quirks detection is unaffected). Skips are pure output
reductions — tree construction runs unchanged, so element structure and offsets
are identical with any combination.

`HtmlParser` enables `{ text, doctype }` (it reads script/style bodies by offset
and never reads prose text or the doctype); comments stay for `webpackIgnore`.
On a text-heavy 554 KiB document this cuts parser heap ~28% and time ~44%.

Add a buildHtmlAst test asserting every skip combination yields the same element
tree across construction edge cases (foster parenting, adoption agency, foreign
content, raw-text elements, quirks).
`text` was misleading — the flag drops only prose (flow-content) text and
keeps raw-text element bodies (`<script>`/`<style>`/`<textarea>`/`<title>`/…),
so `proseText` names what it actually does. `HtmlParser` now passes
`skip: { proseText: true, doctype: true }`.

Expand the skip guard tests: foreign-content CDATA, quirks (no-doctype),
entity/whitespace routing, all four raw-text body types, button scope, and
fragment-context parsing — asserting the element tree is identical under every
skip combination, and that all raw-text bodies survive offset-only.
…Text node

Rename the misleading `proseText` to `text` (the DOM/WHATWG node type) and make
it drop *every* Text node rather than keeping raw-text element bodies. A
raw-text element's body span is instead recorded as its `contentEnd` offset, so
`HtmlParser` reads `<script>`/`<style>` content as [`tagEnd`, `contentEnd`]
without a Text node. Also rename `TEXT_CONTENT_ELEMENTS` to `RAW_TEXT_ELEMENTS`
(the spec's raw text / escapable raw text elements). Memory is unchanged (~28%);
element structure and offsets stay identical under any skip combination.
Under `skip.text` the text node is dropped, so construction only needs the
run's whitespace-ness. For plain text — no entity, NUL, CR, or pending
leading-newline swallow — the decoded value equals the raw range, so scan it
once and dispatch a canonical whitespace marker instead of slicing and entity-
decoding a string that is immediately discarded. Anything trickier falls
through to the exact path unchanged.

Cuts ~4-8% off parse time on text-heavy documents (more on markup with fewer
entities). Element structure and offsets stay byte-identical; the skip guard
tests add whitespace-entity / CR / NUL cases to lock in the fallbacks.
Void elements are inserted and immediately popped, so they never receive
children — mkEl can hand them a shared frozen empty array instead of allocating
one per element (~1200 arrays on a large document). Frozen so any accidental
append throws rather than corrupting the shared instance. ~1% less parser heap;
AST unchanged.
Copilot AI review requested due to automatic review settings July 1, 2026 16:23
@changeset-bot

changeset-bot Bot commented Jul 1, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a68f231

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 1, 2026

Copy link
Copy Markdown
Contributor

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

Install it locally:

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

@codspeed-hq

codspeed-hq Bot commented Jul 1, 2026

Copy link
Copy Markdown

Merging this PR will degrade performance by 35.6%

⚠️ 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
❌ 1 regressed benchmark
✅ 142 untouched benchmarks

Warning

Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Mode Benchmark BASE HEAD Efficiency
Memory benchmark "asset-modules-inline", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' 384.4 KB 1,195.8 KB -67.86%
Memory benchmark "many-modules-esm", scenario '{"name":"mode-production","mode":"production"}' 9.7 MB 7.5 MB +29.01%

Tip

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


Comparing claude/html-parser-perf-compare-hcqefg (a68f231) with main (e848598)

Open in CodSpeed

Copilot AI 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.

Pull request overview

This PR optimizes webpack’s experimental HTML parsing pipeline by allowing the HTML AST builder / SourceProcessor to skip emitting AST node kinds that the HtmlParser consumer doesn’t read, reducing allocations and parse overhead while keeping tree construction behavior the same.

Changes:

  • Add skip options to buildHtmlAst / HTML SourceProcessor to omit text, comments, and/or doctype nodes, and record raw-text body spans via contentEnd.
  • Update HtmlParser to parse via SourceProcessor.process(...) with parser-level skip options and to extract inline <script>/<style> bodies by offset ranges.
  • Update/extend unit tests and add a changeset entry for the optimization.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
lib/html/syntax.js Adds AST-skip options, contentEnd, shared empty children array, and changes grammar to build AST internally.
lib/html/HtmlParser.js Switches to parser-level skip options and reads inline bodies via [tagEnd, contentEnd].
test/HtmlParser.unittest.js Converts tests to drive real HTML parsing end-to-end (no AST mocking).
test/buildHtmlAst.unittest.js Adds coverage ensuring skip options preserve element structure/offsets and validates contentEnd behavior.
.changeset/html-parser-drop-text-data.md Documents the performance optimization as a patch changeset.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread lib/html/syntax.js
};

walk(options.ast || buildHtmlAst(input, options.fragmentContext), null);
walk(buildHtmlAst(input, options.fragmentContext, options.skip), null);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Dropping ast was intentional (it was unused). The stale test that passed { ast } has been removed, so nothing relies on it anymore.


Generated by Claude Code

Comment thread lib/html/syntax.js
Comment on lines 7381 to 7385
/**
* @typedef {object} HtmlProcessOptions
* @property {string=} fragmentContext context element tag name for fragment parsing (see `buildHtmlAst`)
* @property {(HtmlDocument | HtmlDocumentFragment)=} ast walk this pre-built AST instead of parsing the input
* @property {string=} fragmentContext context element tag name for fragment parsing (see `buildHtmlAst`); the HTML analog of the CSS parser's `as` parse-mode option
* @property {HtmlAstSkip=} skip node kinds to omit from the AST for speed/memory (see `HtmlAstSkip`)
*/

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

ast is deliberately removed rather than kept for compat, and the only test that used it is gone, so the typedef stays free of it.


Generated by Claude Code

Comment thread lib/html/HtmlParser.js
Comment on lines +1118 to 1123
// `skip.text` drops the body `Text` node; the raw content
// span is [`tagEnd`, `contentEnd`] on the element.
const bodyStart = node.tagEnd;
const bodyEnd = node.contentEnd;
if (bodyEnd <= bodyStart) continue;
value = source.slice(bodyStart, bodyEnd);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Good catch — the root cause was cloneSubtree not setting contentEnd. Fixed there so every element (cloned included) carries a numeric contentEnd, so bodyEnd can no longer be undefined here.


Generated by Claude Code

Comment thread lib/html/syntax.js
Comment on lines +4721 to 4727
// End of a raw-text element's body under `skip.text` (defaults to the
// body start, i.e. empty); lets consumers read `<script>`/`<style>`
// content as [`tagEnd`, `contentEnd`] without a `Text` node.
contentEnd: pos ? pos.tagEnd : 0,
// Present from creation (only `<template>` fills it) so every element
// keeps one monomorphic hidden class for the open-stack/scope loops.
templateContent: undefined

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Done — cloneSubtree now sets contentEnd and clones templateContent (recursively) so cloned elements match mkEl's monomorphic shape.


Generated by Claude Code

Copilot AI review requested due to automatic review settings July 1, 2026 16:29
@codecov

codecov Bot commented Jul 1, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 92.48%. Comparing base (3cb8578) to head (a68f231).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #21323      +/-   ##
==========================================
- Coverage   92.86%   92.48%   -0.39%     
==========================================
  Files         594      594              
  Lines       65210    65240      +30     
  Branches    18143    18154      +11     
==========================================
- Hits        60559    60337     -222     
- Misses       4651     4903     +252     
Flag Coverage Δ
css-parsing 28.60% <ø> (ø)
html5lib 28.23% <85.36%> (-2.91%) ⬇️
integration 88.87% <92.68%> (-0.02%) ⬇️
test262 45.55% <ø> (-0.01%) ⬇️
unit 43.19% <100.00%> (+0.11%) ⬆️

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.

cloneSubtree now sets contentEnd and clones templateContent so cloned
elements match mkEl's shape and never expose an undefined contentEnd.

Copilot AI 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.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Comments suppressed due to low confidence (1)

test/buildHtmlAst.unittest.js:837

  • This multi-line comment is longer than the repo's guidance for comments in test/ (AGENTS.md:110 suggests 1 line, max 2 short lines). Consider shortening it to a compact statement of intent.
		);
		expect(child(child(t.children, "colgroup").children, "col")).toBeDefined();
		expect(find("<table><colgroup>", "colgroup")).toBeDefined();
		expect(

Comment thread test/buildHtmlAst.unittest.js
Comment thread test/HtmlParser.unittest.js Outdated
Comment on lines +5 to +8
// These tests drive the real tree builder end-to-end (like the CSS parser
// tests): `HtmlParser` builds the AST inside `SourceProcessor.process`, so
// there is nothing to mock — each case parses real HTML and asserts the
// extracted dependencies.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Shortened to two lines.


Generated by Claude Code

Comment thread lib/html/HtmlParser.js Outdated
Comment on lines +1459 to +1463
// Skip the AST output this walk never reads: all `text` nodes (it reads
// `<script>`/`<style>` bodies by offset, via each element's `contentEnd`)
// and the `doctype` node. `comments` are NOT skipped — magic comments
// (`webpackIgnore`) need them. The processor builds the AST internally
// (like the CSS parser).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Condensed to three lines.


Generated by Claude Code

Comment thread lib/html/syntax.js Outdated
Comment on lines +4506 to +4508
// Shared frozen children array for void elements — they are inserted and
// immediately popped, so they never receive children. Frozen so any (buggy)
// append throws instead of corrupting the shared instance.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Condensed to two lines.


Generated by Claude Code

Comment thread lib/html/syntax.js Outdated
Comment on lines +7102 to +7107
// `skip.text` fast path: the node is dropped, so construction only needs
// the run's whitespace-ness (`isAllWs` / framesetOk). For plain text —
// no `&` (entities), `\0`, `\r`, or a pending leading-newline swallow —
// the decoded value equals the raw range, so scan it and dispatch a
// canonical marker (`" "` all-whitespace, `"x"` otherwise), skipping the
// per-run slice + entity decode. Anything trickier falls through.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Condensed to four lines while keeping the decode-skip invariant.


Generated by Claude Code

Comment thread lib/html/syntax.js
Copilot AI review requested due to automatic review settings July 1, 2026 16:36

Copilot AI 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.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Comment thread lib/html/syntax.js Outdated
Under skip.text, foreign-content <script>/<style> (e.g. SVG <style>) lost
their body span because contentEnd was HTML-namespace only, while HtmlParser
extracts those bodies regardless of namespace. Record it for every raw-text
tag name. Also broaden the skip-combination guard, add coverage, and tighten
comments.
@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Types Coverage

Coverage after merging claude/html-parser-perf-compare-hcqefg into main will be
99.36%
Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
bin
   webpack.js98.77%100%100%98.77%91
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.js91.30%100%100%91.30%140, 142–143, 145, 147, 153–154, 161, 168, 90
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.43%100%100%98.43%1641, 1960, 1967, 1975, 1997, 2000, 2939, 3418–3419, 3451, 4117, 4147, 4200–4201, 4205, 4210, 4226–4227, 4241–4242, 4247–4248, 4725, 4751, 526, 531, 5559, 5591, 5608, 5624, 5640, 5655, 5680–5681, 5683, 6011, 6016, 6022, 6025, 6037, 6039, 6043, 6059, 6074, 6106, 6160, 6184, 6298, 777–778
   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.js100%100%100%100%
   ContextModuleFactory.js97.40%100%100%97.40%258, 395, 418, 420, 424, 433–434
   ContextReplacementPlugin.js100%100%100%100%
   DefinePlugin.js98.99%100%100%98.99%172–173, 189, 208, 282
   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.55%100%100%98.55%1100, 1103, 502–506, 508, 654
   ExternalModuleFactoryPlugin.js100%100%100%100%
   ExternalsPlugin.js100%100%100%100%
   FileSystemInfo.js99.52%100%100%99.52%182, 2382–2383, 2386, 2397, 2408, 2419, 280, 3823, 3838, 3862
   FlagAllModulesAsUsedPlugin.js100%100%100%100%
   FlagDependencyExportsPlugin.js98.42%100%100%98.42%413, 422, 424, 428
   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%1285, 1290, 1350, 1364, 1426, 1435
   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.69%100%100%99.69%661
   MultiStats.js100%100%100%100%
   MultiWatching.js100%100%100%100%
   NoEmitOnErrorsPlugin.js100%100%100%100%
   NodeStuffPlugin.js100%100%100%100%
   NormalModule.js97.89%100%100%97.89%1227, 1230, 1247, 1264, 1511, 1545, 1561, 1648, 2004, 2303, 2308–2318, 419, 423, 577
   NormalModuleFactory.js99.47%100%100%99.47%1083, 1392, 486, 498
   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.js98.85%100%100%98.85%527–528, 533, 535, 599
   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.js96.33%100%100%96.33%10, 198, 220, 222
lib/asset
   AssetBytesGenerator.js100%100%100%100%
   AssetBytesParser.js100%100%100%100%
   AssetGenerator.js100%100%100%100%
   AssetModule.js100%100%100%100%
   AssetModulesPlugin.js97.33%100%100%97.33%282, 306, 309, 36, 362, 41
   AssetParser.js100%100%100%100%
   AssetSourceGenerator.js100%100%100%100%
   AssetSourceParser.js100%100%100%100%
   RawDataUrlModule.js100%100%100%100%
lib/async-modules
   AsyncModuleHelpers.js100%100%100%100%
   AwaitDependenciesInitFragment.js100%100%100%100%
   InferAsyncModulesPlugin.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.40%100%100%96.40%1251, 1351, 1355, 1417, 628, 647, 657–659, 661, 677–678, 683, 686, 688, 693, 698, 723, 729, 763, 769, 775, 780, 791, 800, 805–806, 808, 825, 831–832, 834
   ResolverCachePlugin.js100%100%100%100%
   getLazyHashedEtag.js100%100%100%100%
   mergeEtags.js100%100%100%100%
lib/config
   browserslistTargetHandler.js100%100%100%100%
   defaults.js99.33%100%100%99.33%1468–1470, 1478, 274,

@alexander-akait alexander-akait merged commit f7a3f6d into main Jul 2, 2026
104 of 105 checks passed
@alexander-akait alexander-akait deleted the claude/html-parser-perf-compare-hcqefg branch July 2, 2026 14:36
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.

2 participants