Conversation
… order The compiler plugin merges each component stylesheet and web worker metafile into the main esbuild metafile by iterating `additionalResults` in insertion order. The map is populated as each bundle finishes, so the order varies from build to build. When two entries produce the same output file, for example two components whose stylesheets share a file name and content, or two identical images referenced from different stylesheets, the last merged entry wins and `outputs[<file>].inputs` in the stats file flips between builds of identical sources while every emitted file stays byte-identical. Sort the entries by key before merging so the result is the same on every build. Any consumer of the metafile from `onEnd` sees the same attribution. Fixes angular#34209
There was a problem hiding this comment.
Code Review
This pull request ensures deterministic metafile generation by sorting additional compilation results by key order before merging, preventing non-deterministic output attribution caused by completion-order variations. A test has been added to verify this behavior. The feedback suggests that if the merging logic is eventually updated to merge duplicate output inputs rather than overwriting them, the test assertion should be updated to expect both input files.
|
Thanks for investigating this! However, there are a couple of concerns with this approach:
|
|
Both points taken, and this replaces what I said to the bot above. Pushed as two fixups.
Each spec fails against the code it guards, and the application target passes in full. One detail for the record: unminified CSS carries a source-path comment, so identical stylesheets share a hashed name only when styles are minified, which is why this stayed hidden in development builds. |
Build output is non-deterministic: two builds of identical sources can write different stats files. Merging the component stylesheet metafiles in a stable order fixes it.
PR Checklist
PR Type
What is the current behavior?
Issue Number: #34209
outputs[<file>].inputsin the stats file changes between builds of the same sources. The cause is one loop inbuild.onEnd: the compiler plugin merges each component stylesheet's metafile into the main metafile in the order the stylesheets finished bundling, and when two stylesheets produce the same output file, the last one merged owns the entry. Every emitted file is byte-identical; only the metadata moves.What is the new behavior?
The entries are sorted by key before merging, so the merged metafile is the same on every build.
The new spec builds two components in different directories with identical stylesheets, builds twice, and asserts the shared output is attributed to the same input both times.
Does this PR introduce a breaking change?
Other information
Measured on 22.1.9 with the reproduction at https://github.com/sdjayna/angular-metafile-merge-order-repro (60 components, 12 identical-stylesheet pairs, 4 identical-image pairs): without the change 5 of 5 build pairs differed, in 7 to 10 of 54
outputsentries; with it, 0 of 3 differed and the stats file was byte-identical. The same loop is onmaintoday. The sort runs once per build over one entry per stylesheet, so its cost does not register against the bundling.