Summary
src/services/i18n.ts:5 statically imports the full English translation bundle:
import enTranslation from '../locales/en.json';
src/locales/en.json is 131,704 bytes (~30-40KB gzipped). Every page-load downloads + parses the entire dictionary, including keys that are only used by panels the user may never open.
The comment explicitly says "bundle it eagerly" because en is the fallback locale — but eager doesn't have to mean monolithic.
Likely fix
Two options, increasing complexity:
-
Shell + lazy split: extract a small "essential keys" subset (header, nav, error toasts, panel chrome) into en.shell.json (target: <20KB). Keep that as the eager static import. Lazy-load the rest via import.meta.glob (mirrors the existing pattern at i18n.ts:15-18 for other locales). Panels load their slice on mount.
-
Just lazy-load it all: remove the static import; use import.meta.glob for en too. Trade-off: first paint may show raw t('key.path') until the dictionary resolves. Mitigate with a tiny inline fallback for the few keys rendered before hydration.
Option 1 is the better tradeoff — it gives clean first paint while moving most of the weight off the critical path.
Severity
P0 (bundle weight). Compounds with the globe.gl issue — fixing both gives a meaningful first-paint win.
Related
src/services/i18n.ts:5 (static import)
src/locales/*.json (other locales already lazy via line 15-18)
Source
Manual code review (deepseek perf list, validated 2026-05-01).
Summary
src/services/i18n.ts:5statically imports the full English translation bundle:src/locales/en.jsonis 131,704 bytes (~30-40KB gzipped). Every page-load downloads + parses the entire dictionary, including keys that are only used by panels the user may never open.The comment explicitly says "bundle it eagerly" because en is the fallback locale — but eager doesn't have to mean monolithic.
Likely fix
Two options, increasing complexity:
Shell + lazy split: extract a small "essential keys" subset (header, nav, error toasts, panel chrome) into
en.shell.json(target: <20KB). Keep that as the eager static import. Lazy-load the rest viaimport.meta.glob(mirrors the existing pattern ati18n.ts:15-18for other locales). Panels load their slice on mount.Just lazy-load it all: remove the static import; use
import.meta.globfor en too. Trade-off: first paint may show rawt('key.path')until the dictionary resolves. Mitigate with a tiny inline fallback for the few keys rendered before hydration.Option 1 is the better tradeoff — it gives clean first paint while moving most of the weight off the critical path.
Severity
P0 (bundle weight). Compounds with the globe.gl issue — fixing both gives a meaningful first-paint win.
Related
src/services/i18n.ts:5(static import)src/locales/*.json(other locales already lazy via line 15-18)Source
Manual code review (deepseek perf list, validated 2026-05-01).