perf: reduce main bundle via shared subpath exports#260
Merged
Conversation
- Add subpath exports to @m3w/shared (types, schemas, api-contracts, constants, transformers) - Update 20+ frontend files to use specific subpaths - Remove hash utils from barrel export (import directly when needed) - Lazy load MobileLayout, ReloadPrompt, InstallPrompt - Convert auth-provider from useless dynamic imports to static - Create @/lib/shared.ts as unified re-export layer - Document bundle optimization patterns in development standards - Split Radix UI into ui-core (landing page) and ui-extended (lazy loaded) Results: - Main bundle: 354KB → 293KB (-61KB, -17%) - gzip: 109KB → 91KB (-18KB) - Build warnings: 4 → 0 - Tests: 410 pass
11 tasks
There was a problem hiding this comment.
Pull request overview
This PR successfully reduces the main JavaScript bundle size from 354KB to 293KB (17% reduction, 61KB saved) by implementing subpath exports for the @m3w/shared package and optimizing lazy loading patterns. The optimization prevents heavy dependencies like Zod schemas and AWS crypto libraries from being unnecessarily pulled into the main bundle.
Key Changes:
- Added 5 subpath exports to
@m3w/shared(/types,/schemas,/api-contracts,/constants,/transformers) to enable tree-shaking - Lazy loaded
MobileLayout,ReloadPrompt, andInstallPromptcomponents to remove player store and PWA code from critical path - Removed hash utilities from barrel exports to avoid pulling
@aws-crypto/sha256-browserinto main bundle - Added comprehensive bundle optimization guidelines to development standards
Reviewed changes
Copilot reviewed 29 out of 29 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
shared/tsup.config.ts |
Configured multiple entry points for subpath exports with clear documentation |
shared/package.json |
Defined 5 subpath exports for types, schemas, api-contracts, constants, and transformers |
frontend/vite.config.ts |
Split Radix UI into core and extended chunks, separated audio and utility vendors |
frontend/src/lib/utils/index.ts |
Removed hash utility exports to avoid pulling crypto library into main bundle |
frontend/src/lib/shared.ts |
NEW: Unified re-export layer (currently unused - see comment) |
frontend/src/main.tsx |
Lazy loaded MobileLayout and PWA prompt components to reduce critical path |
frontend/src/components/layouts/mobile-layout.tsx |
Added default export for lazy loading compatibility |
frontend/src/components/providers/auth-provider.tsx |
Converted useless dynamic imports to static imports with cleanup improvements |
frontend/src/stores/*.ts |
Updated 3 store files to use subpath imports for RepeatMode and constants |
frontend/src/pages/*.tsx |
Updated 3 page files to use subpath imports for constants |
frontend/src/lib/offline-proxy/routes/*.ts |
Updated 3 route files to use subpath imports for schemas and transformers |
frontend/src/lib/db/schema.ts |
Updated to use subpath import for RepeatMode type |
frontend/src/lib/cache/response-cache.ts |
Updated to use subpath import for getCacheConfig |
frontend/src/lib/audio/queue.ts |
Updated to use subpath import for RepeatMode type |
frontend/src/lib/api/router.ts |
Updated to use subpath import for isOfflineCapable |
frontend/src/lib/utils/defaults.ts |
Updated to use subpath imports for constants |
frontend/src/services/api/main/resources/player.ts |
Updated to use subpath import for RepeatMode type |
frontend/src/components/features/upload/upload-form/index.tsx |
Updated to use subpath import for isDefaultLibrary |
frontend/src/components/features/playlists/AddToPlaylistSheet.tsx |
Updated to use subpath import for isFavoritesPlaylist |
frontend/src/components/features/player/full-player/PlaybackControls.tsx |
Updated to use subpath import for RepeatMode type |
.github/instructions/development-standards.instructions.md |
Added comprehensive "Bundle Optimization" section with patterns and guidelines |
Core modules now import from unified @/lib/shared layer: - lib/api/router.ts - lib/audio/queue.ts - lib/cache/response-cache.ts - lib/db/schema.ts - lib/utils/defaults.ts - services/api/main/resources/player.ts - stores/libraryStore.ts - stores/playerStore/* - stores/playlistStore.ts Lazy-loaded modules (pages, offline-proxy) continue using direct @m3w/shared subpath imports as documented.
Contributor
|
Coverage after merging perf/bundle-optimization-subpath-exports into main will be
Coverage Report |
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.
Summary
Reduce JavaScript main bundle size from 354KB to 293KB (61KB reduction, 17% smaller) by implementing subpath exports for
@m3w/sharedand fixing barrel export patterns.Closes #261
Part of Epic 4.3 (#219)
Problem
The main bundle was unnecessarily large due to:
@aws-crypto/sha256-browser(~112KB) pulled via@/lib/utils/index.tsbarrel export@m3w/sharedbarrel even when only importing constants/typesSolution
1. Shared Package Subpath Exports
Added 5 subpath exports to
@m3w/shared:@m3w/shared/types- Runtime enums (RepeatMode)@m3w/shared/schemas- Zod schemas (only for lazy-loaded code)@m3w/shared/api-contracts- Route definitions@m3w/shared/constants- Pure functions (isDefaultLibrary, etc.)@m3w/shared/transformers- Data transformers2. Barrel Export Fixes
@/lib/utils/index.ts(import directly when needed)@/lib/shared.tsas unified re-export layer for safe imports3. Lazy Loading Improvements
MobileLayout(removes playerStore from critical path)ReloadPromptandInstallPrompt(only shown on PWA events)ui-core(landing page) andui-extended(lazy loaded)4. Code Cleanup
Results
Files Changed
Shared package:
shared/tsup.config.ts- Multiple entry pointsshared/package.json- Subpath exportsFrontend:
frontend/src/lib/shared.ts- NEW: Unified re-export layerfrontend/src/lib/utils/index.ts- Remove hash exportsfrontend/src/main.tsx- Lazy load MobileLayout, PWA promptsfrontend/src/components/layouts/mobile-layout.tsx- Add default exportfrontend/src/components/providers/auth-provider.tsx- Static importsfrontend/vite.config.ts- Split Radix UI chunksDocumentation:
.github/instructions/development-standards.instructions.md- Bundle optimization guidelinesTesting
Follow-up
The new "Bundle Optimization" section in development standards documents: