vite.config.optimized.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /**
  2. * Vite 优化配置
  3. *
  4. * 这是一个优化后的 vite 配置文件,包含:
  5. * - 更细粒度的 chunk 拆分
  6. * - Bundle 分析工具
  7. * - 图片压缩
  8. *
  9. * 使用方法:
  10. * 1. 备份当前的 vite.config.ts
  11. * 2. 将此文件重命名为 vite.config.ts
  12. * 3. 安装必要依赖: npm install --save-dev rollup-plugin-visualizer
  13. */
  14. import { defineConfig } from 'vite';
  15. import react from '@vitejs/plugin-react';
  16. import { visualizer } from 'rollup-plugin-visualizer';
  17. // https://vite.dev/config/
  18. export default defineConfig({
  19. plugins: [
  20. react(),
  21. // Bundle 分析工具(仅在需要时启用)
  22. // 运行 npm run build 后会生成 dist/stats.html
  23. process.env.ANALYZE === 'true' && visualizer({
  24. open: true,
  25. filename: 'dist/stats.html',
  26. gzipSize: true,
  27. brotliSize: true,
  28. template: 'treemap', // 'sunburst' | 'treemap' | 'network'
  29. }),
  30. ].filter(Boolean),
  31. build: {
  32. // 使用 Vite 8 默认的 oxc 压缩器(最快)
  33. // 如果需要更高压缩率,可以改为 'esbuild' 或 'terser'
  34. // minify: 'esbuild',
  35. // 提高 chunk 大小警告阈值(Ant Design 较大)
  36. chunkSizeWarningLimit: 600,
  37. rollupOptions: {
  38. output: {
  39. /**
  40. * 优化的手动 chunk 拆分策略
  41. *
  42. * 目标:
  43. * 1. 将不同功能的库拆分到独立 chunk
  44. * 2. 提高浏览器缓存命中率
  45. * 3. 减少首次加载体积
  46. */
  47. manualChunks(id: string) {
  48. // ========== 核心框架 ==========
  49. if (id.includes('node_modules/react') || id.includes('node_modules/react-dom')) {
  50. return 'react-vendor';
  51. }
  52. // ========== UI 组件库 ==========
  53. // Ant Design 核心组件(高频使用)
  54. if (
  55. id.includes('node_modules/antd/es/button') ||
  56. id.includes('node_modules/antd/es/input') ||
  57. id.includes('node_modules/antd/es/form') ||
  58. id.includes('node_modules/antd/es/space') ||
  59. id.includes('node_modules/antd/es/card') ||
  60. id.includes('node_modules/antd/es/spin')
  61. ) {
  62. return 'antd-core';
  63. }
  64. // Ant Design 扩展组件(低频使用)
  65. if (
  66. id.includes('node_modules/antd/es/table') ||
  67. id.includes('node_modules/antd/es/drawer') ||
  68. id.includes('node_modules/antd/es/modal') ||
  69. id.includes('node_modules/antd/es/dropdown') ||
  70. id.includes('node_modules/antd/es/menu')
  71. ) {
  72. return 'antd-extended';
  73. }
  74. // 其他 Ant Design 代码和图标
  75. if (id.includes('node_modules/antd') || id.includes('node_modules/@ant-design')) {
  76. return 'antd-vendor';
  77. }
  78. // ========== 文档处理库(按需加载)==========
  79. // Word 文档解析(mammoth, docx-preview)
  80. if (
  81. id.includes('node_modules/mammoth') ||
  82. id.includes('node_modules/docx-preview')
  83. ) {
  84. return 'document-libs-vendor';
  85. }
  86. // ========== 导出功能库(按需加载)==========
  87. // PDF 和截图(jspdf, html2canvas)
  88. if (
  89. id.includes('node_modules/jspdf') ||
  90. id.includes('node_modules/html2canvas')
  91. ) {
  92. return 'export-libs-vendor';
  93. }
  94. // HTML 转 Markdown(turndown)
  95. if (id.includes('node_modules/turndown')) {
  96. return 'markdown-converter-vendor';
  97. }
  98. // ========== Markdown 渲染库 ==========
  99. // react-markdown 及其依赖
  100. if (
  101. id.includes('node_modules/react-markdown') ||
  102. id.includes('node_modules/remark-') ||
  103. id.includes('node_modules/rehype-') ||
  104. id.includes('node_modules/unified') ||
  105. id.includes('node_modules/micromark')
  106. ) {
  107. return 'markdown-vendor';
  108. }
  109. // ========== 编辑器相关 ==========
  110. // Slate.js 富文本编辑器(如果使用)
  111. if (
  112. id.includes('node_modules/slate') ||
  113. id.includes('node_modules/slate-react') ||
  114. id.includes('node_modules/slate-history')
  115. ) {
  116. return 'slate-vendor';
  117. }
  118. // ========== 工具库 ==========
  119. // HTTP 客户端
  120. if (id.includes('node_modules/axios')) {
  121. return 'axios-vendor';
  122. }
  123. // 状态管理
  124. if (id.includes('node_modules/zustand')) {
  125. return 'zustand-vendor';
  126. }
  127. // 其他小型工具库
  128. if (
  129. id.includes('node_modules/uuid') ||
  130. id.includes('node_modules/dayjs') ||
  131. id.includes('node_modules/lodash')
  132. ) {
  133. return 'utils-vendor';
  134. }
  135. // ========== 其他第三方库 ==========
  136. if (id.includes('node_modules')) {
  137. return 'vendor';
  138. }
  139. // 应用代码(由 React.lazy 自动分割)
  140. // 不需要在这里处理
  141. },
  142. },
  143. // Tree-shaking 配置(移除未使用的代码)
  144. treeshake: {
  145. moduleSideEffects: false,
  146. propertyReadSideEffects: false,
  147. },
  148. },
  149. // 启用 CSS 代码分割
  150. cssCodeSplit: true,
  151. // 启用源码映射(方便调试,生产环境可关闭)
  152. sourcemap: process.env.NODE_ENV !== 'production',
  153. // 产物输出目录
  154. outDir: 'dist',
  155. // 静态资源处理
  156. assetsDir: 'assets',
  157. // 小于此阈值的资源将内联为 base64
  158. assetsInlineLimit: 4096, // 4KB
  159. },
  160. // 开发服务器配置
  161. server: {
  162. port: 5173,
  163. host: true, // 监听所有地址
  164. open: false, // 不自动打开浏览器
  165. // 预加载优化
  166. warmup: {
  167. clientFiles: [
  168. './src/App.tsx',
  169. './src/components/ChatPanel/ChatPanel.tsx',
  170. './src/components/EditorPanel/EditorPanel.tsx',
  171. ],
  172. },
  173. },
  174. // 依赖预构建优化
  175. optimizeDeps: {
  176. include: [
  177. 'react',
  178. 'react-dom',
  179. 'axios',
  180. 'zustand',
  181. 'antd',
  182. '@ant-design/icons',
  183. ],
  184. // 排除不需要预构建的大型依赖
  185. exclude: [
  186. 'mammoth',
  187. 'docx-preview',
  188. 'jspdf',
  189. 'html2canvas',
  190. ],
  191. },
  192. });