vite.config.ts 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. import { defineConfig } from 'vite';
  2. import react from '@vitejs/plugin-react';
  3. import { visualizer } from 'rollup-plugin-visualizer';
  4. // https://vite.dev/config/
  5. export default defineConfig({
  6. plugins: [
  7. react(),
  8. // Bundle 分析工具(通过 ANALYZE=true 环境变量启用)
  9. process.env.ANALYZE === 'true' && visualizer({
  10. open: true,
  11. filename: 'dist/stats.html',
  12. gzipSize: true,
  13. brotliSize: true,
  14. template: 'treemap',
  15. }),
  16. ].filter(Boolean),
  17. build: {
  18. // Enable minification for production builds (Req 13.9)
  19. // Vite 8+ uses oxc by default; 'esbuild' requires a separate install.
  20. // Leaving minify at its default ('oxc' in Vite 8) gives fast, aggressive
  21. // minification out of the box.
  22. // minify: 'esbuild', // uncomment if esbuild is installed separately
  23. // Raise the warning threshold slightly – Ant Design + Slate are large
  24. // but are split into their own vendor chunk below.
  25. chunkSizeWarningLimit: 600,
  26. rollupOptions: {
  27. output: {
  28. /**
  29. * 优化的 Manual chunk splitting 策略
  30. *
  31. * 将 Ant Design 拆分为多个更小的 chunks,提高缓存命中率
  32. * 并独立打包大型文档处理库
  33. */
  34. manualChunks(id: string) {
  35. // ========== React 核心框架 ==========
  36. if (id.includes('node_modules/react') || id.includes('node_modules/react-dom')) {
  37. return 'react-vendor';
  38. }
  39. // ========== Ant Design 细粒度拆分 ==========
  40. // 核心组件(高频使用,首屏必需)
  41. if (
  42. id.includes('node_modules/antd/es/button') ||
  43. id.includes('node_modules/antd/es/input') ||
  44. id.includes('node_modules/antd/es/space') ||
  45. id.includes('node_modules/antd/es/spin') ||
  46. id.includes('node_modules/antd/es/typography') ||
  47. id.includes('node_modules/antd/es/config-provider') ||
  48. id.includes('node_modules/antd/es/alert')
  49. ) {
  50. return 'antd-core';
  51. }
  52. // 表单和反馈组件(中频使用)
  53. if (
  54. id.includes('node_modules/antd/es/message') ||
  55. id.includes('node_modules/antd/es/popconfirm') ||
  56. id.includes('node_modules/antd/es/tooltip') ||
  57. id.includes('node_modules/antd/es/select')
  58. ) {
  59. return 'antd-feedback';
  60. }
  61. // 布局和导航组件(中频使用)
  62. if (
  63. id.includes('node_modules/antd/es/drawer') ||
  64. id.includes('node_modules/antd/es/list') ||
  65. id.includes('node_modules/antd/es/card') ||
  66. id.includes('node_modules/antd/es/divider') ||
  67. id.includes('node_modules/antd/es/empty')
  68. ) {
  69. return 'antd-layout';
  70. }
  71. // 数据展示组件(低频使用,按需加载)
  72. if (
  73. id.includes('node_modules/antd/es/tree') ||
  74. id.includes('node_modules/antd/es/table') ||
  75. id.includes('node_modules/antd/es/dropdown')
  76. ) {
  77. return 'antd-data';
  78. }
  79. // 其他 Ant Design 代码(图标、样式、工具等)
  80. if (id.includes('node_modules/antd') || id.includes('node_modules/@ant-design')) {
  81. return 'antd-vendor';
  82. }
  83. // ========== 文档处理库(按需加载)==========
  84. if (
  85. id.includes('node_modules/mammoth') ||
  86. id.includes('node_modules/docx-preview')
  87. ) {
  88. return 'document-libs';
  89. }
  90. // ========== 导出功能库(按需加载)==========
  91. if (
  92. id.includes('node_modules/jspdf') ||
  93. id.includes('node_modules/html2canvas')
  94. ) {
  95. return 'export-libs';
  96. }
  97. // ========== Markdown 处理库 ==========
  98. if (
  99. id.includes('node_modules/react-markdown') ||
  100. id.includes('node_modules/remark-') ||
  101. id.includes('node_modules/rehype-') ||
  102. id.includes('node_modules/turndown') ||
  103. id.includes('node_modules/unified') ||
  104. id.includes('node_modules/micromark')
  105. ) {
  106. return 'markdown-vendor';
  107. }
  108. // ========== Slate 编辑器 ==========
  109. if (
  110. id.includes('node_modules/slate') ||
  111. id.includes('node_modules/slate-react') ||
  112. id.includes('node_modules/slate-history')
  113. ) {
  114. return 'slate-vendor';
  115. }
  116. // ========== 工具库 ==========
  117. if (
  118. id.includes('node_modules/axios') ||
  119. id.includes('node_modules/zustand') ||
  120. id.includes('node_modules/uuid')
  121. ) {
  122. return 'utils-vendor';
  123. }
  124. // 其他 node_modules
  125. if (id.includes('node_modules')) {
  126. return 'vendor';
  127. }
  128. },
  129. },
  130. // Rollup performs tree-shaking by default when building ES modules.
  131. // These options reinforce that unused exports are dropped (Req 13.9).
  132. treeshake: {
  133. moduleSideEffects: false,
  134. propertyReadSideEffects: false,
  135. },
  136. },
  137. // 启用 CSS 代码分割
  138. cssCodeSplit: true,
  139. // 小于此阈值的资源将内联为 base64
  140. assetsInlineLimit: 4096, // 4KB
  141. },
  142. // 开发服务器配置
  143. server: {
  144. port: 5173,
  145. host: true,
  146. open: false,
  147. },
  148. // 依赖预构建优化
  149. optimizeDeps: {
  150. include: [
  151. 'react',
  152. 'react-dom',
  153. 'axios',
  154. 'zustand',
  155. 'antd',
  156. '@ant-design/icons',
  157. ],
  158. // 排除不需要预构建的大型依赖
  159. exclude: [
  160. 'mammoth',
  161. 'docx-preview',
  162. ],
  163. },
  164. });