Skip to content

fix(i18n): keep production sourcemaps usable when the i18n plugin rewrites a chunk - #25691

Open
totally-not-ai[bot] wants to merge 2 commits into
mainfrom
fix/i18n-plugin-breaking-production-sourcemaps
Open

fix(i18n): keep production sourcemaps usable when the i18n plugin rewrites a chunk#25691
totally-not-ai[bot] wants to merge 2 commits into
mainfrom
fix/i18n-plugin-breaking-production-sourcemaps

Conversation

@totally-not-ai

Copy link
Copy Markdown
Contributor

Summary

The Vaadin i18n build plugin replaced the sourcemap of every chunk with an empty one, so all .map files of an app built with build.sourcemap enabled were useless. The plugin now rewrites chunks at a point where the bundler keeps the original sourcemap, and leaves untouched chunks alone.

Related to #16679

What changed

Behavior change: only apps that build with build.sourcemap enabled are affected, and only for the better — their .map files now contain the real sources instead of being empty. Chunk output itself is unchanged, so no API or runtime behavior changes for anyone else.

  • rollup-plugin-vaadin-i18n.js moves the chunk rewriting from generateBundle to renderChunk. The bundler then composes the map returned by the plugin with the map it already has for that chunk. Chunks the plugin does not touch return null and keep their sourcemap as is. generateBundle still collects the translation keys.
  • The registerChunk calls are now found with a regular expression instead of an exact string match. It tolerates a renamed i18n binding and rewritten string quotes, so duplicate calls are removed and the chunk name marker is replaced also when the bundler has reformatted the rendered chunk.
  • The vite-production test app now uses Hilla translations in two frontend modules (via a small stub of @vaadin/hilla-react-i18n) and builds with sourcemaps on, so the tests actually run through the rewriting path.

Test summary

# Status What the test verifies Why it matters
1 Every .map file reachable from the entry bundle has non-empty sources, non-empty mappings, and the contents of each source This is the bug: a rewritten chunk got a map with no sources, so the browser could not map the bundle back to the original files
2 Chunks the plugin does not rewrite still have a usable sourcemap The early return null must not drop maps the bundler produced
3 The chunk that contains translations calls registerChunk with its own served file name, and the marker is gone A wrong or unreplaced name means the runtime cannot load the translations of that chunk
4 That chunk has exactly one registerChunk call Duplicate calls from several modules must be removed; a missed match would also leave a stale marker behind
5 gap Matching when the bundler renames the i18n binding or rewrites the string quotes The regex exists for this case, but no test forces that output shape; whether it happens depends on the minifier settings of the test app

Tests added on this branch:

  • SourceMapsIT.bundleSourceMapsPointToOriginalSources — rows 1, 2
  • I18nChunkIT.chunkRegistersItselfUnderItsOwnName — rows 3, 4

Left untested on purpose: BundleAccess is a test helper that only downloads bundle files, so it is covered indirectly by both ITs.

The i18n Vite plugin rewrote every chunk in generateBundle and replaced
the chunk sourcemap with a MagicString map that has no sources, so all
.map files of an application built with build.sourcemap enabled came out
empty. The rewriting now happens in renderChunk, where the bundler
composes the returned map with the one it already has for the chunk, and
chunks the plugin does not touch keep their sourcemap as is.

The registerChunk calls are now matched with a pattern that tolerates
renamed bindings and rewritten string quotes, so the duplicate calls are
removed and every chunk name marker is replaced also when the bundler
has reformatted the rendered chunk.

Related to #16679
The production test application now uses Hilla translations in two
frontend modules, so that the i18n build plugin rewrites the chunk they
end up in. Without them the plugin left every chunk untouched and the
sourcemap test only covered the chunks the plugin does not rewrite.

The sourcemap test also follows the imports of the entry bundle
transitively and checks that the sources of a map are the original
files, with their contents, instead of only counting them.
@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

Test Results

 1 442 files  +2   1 526 suites  +2   1h 31m 36s ⏱️ - 3m 1s
12 062 tests +2  11 994 ✅ +2  68 💤 ±0  0 ❌ ±0 
12 380 runs  +2  12 312 ✅ +2  68 💤 ±0  0 ❌ ±0 

Results for commit 78f3383. ± Comparison against base commit 980ac5b.

@Artur-
Artur- requested a review from platosha September 12, 2026 11:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants