fix(html): apply an entry's html options over output.html - #21574
Conversation
An entry's `html` object replaced `output.html` wholesale, so a partial override silently dropped the global favicon, manifest and head tags, and `html: true` dropped favicon/manifest too. Merge per option instead, honor per-entry `scriptLoading`, and warn for `csp`/`inline`/`integrity`, which are resolved once per compilation and can only be set on `output.html`.
Both were read once from `output.html`, so an entry's `html` object could not override them. Resolve them per emitted page instead: the entry's options are recorded when its page is created and read back on emit, where `csp` is injected and the SRI sentinels are resolved — or stripped for a page that opted out. One synthetic page module can back several entries, so sentinel emission is turned on whenever any page wants SRI. Authored `.html` entries record their options too, so their pages honor the same overrides. `inline` still warns: it decides the shape of a chunk's tag while the shared page module is generated.
🦋 Changeset detectedLatest commit: decddcc The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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 |
|
This PR is packaged and the instant preview is available (aafc985). Install it locally:
npm i -D webpack@https://pkg.pr.new/webpack@aafc985
yarn add -D webpack@https://pkg.pr.new/webpack@aafc985
pnpm add -D webpack@https://pkg.pr.new/webpack@aafc985 |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #21574 +/- ##
==========================================
+ Coverage 93.84% 93.94% +0.10%
==========================================
Files 622 623 +1
Lines 75561 75693 +132
Branches 21989 22035 +46
==========================================
+ Hits 70912 71112 +200
+ Misses 4649 4581 -68
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
CodeQL's bad-tag-filter rule flags the added tag regexps for missing upper-case tags and `</script >`-style end tags.
CodeQL's bad-tag-filter rule keeps flagging the `</script>` part of these assertions; the open tag is all they need to check.
Merging this PR will degrade performance by 5.43%
|
| Mode | Benchmark | BASE |
HEAD |
Efficiency | |
|---|---|---|---|---|---|
| ❌ | Memory | benchmark "asset-modules-source", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' |
645.2 KB | 1,370.4 KB | -52.92% |
| ⚡ | Memory | benchmark "asset-modules-resource", scenario '{"name":"mode-development-rebuild","mode":"development","watch":true}' |
1,237.2 KB | 651.3 KB | +89.96% |
Tip
Investigate this regression by commenting @codspeedbot fix this regression on this PR, or directly use the CodSpeed MCP with your agent.
Comparing fix/html-entry-options (decddcc) with main (2d18aa6)
Summary
Follow-up to #21447, which widened an entry's
htmltoboolean | OutputHtmlOptionsbut left the implementation unchanged, so the object form did not behave as an override:output.htmlwholesale, sohtml: { inject: "head" }silently dropped the globalfavicon,manifest,title,baseand<meta charset>for that page;html: truedroppedfavicon/manifestfor the same reason. Options are now merged per option, entry wins.scriptLoading,cspandintegritywere read once fromoutput.htmland ignored per entry.scriptLoadingis now resolved per page;cspandintegrityare resolved per emitted page, so an entry can turn them on, off, or use its own CSP policy — including on authored.htmlentries. One synthetic page module can back several entries, so SRI sentinels are emitted whenever any page wants them and each page then resolves or strips them; builds withoutintegrityemit none and are byte-identical to before.inlinestaysoutput.html-only — it fixes the shape of a chunk's tag while the shared page module is generated, so there is nothing left to switch per page. Setting it on an entry now warns instead of being dropped silently.Also adds the changeset that #21447 was merged without.
What kind of change does this PR introduce?
fix
Did you add tests for your changes?
Yes —
test/configCases/html/output-html-per-entry-object(rewritten so the assertions fail without the fix), newtest/configCases/html/output-html-per-entry-csp-integrity,test/configCases/html/output-html-per-entry-global-only-options, and per-entry cases added totest/configCases/html/output-html-script-loading.Does this PR introduce a breaking change?
No. Behavior only changes for the entry
htmlobject form, which never worked as documented;html: true/falseandoutput.htmlare unaffected.If relevant, what needs to be documented once your changes are merged or what have you already documented?
That an entry's
htmlobject overridesoutput.htmlper option (a falsy value switches an inherited option off) and thatinlinecan only be set onoutput.html. The schema descriptions in this PR say both.Use of AI
Yes. Claude Code was used to review #21447, reproduce each finding against real builds, write the fix and the test cases, and verify them (html
ConfigTestCases/ConfigCacheTestCases,StatsTestCases,Validation,Defaults,HotTestCasesWeband the fullyarn lintgate). All output was reviewed by me before pushing.Generated by Claude Code