build.js 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /**
  2. * Vite 打包配置
  3. */
  4. /**
  5. * 获取打包基础配置
  6. */
  7. export function getBuildBase(isProd) {
  8. return {
  9. target: 'es2015',
  10. outDir: 'dist',
  11. emptyOutDir: true,
  12. sourcemap: isProd ? false : 'inline',
  13. chunkSizeWarningLimit: 1500,
  14. cssCodeSplit: true,
  15. cssMinify: isProd,
  16. assetsInlineLimit: 4096,
  17. reportCompressedSize: false
  18. };
  19. }
  20. /**
  21. * 获取压缩配置
  22. */
  23. export function getTerserOptions(isProd) {
  24. if (!isProd) return undefined;
  25. return {
  26. compress: {
  27. drop_console: true,
  28. drop_debugger: true,
  29. pure_funcs: ['console.log', 'console.info', 'console.debug', 'console.trace'],
  30. passes: 2,
  31. },
  32. format: {
  33. comments: false,
  34. }
  35. };
  36. }
  37. /**
  38. * 获取静态资源文件名配置
  39. */
  40. export function getAssetFileNames(assetInfo) {
  41. const info = assetInfo.name.split('.');
  42. let extType = info[info.length - 1];
  43. if (/\.(png|jpe?g|gif|svg|webp|ico)$/i.test(assetInfo.name)) {
  44. extType = 'img';
  45. } else if (/\.(woff2?|eot|ttf|otf)$/i.test(assetInfo.name)) {
  46. extType = 'fonts';
  47. } else if (/\.css$/i.test(assetInfo.name)) {
  48. extType = 'css';
  49. }
  50. return `${extType}/[name]-[hash].[ext]`;
  51. }
  52. /**
  53. * 手动代码分割策略 - 优化版
  54. */
  55. export function manualChunks(id) {
  56. // 将 node_modules 中的代码分割为不同的 chunk
  57. if (id.includes('node_modules')) {
  58. // 获取包名
  59. const packageName = id.split('node_modules/')[1].split('/')[0].replace('@', '');
  60. // 核心Vue生态库 - 最高优先级,确保基础框架独立
  61. if (id.includes('vue/') && !id.includes('vue-router') && !id.includes('vue-request') && !id.includes('ant-design-vue') && !id.includes('@ant-design')) {
  62. return 'vue-core';
  63. }
  64. if (id.includes('vue-router')) {
  65. return 'vue-router';
  66. }
  67. if (id.includes('pinia')) {
  68. return 'pinia';
  69. }
  70. if (id.includes('@vueuse')) {
  71. return 'vueuse';
  72. }
  73. // Ant Design Vue 统一打包,避免循环依赖
  74. if (id.includes('ant-design-vue')) {
  75. return 'antd-vue';
  76. }
  77. if (id.includes('@ant-design/icons-vue')) {
  78. return 'antd-icons';
  79. }
  80. // 表单设计器
  81. if (id.includes('@form-create/ant-design-vue')) {
  82. return 'form-create-antd';
  83. }
  84. if (id.includes('@form-create/antd-designer')) {
  85. return 'form-designer';
  86. }
  87. if (id.includes('@form-create')) {
  88. return 'form-create-core';
  89. }
  90. // 编辑器相关
  91. if (id.includes('@wangeditor/editor-for-vue')) {
  92. return 'wangeditor-vue';
  93. }
  94. if (id.includes('@wangeditor')) {
  95. return 'wangeditor-core';
  96. }
  97. if (id.includes('highlight.js')) {
  98. return 'highlight';
  99. }
  100. if (id.includes('vue3-highlightjs')) {
  101. return 'vue-highlight';
  102. }
  103. // 图表库
  104. if (id.includes('echarts')) {
  105. if (id.includes('echarts/core')) {
  106. return 'echarts-core';
  107. }
  108. if (id.includes('echarts/charts')) {
  109. return 'echarts-charts';
  110. }
  111. if (id.includes('echarts/components')) {
  112. return 'echarts-components';
  113. }
  114. if (id.includes('echarts/renderers')) {
  115. return 'echarts-renderers';
  116. }
  117. return 'echarts-base';
  118. }
  119. // 工具库
  120. if (id.includes('axios')) {
  121. return 'axios';
  122. }
  123. if (id.includes('dayjs')) {
  124. return 'dayjs';
  125. }
  126. if (id.includes('js-cookie')) {
  127. return 'js-cookie';
  128. }
  129. if (id.includes('nprogress')) {
  130. return 'nprogress';
  131. }
  132. // 其他工具库
  133. if (id.includes('sortablejs')) {
  134. return 'sortable';
  135. }
  136. if (id.includes('file-saver')) {
  137. return 'file-saver';
  138. }
  139. if (id.includes('particles.js')) {
  140. return 'particles';
  141. }
  142. if (id.includes('@vueuse')) {
  143. return 'vueuse';
  144. }
  145. if (id.includes('vue-request')) {
  146. return 'vue-request';
  147. }
  148. // polyfills
  149. if (id.includes('core-js')) {
  150. return 'polyfills';
  151. }
  152. return 'vendor-misc';
  153. }
  154. // 项目内部代码分割 - 优化版
  155. if (id.includes('src/')) {
  156. // 布局和核心组件 - 优先级高,单独打包
  157. if (id.includes('src/layout/')) {
  158. return 'layout';
  159. }
  160. if (id.includes('src/components/layout')) {
  161. return 'components-layout';
  162. }
  163. if (id.includes('src/components/common')) {
  164. return 'components-common';
  165. }
  166. if (id.includes('src/components/')) {
  167. return 'components-other';
  168. }
  169. // 路由相关 - 按模块分割
  170. if (id.includes('src/router/')) {
  171. return 'router';
  172. }
  173. // 状态管理
  174. if (id.includes('src/stores/')) {
  175. return 'stores';
  176. }
  177. // API 按业务模块分割
  178. if (id.includes('src/api/system/')) {
  179. return 'api-system';
  180. }
  181. if (id.includes('src/api/monitor/')) {
  182. return 'api-monitor';
  183. }
  184. if (id.includes('src/api/tool/')) {
  185. return 'api-tool';
  186. }
  187. if (id.includes('src/api/')) {
  188. return 'api-common';
  189. }
  190. // 业务页面按模块分割
  191. if (id.includes('src/views/system/')) {
  192. return 'views-system';
  193. }
  194. if (id.includes('src/views/monitor/')) {
  195. return 'views-monitor';
  196. }
  197. if (id.includes('src/views/tool/')) {
  198. return 'views-tool';
  199. }
  200. if (id.includes('src/views/frontend/')) {
  201. return 'views-frontend';
  202. }
  203. if (id.includes('src/views/')) {
  204. return 'views-common';
  205. }
  206. // 工具和配置
  207. if (id.includes('src/utils/')) {
  208. return 'utils';
  209. }
  210. if (id.includes('src/directive/')) {
  211. return 'directive';
  212. }
  213. if (id.includes('src/config/')) {
  214. return 'config';
  215. }
  216. if (id.includes('src/plugins/')) {
  217. return 'plugins';
  218. }
  219. // 静态资源
  220. if (id.includes('src/assets/')) {
  221. return 'assets';
  222. }
  223. }
  224. }
  225. /**
  226. * 获取完整的打包配置
  227. */
  228. export function getBuildConfig(isProd) {
  229. const baseConfig = getBuildBase(isProd);
  230. return {
  231. ...baseConfig,
  232. minify: isProd ? 'terser' : false,
  233. terserOptions: getTerserOptions(isProd),
  234. rollupOptions: {
  235. output: {
  236. chunkFileNames: 'js/[name]-[hash].js',
  237. entryFileNames: 'js/[name]-[hash].js',
  238. assetFileNames: getAssetFileNames,
  239. manualChunks
  240. },
  241. external: isProd ? [] : [],
  242. },
  243. optimizeDeps: {
  244. include: [
  245. 'vue',
  246. 'vue-router',
  247. 'pinia',
  248. 'dayjs',
  249. 'axios',
  250. 'js-cookie',
  251. 'nprogress'
  252. ],
  253. exclude: [
  254. '@wangeditor/editor',
  255. '@wangeditor/editor-for-vue',
  256. '@form-create/antd-designer',
  257. '@form-create/ant-design-vue',
  258. 'ant-design-vue',
  259. '@ant-design/icons-vue'
  260. ]
  261. }
  262. };
  263. }