…rites a chunk (#25691)
## 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.
Fixes #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.
---------
Co-authored-by: totally-not-ai[bot] <290682512+totally-not-ai[bot]@users.noreply.github.com>
Co-authored-by: Artur Signell <artur@vaadin.com>
This PR cherry-picks changes from the original PR #25691 to branch 25.3.
Original PR description