diff --git a/apps/desktop/vite.config.ts b/apps/desktop/vite.config.ts index 4a58133b8bfb..c291d6d9718b 100644 --- a/apps/desktop/vite.config.ts +++ b/apps/desktop/vite.config.ts @@ -53,16 +53,46 @@ export default defineConfig(({ command }) => ({ postcss: { plugins: [] } }, build: { - // Keep desktop packaging stable: Shiki ships many dynamic chunks by - // default, and electron-builder can OOM scanning thousands of files. - // Collapsing to a single chunk is intentional, so the renderer bundle is - // large by design (~22 MB). Raise the warning ceiling above that so the - // cosmetic "chunk larger than 500 kB" nag stays quiet, while still acting - // as a regression alarm if the bundle balloons well past today's size. + // The renderer intentionally ships FEW chunks (not one, not thousands): + // · `codeSplitting: false` (the old setup) inlines every `lazy()` / + // dynamic import into the entry, so heavyweight lazy-only deps + // (mermaid, shiki grammars, katex) are parsed + evaluated on every + // cold start even though nothing rendered them. By the time the + // bundle hit ~28 MB that eval was ~1s of launch on an M-series. + // · Default splitting emits a chunk per shiki grammar/theme — thousands + // of files, which electron-builder OOMs scanning (#38888). + // `advancedChunks` is the middle ground: heavyweight libraries merge into + // a handful of named vendor chunks loaded on first use, app-level dynamic + // imports stay lazy, and the file count stays in the tens. chunkSizeWarningLimit: 25000, rolldownOptions: { output: { - codeSplitting: false + advancedChunks: { + groups: [ + // Shared foundations FIRST (first match wins): an unmatched + // module shared by the entry and a heavy chunk gets merged INTO + // the heavy chunk, and the entry then statically imports 19 MB of + // shiki just to reach react/hast utils — putting the heavy chunk + // right back on the boot path. + { name: 'vendor-react', test: /node_modules[\\/](react|react-dom|scheduler)[\\/]/ }, + { + name: 'vendor-md', + test: /node_modules[\\/](property-information|hast-util-[^\\/]+|mdast-util-[^\\/]+|micromark[^\\/]*|unist-util-[^\\/]+|vfile[^\\/]*|unified|stringify-entities|space-separated-tokens|comma-separated-tokens|zwitch|html-void-elements|devlop|style-to-js|style-to-object|clsx)[\\/]/ + }, + // Shared utility packages the entry ALSO uses — kept out of the + // heavy groups for the same boot-path reason. + { + name: 'vendor-util', + test: /node_modules[\\/](lodash-es|es-toolkit|uuid|dayjs|d3-array|d3-color|d3-force|d3-interpolate|d3-time[^\\/]*|dompurify|stylis)[\\/]/ + }, + // One chunk per heavyweight, lazy-only library family. + // @streamdown/code lives WITH shiki because it statically imports + // the full shiki bundle. + { name: 'mermaid', test: /node_modules[\\/](mermaid|cytoscape|dagre|khroma|elkjs|d3|d3-[^\\/]+|@mermaid-js)[\\/]/ }, + { name: 'shiki', test: /node_modules[\\/](shiki|@shikijs|react-shiki|@streamdown[\\/]code|oniguruma-to-es|oniguruma-parser|regex(-[^\\/]+)?)[\\/]/ }, + { name: 'katex', test: /node_modules[\\/]katex[\\/]/ } + ] + } } } },