fix(@angular/build): stabilize chunk hashes during i18n inlining#32889
fix(@angular/build): stabilize chunk hashes during i18n inlining#32889maruthang wants to merge 1 commit intoangular:mainfrom
Conversation
Previously, a global SHA-256 hash of ALL translation files was appended as a footer comment to every JavaScript output file. This caused esbuild to generate different content hashes for ALL chunks whenever ANY translation changed, even if the actual code in those chunks was unaffected. This led to complete cache invalidation on every deploy for i18n applications. The fix removes the global i18n footer and instead rehashes output filenames after i18n inlining based on the actual inlined content of each file. Only files whose content actually changed during translation inlining will receive new filename hashes. Cross-chunk import references are also updated to reflect the new filenames. Fixes angular#30675
There was a problem hiding this comment.
Code Review
This pull request refactors the i18n output hashing mechanism to prevent unnecessary cache busting. It removes the global i18n hash footer previously added to all JavaScript files and replaces it with a more granular approach that re-hashes only the files whose content actually changes during the inlining process. The I18nInliner now manages a rename map to update file paths and internal references (like dynamic imports) accordingly. Feedback was provided to extract the specific 8-character hash generation logic into a helper method to improve maintainability and readability.
| const hashBytes = createHash('sha256').update(code).digest(); | ||
| const hashValue = hashBytes.readBigUInt64BE(0); | ||
| const newHash = hashValue.toString(36).slice(0, 8).toUpperCase().padStart(8, '0'); |
There was a problem hiding this comment.
The logic for generating the 8-character uppercase alphanumeric hash (hashValue.toString(36).slice(0, 8).toUpperCase().padStart(8, '0')) is quite dense. Extracting this into a small, private helper method (e.g., _generateShortHash) would improve readability and encapsulate this specific hashing algorithm.
PR Checklist
PR Type
What is the current behavior?
During i18n inlining, chunk hashes are computed from content that includes locale-specific translation dictionaries. When translations change (even for a single locale), all chunk hashes change across all locales, causing unnecessary cache invalidation on every deploy.
Issue Number: #30675
What is the new behavior?
Chunk hashes are now computed from the pre-inlined content (before locale-specific translations are substituted). This ensures that only actual code changes affect chunk hashes, preserving browser cache across deployments when only translations change.
Does this PR introduce a breaking change?