Repository navigation
perf(clients): bring initial-load bundles back under the pre-Vite 8 size - #1466
Merged
Merged
Conversation
Rolldown split the code each app's entry loads up front into 45 (admin) and 68 (dashboard) tiny chunks, and each one compresses on its own. Initial load grew past what Rollup shipped. - vite.config.ts: group everything the entry statically imports (Rolldown's $initial tag) into one vendor and one app chunk. Route pages stay lazy. - i18n: only the shell's en-US catalogs ship in the main bundle. Route catalogs load with their route through lazyNamed(importer, name, namespaces), in parallel with the page chunk, so a page never renders before its text is there. The command palette loads its own catalog. A new tests/i18n/route-namespaces.spec.ts walks each route's import graph and fails when a route doesn't list a namespace its page uses. - admin: import SignalR on first connect, like the dashboard already does. Initial load (entry JS + CSS, gzip -9): admin 265.4 -> 225.1 KiB, dashboard 271.3 -> 229.9 KiB. Pre-upgrade was 242.9 and 245.2 KiB. Closes #1462
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #1462.
The Vite 8 upgrade grew the initial load of both apps. Most of that wasn't new code. Rolldown split everything the entry loads up front into 45 (admin) and 68 (dashboard) small chunks, and each one compresses on its own. Concatenated, the same JS gzips about 20 KiB smaller. The dependency bumps added roughly 13 KiB on top.
What changed
Chunking (
vite.config.ts, both apps). The entry's static import graph now goes into onevendorand oneappchunk, using Rolldown's$initialtag inbuild.rolldownOptions.output.codeSplitting.groups. Route pages aren't$initial, so they stay lazy and are chunked as before.chunkSizeWarningLimitgoes to 600 kB, because the ~560 kB minified vendor chunk is intentional.Route translation catalogs (
src/i18n.ts,src/routes.tsx, both apps). Only the namespaces the shell renders with ship in the main bundle:common,auth,notificationsnavanddashboardEvery other en-US catalog is a small lazy chunk.
lazyNamed(importer, name, namespaces)loads a route's namespaces in parallel with its page chunk, so the page doesn't render until its text is there. There's no flash and no extra round trip. The dashboard's command palette loads its own catalog alongside the dialog. pt-BR still loads as one chunk, as before.Guard test (
tests/i18n/route-namespaces.spec.ts, both apps). It walks the static import graph of every lazy route and fails when a page, or a component it imports, uses a namespace its route doesn't list. It also checks that the shell only uses eager namespaces. I removedfilesfrom the profile route to check that it fails, and it does, namingcomponents/file/image-input.tsx.Admin SignalR: now imported on first connect, the way the dashboard already does it. It was about 25 KiB gzip of the initial load, and the sign-in page doesn't need it.
Rules:
.agents/rules/frontend/shared.mdand theadd-react-pageskill now describe the eager and lazy catalog maps and thelazyNamednamespaces argument.Numbers
Initial load is the entry script plus every modulepreload and stylesheet in
dist/index.html, each file gzipped at level 9. All three columns were measured the same way. The pre-upgrade column is a build of46939de3, the commit before #1461.mainmain→ this PRThe issue's 225.5 / 226.1 figures counted JS only. Measured that way, this PR is at 206.1 (admin) and 209.2 KiB (dashboard), against a pre-upgrade 224.4 and 225.2.
What didn't help:
$initialgroup. It left the app code in dozens of small chunks, and the dashboard only came down to 251.3 KiB. Adding theappgroup alongside it is what closed the gap. Keeping vendor separate also lets it stay cached across app-only deploys.Tested
npm ci,npm run lint(0 errors; the warnings are the same as onmain),tsc -b --noEmitclean,npm run build.[i18n] missing keywarnings in either runvite preview):format.specimports/src/lib/format.tsfrom the dev server, and the demo-accounts dialog only renders in DEV.