Repository navigation
feat(minify): inline more functions and values, merge imports and exports - #22909
Conversation
🦋 Changeset detectedLatest commit: c587583 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 of its latest commit is available. Install it locally:
npm i -D webpack@https://pkg.pr.new/webpack@22909
yarn add -D webpack@https://pkg.pr.new/webpack@22909
pnpm add -D webpack@https://pkg.pr.new/webpack@22909 |
Types CoverageCoverage after merging feat/minify-inline-gaps into main will be
Coverage Report |
Generated code sizeComparing base (
Read 8 asset(s) changed size, test untouched
No runtime gained or lost a runtime module. Built |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Value tracking and guarded folding lib/javascript/syntax-printer.js, test/unitCases/javascript/printer.unittest.js |
The compressor tracks eligible local and object-literal values, checks declaration order and execution effects, and applies guarded substitutions and property-hoisting changes. Tests cover rewrites and cases where reads must remain. |
Inlining and declaration movement lib/javascript/syntax-printer.js, test/unitCases/javascript/printer.unittest.js |
The compressor adds guarded argument substitution and function copying, top-level function inlining, and declaration movement into loop heads or later declarations. Tests cover applicable rewrites and preservation conditions. |
Module and expression rewrites lib/javascript/syntax-printer.js, test/unitCases/javascript/printer.unittest.js |
The compressor merges compatible imports and exports, folds eligible declarations into default exports, and adjusts expression ordering and conditional-throw merging. |
Documentation and comparison updates .changeset/066-minify-inline-gaps.md, docs/syntax.md, test/helpers/oxcSmaller.js, test/helpers/swcSmaller.js, test/specCases/minify-corpora.spectest.js, test/unitCases/javascript/printer.unittest.js |
The syntax documentation and Changeset describe minification changes. Comparison lists and corpus exceptions are updated. Compression tests also include a fixture-expression change. |
Possibly related PRs
- webpack/webpack#22897: Both changes address tagged-template
thisbehavior insyntax-printer.jsand update related tests and comparison entries. - webpack/webpack#22887: Both changes modify the
minify-corporatest contract.
Priority:
Change: Feature
Merge Risk: 
Minimal · up to c5875
-
No actionable merge-blocking risk is identified in the supplied incremental change; normal checks can proceed.
Pre-merge checks: 
4
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
Merging this PR will not alter performance1 warning, 1 note
Comparing |
…ve bare vars later, numbers last Claude-Session: https://claude.ai/code/session_01ViD41i2KdwwGxrDk7yrjeD
terser writes `2*e` for `value * 2`, which writing numbers last turns back, so the byte-for-byte comparison with the reference minifier would test the improve phase rather than the plugin's comments and maps. Claude-Session: https://claude.ai/code/session_01ViD41i2KdwwGxrDk7yrjeD
…rimitives off object literals Also keeps a constant-left sequence lift out of the right side of `||`, `&&` and `??`, which dropped code the operator would run. Claude-Session: https://claude.ai/code/session_01ViD41i2KdwwGxrDk7yrjeD
5ec541b to
c587583
Compare
…own unit tests (#22942) * test(javascript): cover the settling pass and other printer gaps main brought in Eleven cases, each held to running as its source does, reach what the printer test left unrun of #22909's settling of known values and the built-ins probe. The operator each switch was left with is its default. Claude-Session: https://claude.ai/code/session_017TkBWTk3wcyUcJYDp5ZhaP * test: cover hasOctalEscape and fold two fallbacks nothing reaches `new Set(undefined)` is already the empty set a missing family gave, and the cold template reader never starts at a chunk's start, which the fast reader handles before handing it over. Claude-Session: https://claude.ai/code/session_017TkBWTk3wcyUcJYDp5ZhaP * ci: hold each language's syntax to its own unit tests `yarn test:syntax-coverage` runs each language's tokenizer, parser, printer and minifier tests in a jest process of its own and fails when what they never run grows past tooling/syntax-coverage.json. CI runs it when a pull request touches the syntax or its tests. Claude-Session: https://claude.ai/code/session_017TkBWTk3wcyUcJYDp5ZhaP * chore: shorten the conditional comment changeset to one sentence Claude-Session: https://claude.ai/code/session_017TkBWTk3wcyUcJYDp5ZhaP * test(javascript): drop the handler cases #22926 left nothing to test An event handler is now minified as a function body itself, so there is no wrap to read back and no answer to fall back from; the three cases that held that fallback fail on main. Claude-Session: https://claude.ai/code/session_017TkBWTk3wcyUcJYDp5ZhaP * ci: drop the syntax-coverage job, keep yarn test:syntax-coverage local Claude-Session: https://claude.ai/code/session_017TkBWTk3wcyUcJYDp5ZhaP
Summary
Closes more of the size gaps between webpack's JS minifier and swc/oxc. Every change is in the
improvephase, which writes less than terser only where the program provably runs the same.let/const, and into afor…in/for…ofobject. A binding whose straight-line writes leave every read known is replaced by its value. A primitive is read straight off an object literal.toplevelowns itsvars. A literal argument is read in place of its parameter. A small function called from several places is copied into each call when its arguments are read in order.imports andexport{…}lists of one module merge.function f(){}…export default fbecomesexport default function f(){}. A barevarmoves into a latervar. A number moves to the right of*,&,|and^, as oxc and esbuild write it.this(now(0,a.b)```). A sequence on the right of a constant-left||/&&/??` is no longer lifted out, which dropped code the operator would run.Gap lists:
swcSmaller.js−23/+1,oxcSmaller.js−16/+8. The added entries are 1–3 bytes of gzip noise from writing numbers last, or cases where oxc's output is wrong (thisof a tag).Before/after (
compress: {},mangle: false; raw/gzip bytes):main(function(){ var e = g(); s = e; })()(inline: false)!function(){var e=g();s=e}()— 72/86!function(){s=g()}()— 64/78let a = 1; if (o) a = 2; else a = 2; a++; console.log(a);let a=1;a=2,console.log(++a)— 48/68console.log(3)— 34/54export { f as a }; export { b } from 'm'; export { c } from 'm'; export default f;(default options, module)function a(){return 1}export{a};export{b}from"m";export{c}from"m";export default a;— 83/78export default function a(){return 1}export{a};export{b,c}from"m";— 66/77The 31
schemas/**/*.check.jsvalidators are regenerated, since they are minified with this printer.What kind of change does this PR introduce?
feat
Did you add tests for your changes?
Yes:
test/unitCases/javascript/printer.unittest.js(what transforms and what must not), plus the gap lists andIMPROVED_YET_BIGGERintest/specCases/minify-corpora.spectest.js. ThejsMinifyfixture now usesvalue + 1, so its byte-for-byte comparison with terser tests the plugin rather than the improve phase.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?
docs/syntax.md(thesyntax-printer.jsbullet) describes the new rewrites.Use of AI
Claude Code wrote the changes and tests: four agents each triaged one family of gap-list entries, and the results were merged and checked with the printer unit tests, the corpus groups, the fuzz seeds and
yarn lint.Generated by Claude Code
Summary by CodeRabbit