-
Notifications
You must be signed in to change notification settings - Fork 388
[feat] implement dynamic imports for locale code splitting #6076
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
- Convert static imports to dynamic imports for all locales except English - Only bundle English locale in the initial bundle - Load other locales on-demand when user switches language - Add loadLocale() function to handle lazy loading of locale files - Update GraphView to await locale loading before switching - Apply changes to both src/i18n.ts and apps/desktop-ui/src/i18n.ts This reduces initial bundle size by deferring non-English locale loading until they are actually needed.
🎨 Storybook Build Status✅ Build completed successfully! ⏰ Completed at: 10/19/2025, 03:33:18 AM UTC 🔗 Links🎉 Your Storybook is ready for review! |
🎭 Playwright Test Results⏰ Completed at: 10/19/2025, 03:49:08 AM UTC 📈 Summary
📊 Test Reports by Browser
🎉 Click on the links above to view detailed test results for each browser configuration. |
- Add proper type constraints to buildLocale function generics - Define LocaleMessages type inferred from English locale structure - Replace 'as any' with 'as LocaleMessages' for type-safe message loading - Add explanatory comments for eslint-disable directives 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
- Move eslint-disable-next-line closer to problematic imports - Use block disable/enable only for loader object sections - Improves code clarity by limiting eslint suppression scope
apps/desktop-ui/src/i18n.ts
Outdated
/** | ||
* Dynamically load a locale and its associated files (nodeDefs, commands, settings) | ||
*/ | ||
async function loadLocale(locale: string): Promise<void> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[architecture] high Priority
Issue: loadLocale function is not exported in desktop-ui version but is used
Context: The function exists but is not exported, preventing external usage for locale switching
Suggestion: Add 'export' keyword before the loadLocale function declaration on this line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 41b15a4 - exported the loadLocale function to make it available for external usage.
src/views/GraphView.vue
Outdated
i18n.global.locale.value = locale as 'en' | 'zh' | 'ru' | 'ja' | ||
// Load the locale dynamically if not already loaded | ||
await loadLocale(locale) | ||
;(i18n.global.locale as any).value = locale |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[quality] medium Priority
Issue: Unsafe type assertion using 'as any' circumvents TypeScript safety
Context: The CLAUDE.md explicitly forbids 'as any' assertions - fix the underlying type issue
Suggestion: Define proper typing for i18n.global.locale or use a type-safe alternative
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in c63ed4e - replaced 'as any' with type-safe assertion using typeof and added error handling.
src/views/GraphView.vue
Outdated
if (locale) { | ||
i18n.global.locale.value = locale as 'en' | 'zh' | 'ru' | 'ja' | ||
// Load the locale dynamically if not already loaded | ||
await loadLocale(locale) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[quality] medium Priority
Issue: Async function in watchEffect lacks error handling
Context: loadLocale can throw errors but they are not caught, potentially causing unhandled promise rejections
Suggestion: Wrap await loadLocale(locale) in try-catch block with appropriate error logging
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in c63ed4e - added try-catch block around loadLocale with proper error logging.
} | ||
|
||
// Locale loader map - dynamically import locales only when needed | ||
const localeLoaders: Record< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[architecture] low Priority
Issue: Significant code duplication between src/i18n.ts and apps/desktop-ui/src/i18n.ts
Context: Almost identical implementations violate DRY principles and increase maintenance overhead
Suggestion: Consider extracting common logic into shared utilities or use a monorepo approach
} | ||
|
||
// Track which locales have been loaded | ||
const loadedLocales = new Set<string>(['en']) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[performance] low Priority
Issue: loadedLocales Set grows indefinitely without cleanup mechanism
Context: In long-running applications, this could lead to minor memory leak if locales are loaded dynamically
Suggestion: Consider adding cleanup mechanism or document that this is acceptable for typical usage patterns
* Dynamically load a locale and its associated files (nodeDefs, commands, settings) | ||
*/ | ||
export async function loadLocale(locale: string): Promise<void> { | ||
if (loadedLocales.has(locale)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[quality] medium Priority
Issue: Potential race condition in concurrent loadLocale calls
Context: If loadLocale is called simultaneously for the same locale, both calls could proceed past the loadedLocales.has() check
Suggestion: Add pending loading state tracking or use a Promise cache to handle concurrent requests for the same locale
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comprehensive PR Review
This review is generated by Claude. It may not always be accurate, as with human reviewers. If you believe that any of the comments are invalid or incorrect, please state why for each. For others, please implement the changes in one way or another.
Review Summary
PR: [feat] implement dynamic imports for locale code splitting (#6076)
Impact: 252 additions, 98 deletions across 3 files
Issue Distribution
- Critical: 0
- High: 1
- Medium: 3
- Low: 2
Category Breakdown
- Architecture: 2 issues
- Security: 0 issues
- Performance: 1 issue
- Code Quality: 3 issues
Key Findings
Architecture & Design
The PR successfully implements dynamic locale loading which is an excellent performance optimization. However, there's a critical API consistency issue where the desktop-ui version doesn't export the loadLocale function, and significant code duplication between the two i18n implementations that should be addressed for maintainability.
Security Considerations
No security issues identified. The dynamic imports are properly scoped and don't introduce security vulnerabilities.
Performance Impact
The code splitting implementation will significantly reduce initial bundle size by loading only English locale eagerly. Minor concern about unbounded growth of loadedLocales Set, but this is acceptable for typical usage patterns with limited locale switching.
Integration Points
The implementation correctly integrates with Vue i18n and maintains backward compatibility. The GraphView integration properly loads locales on demand, though it needs better error handling and type safety improvements.
Positive Observations
- Excellent bundle optimization approach using dynamic imports
- Comprehensive implementation covering all locale file types
- Good use of Promise.all for parallel loading
- Proper TypeScript generics for type safety in buildLocale function
- Maintains backward compatibility with existing locale switching mechanism
References
Next Steps
- Address the missing export in desktop-ui i18n module (high priority)
- Fix unsafe type assertion in GraphView and add error handling
- Consider refactoring to reduce code duplication between i18n implementations
- Add race condition protection for concurrent locale loading
This is a comprehensive automated review. For architectural decisions requiring human judgment, please request additional manual review.
Export the loadLocale function to make it available for external usage in locale switching functionality. This aligns with the src/i18n.ts implementation which already exports this function. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
…loading - Replace 'as any' with type-safe assertion using typeof - Add try-catch block to handle potential errors from loadLocale - Improve error logging for locale switching failures This addresses the code quality issues flagged in the PR review where the CLAUDE.md explicitly forbids 'as any' assertions and requires proper error handling for async operations. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Add a loadingLocales Map to track in-progress locale loads and prevent duplicate concurrent loading of the same locale. When multiple requests come in for the same locale simultaneously, subsequent requests will wait for the existing load to complete rather than initiating new loads. This prevents potential race conditions and resource waste when rapid locale switching occurs or multiple components request the same locale. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
Add desktop-ui to knip workspaces configuration with i18n.ts as an entry point to prevent false positives for exported loadLocale function. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
/** | ||
* Dynamically load a locale and its associated files (nodeDefs, commands, settings) | ||
*/ | ||
export async function loadLocale(locale: string): Promise<void> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[quality] high Priority
Issue: Desktop-ui i18n.ts is missing the 'd' export for date/number formatting that is present in main i18n.ts
Context: This creates API inconsistency between the two i18n modules which could break functionality
Suggestion: Export 'd' along with 't' and 'te' to maintain API consistency: export const { t, te, d } = i18n.global
// Create and track the loading promise | ||
const loadPromise = (async () => { | ||
try { | ||
const [main, nodes, commands, settings] = await Promise.all([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[performance] medium Priority
Issue: Promise.all will fail completely if any single locale file fails to load
Context: Network issues or missing files could prevent all locale loading rather than partial success
Suggestion: Consider Promise.allSettled for more resilient error handling or individual try/catch blocks
}) | ||
watchEffect(() => { | ||
watchEffect(async () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[architecture] low Priority
Issue: async watchEffect could cause unexpected behavior if locale changes rapidly
Context: Multiple rapid locale changes could result in race conditions where old loads complete after new ones
Suggestion: Consider debouncing locale changes or cancelling previous loads using AbortController
project: ['**/*.{js,ts,vue}', '*.{js,ts,mts}'] | ||
}, | ||
'apps/desktop-ui': { | ||
entry: ['src/main.ts', 'src/i18n.ts'], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[quality] low Priority
Issue: Adding i18n.ts as entry point may expose functions not intended for external use
Context: loadLocale is now exported from desktop-ui but may not need to be a Knip entry point
Suggestion: Consider if loadLocale export is actually needed as entry or if it should be internal only
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comprehensive PR Review
This review is generated by Claude. It may not always be accurate, as with human reviewers. If you believe that any of the comments are invalid or incorrect, please state why for each. For others, please implement the changes in one way or another.
Review Summary
PR: [feat] implement dynamic imports for locale code splitting (#6076)
Impact: 297 additions, 98 deletions across 4 files
Issue Distribution
- Critical: 0
- High: 1
- Medium: 1
- Low: 2
Category Breakdown
- Architecture: 1 issues
- Security: 0 issues
- Performance: 1 issues
- Code Quality: 2 issues
Key Findings
Architecture & Design
This PR implements a well-structured code splitting approach for internationalization, moving from eager loading of all locales to dynamic imports. The implementation follows Vue 3 and i18n best practices with proper race condition protection. However, there's a minor inconsistency between the main and desktop-ui i18n modules regarding exported functions.
Security Considerations
No significant security vulnerabilities identified. The dynamic imports are properly structured and use static paths that Vite can resolve at build time.
Performance Impact
Excellent performance improvement through code splitting - this will significantly reduce initial bundle size by removing ~8 languages worth of JSON data from the main bundle. The Promise.all approach could be made more resilient to partial failures.
Integration Points
The changes maintain backward compatibility with existing locale switching mechanisms. Both web and desktop-ui applications are updated consistently. The knip configuration changes properly reflect the new module structure.
Positive Observations
- Excellent implementation of code splitting for i18n
- Proper race condition handling with loadingLocales Map
- Consistent implementation across web and desktop-ui
- Good TypeScript typing with proper generic constraints
- Clean separation of concerns with dedicated loader maps
- Graceful error handling and fallback behavior
- Well-documented ESLint suppressions with explanations
References
Next Steps
- Address API consistency between main and desktop-ui i18n modules
- Consider more resilient error handling for network failures
- Review if race condition handling in watchEffect needs debouncing
- Validate that the knip entry point configuration matches intended API surface
This is a comprehensive automated review. For architectural decisions requiring human judgment, please request additional manual review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
root/assets/index-DsaPWZDT.js/src/locales
Before
Rendered: 3.06MB (25.37%)
Gzip: 653.14KB
Brotli: 530.2KB
After
Rendered: 369.68KB (2.99%)
Gzip: 68.45KB
Brotli: 54.49KB
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Bundle Size ReportSummary
Category Glance Per-category breakdownApp Entry Points — 8.68 MB (baseline 11.7 MB) • 🟢 -3.01 MB_Main entry bundles and manifests_ | File | Before | After | Δ Raw | Δ Gzip | Δ Brotli | | ---------------------------------------- | ------- | ------- | ----------------------- | ----------------------- | ----------------------- | | ~~assets/index-CtdCLNdd.js~~ _(removed)_ | 9.67 MB | — | 🟢 -9.67 MB | 🟢 -1.99 MB | 🟢 -1.43 MB | | **assets/index-Dk18fr6I.js** _(new)_ | — | 6.66 MB | 🔴 +6.66 MB | 🔴 +1.39 MB | 🔴 +1.08 MB | | ~~assets/index-DOdupr_x.js~~ _(removed)_ | 2.02 MB | — | 🟢 -2.02 MB | 🟢 -381 kB | 🟢 -296 kB | | **assets/index-YNCDQp5h.js** _(new)_ | — | 2.02 MB | 🔴 +2.02 MB | 🔴 +381 kB | 🔴 +296 kB | | assets/index-PESgPnbc.js | 507 B | 507 B | ⚪ 0 B | ⚪ 0 B | ⚪ 0 B |Status: 2 added / 2 removed Graph Workspace — 707 kB (baseline 706 kB) • 🔴 +187 B_Graph editor runtime, canvas, workflow orchestration_ | File | Before | After | Δ Raw | Δ Gzip | Δ Brotli | | -------------------------------------------- | ------ | ------ | ---------------------- | ---------------------- | ---------------------- | | **assets/GraphView-B7MA-b5m.js** _(new)_ | — | 707 kB | 🔴 +707 kB | 🔴 +138 kB | 🔴 +107 kB | | ~~assets/GraphView-BtlKFHvX.js~~ _(removed)_ | 706 kB | — | 🟢 -706 kB | 🟢 -138 kB | 🟢 -107 kB |Status: 1 added / 1 removed Views & Navigation — 7.99 kB (baseline 7.99 kB) • ⚪ 0 B_Top-level views, pages, and routed surfaces_ | File | Before | After | Δ Raw | Δ Gzip | Δ Brotli | | ------------------------------------------------- | ------- | ------- | ----------------------- | ----------------------- | ---------------------- | | **assets/UserSelectView-Bhee9Ioo.js** _(new)_ | — | 7.99 kB | 🔴 +7.99 kB | 🔴 +2.39 kB | 🔴 +2.09 kB | | ~~assets/UserSelectView-DjvAHfN5.js~~ _(removed)_ | 7.99 kB | — | 🟢 -7.99 kB | 🟢 -2.39 kB | 🟢 -2.1 kB |Status: 1 added / 1 removed Panels & Settings — 293 kB (baseline 74.8 kB) • 🔴 +219 kB_Configuration panels, inspectors, and settings screens_ | File | Before | After | Δ Raw | Δ Gzip | Δ Brotli | | ---------------------------------------------------- | ------- | ------- | ----------------------- | ----------------------- | ----------------------- | | **assets/settings-DfQ6dSJj.js** _(new)_ | — | 31.6 kB | 🔴 +31.6 kB | 🔴 +7.3 kB | 🔴 +6.12 kB | | **assets/settings-M6_GZccG.js** _(new)_ | — | 26 kB | 🔴 +26 kB | 🔴 +6.23 kB | 🔴 +5.2 kB | | **assets/settings-DJ2QgDzm.js** _(new)_ | — | 25.2 kB | 🔴 +25.2 kB | 🔴 +6.61 kB | 🔴 +5.67 kB | | **assets/settings-CXGVj_nD.js** _(new)_ | — | 24.5 kB | 🔴 +24.5 kB | 🔴 +6.29 kB | 🔴 +5.65 kB | | **assets/settings-G6Dybj1b.js** _(new)_ | — | 24.1 kB | 🔴 +24.1 kB | 🔴 +6.19 kB | 🔴 +5.59 kB | | **assets/settings-DRNLPMG6.js** _(new)_ | — | 23.7 kB | 🔴 +23.7 kB | 🔴 +6.06 kB | 🔴 +5.31 kB | | **assets/settings-CI6OKvJn.js** _(new)_ | — | 22.9 kB | 🔴 +22.9 kB | 🔴 +6.28 kB | 🔴 +5.39 kB | | ~~assets/CreditsPanel-CNqxmfsr.js~~ _(removed)_ | 21.9 kB | — | 🟢 -21.9 kB | 🟢 -5.2 kB | 🟢 -4.53 kB | | **assets/CreditsPanel-DB-Jolhc.js** _(new)_ | — | 21.9 kB | 🔴 +21.9 kB | 🔴 +5.21 kB | 🔴 +4.54 kB | | **assets/settings-B-df0dZe.js** _(new)_ | — | 20.7 kB | 🔴 +20.7 kB | 🔴 +6.21 kB | 🔴 +5.11 kB | | **assets/settings-DVVycxDc.js** _(new)_ | — | 19.9 kB | 🔴 +19.9 kB | 🔴 +5.97 kB | 🔴 +4.78 kB | | ~~assets/KeybindingPanel-B-XQIYLb.js~~ _(removed)_ | 15.1 kB | — | 🟢 -15.1 kB | 🟢 -3.68 kB | 🟢 -3.25 kB | | **assets/KeybindingPanel-Dp16EuvN.js** _(new)_ | — | 15.1 kB | 🔴 +15.1 kB | 🔴 +3.68 kB | 🔴 +3.24 kB | | **assets/ExtensionPanel-BJRiVoXf.js** _(new)_ | — | 11.9 kB | 🔴 +11.9 kB | 🔴 +2.75 kB | 🔴 +2.4 kB | | ~~assets/ExtensionPanel-HQ5RMX7X.js~~ _(removed)_ | 11.9 kB | — | 🟢 -11.9 kB | 🟢 -2.75 kB | 🟢 -2.4 kB | | **assets/AboutPanel-CEZ5HBCP.js** _(new)_ | — | 10.1 kB | 🔴 +10.1 kB | 🔴 +2.58 kB | 🔴 +2.27 kB | | ~~assets/AboutPanel-CLKaxNTg.js~~ _(removed)_ | 10.1 kB | — | 🟢 -10.1 kB | 🟢 -2.58 kB | 🟢 -2.27 kB | | ~~assets/ServerConfigPanel-Bx6_KxjP.js~~ _(removed)_ | 8.04 kB | — | 🟢 -8.04 kB | 🟢 -2.08 kB | 🟢 -1.84 kB | | **assets/ServerConfigPanel-CIsnfGQb.js** _(new)_ | — | 8.04 kB | 🔴 +8.04 kB | 🔴 +2.08 kB | 🔴 +1.83 kB | | ~~assets/UserPanel-BIhpR5Ri.js~~ _(removed)_ | 7.76 kB | — | 🟢 -7.76 kB | 🟢 -1.97 kB | 🟢 -1.72 kB | | **assets/UserPanel-DAiQR0aw.js** _(new)_ | — | 7.76 kB | 🔴 +7.76 kB | 🔴 +1.97 kB | 🔴 +1.72 kB |Status: 15 added / 6 removed UI Components — 11.9 kB (baseline 11.9 kB) • ⚪ 0 B_Reusable component library chunks_ | File | Before | After | Δ Raw | Δ Gzip | Δ Brotli | | ----------------------------------------------------------------- | ------- | ------- | ----------------------- | ----------------------- | ----------------------- | | **assets/ComfyQueueButton-C7TZkaF0.js** _(new)_ | — | 10.7 kB | 🔴 +10.7 kB | 🔴 +2.64 kB | 🔴 +2.33 kB | | ~~assets/ComfyQueueButton-Ca24HJzZ.js~~ _(removed)_ | 10.7 kB | — | 🟢 -10.7 kB | 🟢 -2.64 kB | 🟢 -2.33 kB | | assets/UserAvatar.vue_vue_type_script_setup_true_lang-C9bSkTC5.js | 1.12 kB | 1.12 kB | ⚪ 0 B | ⚪ 0 B | ⚪ 0 B |Status: 1 added / 1 removed Data & Services — 10 kB (baseline 10 kB) • ⚪ 0 B_Stores, services, APIs, and repositories_ | File | Before | After | Δ Raw | Δ Gzip | Δ Brotli | | ---------------------------------------------------- | ------- | ------- | ----------------------- | ----------------------- | ---------------------- | | **assets/keybindingService-_wbZF4Wd.js** _(new)_ | — | 7.21 kB | 🔴 +7.21 kB | 🔴 +1.75 kB | 🔴 +1.5 kB | | ~~assets/keybindingService-DPPz7ASj.js~~ _(removed)_ | 7.21 kB | — | 🟢 -7.21 kB | 🟢 -1.75 kB | 🟢 -1.5 kB | | **assets/serverConfigStore-Bv3vQw3d.js** _(new)_ | — | 2.79 kB | 🔴 +2.79 kB | 🔴 +890 B | 🔴 +776 B | | ~~assets/serverConfigStore-CMadDTUK.js~~ _(removed)_ | 2.79 kB | — | 🟢 -2.79 kB | 🟢 -886 B | 🟢 -773 B |Status: 2 added / 2 removed Utilities & Hooks — 1.07 kB (baseline 1.07 kB) • ⚪ 0 B_Helpers, composables, and utility bundles_ | File | Before | After | Δ Raw | Δ Gzip | Δ Brotli | | --------------------------- | ------- | ------- | ------------------ | ------------------ | ------------------ | | assets/mathUtil-CTARWQ-l.js | 1.07 kB | 1.07 kB | ⚪ 0 B | ⚪ 0 B | ⚪ 0 B |Other — 2.79 MB (baseline 0 B) • 🔴 +2.79 MB_Bundles that do not match a named category_ | File | Before | After | Δ Raw | Δ Gzip | Δ Brotli | | --------------------------------------- | ------ | ------- | --------------------- | --------------------- | --------------------- | | **assets/nodeDefs-DexhCMEi.js** _(new)_ | — | 233 kB | 🔴 +233 kB | 🔴 +32.3 kB | 🔴 +23.5 kB | | **assets/nodeDefs-CDfbduPY.js** _(new)_ | — | 219 kB | 🔴 +219 kB | 🔴 +30.2 kB | 🔴 +22.2 kB | | **assets/nodeDefs-BfT7dJcF.js** _(new)_ | — | 204 kB | 🔴 +204 kB | 🔴 +29.5 kB | 🔴 +21.9 kB | | **assets/nodeDefs-DAwVV156.js** _(new)_ | — | 200 kB | 🔴 +200 kB | 🔴 +29 kB | 🔴 +21.5 kB | | **assets/nodeDefs-CDurg_KW.js** _(new)_ | — | 197 kB | 🔴 +197 kB | 🔴 +28.1 kB | 🔴 +21.5 kB | | **assets/nodeDefs-BePSqkA4.js** _(new)_ | — | 195 kB | 🔴 +195 kB | 🔴 +28.1 kB | 🔴 +21.7 kB | | **assets/nodeDefs-BiAtoiXc.js** _(new)_ | — | 194 kB | 🔴 +194 kB | 🔴 +27.2 kB | 🔴 +21 kB | | **assets/nodeDefs-kTrYLFPK.js** _(new)_ | — | 184 kB | 🔴 +184 kB | 🔴 +28 kB | 🔴 +20.8 kB | | **assets/nodeDefs-CE-vG3RG.js** _(new)_ | — | 182 kB | 🔴 +182 kB | 🔴 +27.9 kB | 🔴 +20.4 kB | | **assets/main-BfHN1fzx.js** _(new)_ | — | 125 kB | 🔴 +125 kB | 🔴 +32.2 kB | 🔴 +26.2 kB | | **assets/main-6UgCUkrV.js** _(new)_ | — | 108 kB | 🔴 +108 kB | 🔴 +28.9 kB | 🔴 +23.9 kB | | **assets/main-CEhf19j2.js** _(new)_ | — | 99.4 kB | 🔴 +99.4 kB | 🔴 +28.5 kB | 🔴 +23.6 kB | | **assets/main-CKz_lTAz.js** _(new)_ | — | 94.3 kB | 🔴 +94.3 kB | 🔴 +27.8 kB | 🔴 +24.1 kB | | **assets/main-BPHe683n.js** _(new)_ | — | 92.4 kB | 🔴 +92.4 kB | 🔴 +27.7 kB | 🔴 +23.1 kB | | **assets/main-C75C4LWt.js** _(new)_ | — | 90.9 kB | 🔴 +90.9 kB | 🔴 +27.2 kB | 🔴 +23.8 kB | | **assets/main-Dzm38Va4.js** _(new)_ | — | 90.3 kB | 🔴 +90.3 kB | 🔴 +27.2 kB | 🔴 +23.4 kB | | **assets/main-CipazGd8.js** _(new)_ | — | 79.3 kB | 🔴 +79.3 kB | 🔴 +27.2 kB | 🔴 +22.5 kB | | **assets/main-BhulUfFD.js** _(new)_ | — | 77.5 kB | 🔴 +77.5 kB | 🔴 +26.4 kB | 🔴 +21.6 kB | | **assets/commands-DGfVUJCR.js** _(new)_ | — | 16.2 kB | 🔴 +16.2 kB | 🔴 +3.16 kB | 🔴 +2.59 kB | | **assets/commands-B2KZRBmX.js** _(new)_ | — | 15.1 kB | 🔴 +15.1 kB | 🔴 +2.89 kB | 🔴 +2.36 kB | | **assets/commands-DwiE551e.js** _(new)_ | — | 14.7 kB | 🔴 +14.7 kB | 🔴 +2.93 kB | 🔴 +2.44 kB | | **assets/commands-dOJNDogK.js** _(new)_ | — | 14.5 kB | 🔴 +14.5 kB | 🔴 +2.73 kB | 🔴 +2.4 kB | | **assets/commands-CuozCW4W.js** _(new)_ | — | 14 kB | 🔴 +14 kB | 🔴 +2.7 kB | 🔴 +2.36 kB | | **assets/commands-Bw-ckyga.js** _(new)_ | — | 13.9 kB | 🔴 +13.9 kB | 🔴 +2.61 kB | 🔴 +2.27 kB | | **assets/commands-C_NmM85I.js** _(new)_ | — | 13.8 kB | 🔴 +13.8 kB | 🔴 +2.83 kB | 🔴 +2.34 kB | | **assets/commands-FXnO1W4Q.js** _(new)_ | — | 13.2 kB | 🔴 +13.2 kB | 🔴 +2.77 kB | 🔴 +2.22 kB | | **assets/commands-Fw7mvqSy.js** _(new)_ | — | 13.1 kB | 🔴 +13.1 kB | 🔴 +2.75 kB | 🔴 +2.15 kB |Status: 27 added |
a57792b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Summary
Technical Details
loadLocale()
function that uses dynamic imports withPromise.all()
for efficient parallel loadingloadedLocales
Set to prevent duplicate loadingsrc/i18n.ts
andapps/desktop-ui/src/i18n.ts
with consistent implementationBundle Size Impact
This change significantly reduces the initial bundle size by removing ~8 languages worth of JSON locale data from the main bundle. Locale files are now loaded on-demand only when users switch languages.
Implementation
import('./locales/[locale]/[file].json')
Test plan
🤖 Generated with Claude Code
┆Issue is synchronized with this Notion page by Unito