vite.config.ts 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. import { execSync } from 'node:child_process'
  2. import { defineConfig, loadEnv } from 'vite'
  3. import vue from '@vitejs/plugin-vue'
  4. import path from 'path'
  5. import { createAppBuildMeta, readGitShort, writeVersionJson } from './scripts/app-build-meta'
  6. import { fileURLToPath } from 'url'
  7. import vueDevTools from 'vite-plugin-vue-devtools'
  8. import viteCompression from 'vite-plugin-compression'
  9. import Components from 'unplugin-vue-components/vite'
  10. import AutoImport from 'unplugin-auto-import/vite'
  11. import ElementPlus from 'unplugin-element-plus/vite'
  12. import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
  13. import { VantResolver } from '@vant/auto-import-resolver'
  14. import tailwindcss from '@tailwindcss/vite'
  15. // import { visualizer } from 'rollup-plugin-visualizer'
  16. export default ({ mode }: { mode: string }) => {
  17. const root = process.cwd()
  18. const env = loadEnv(mode, root)
  19. const { VITE_VERSION, VITE_PORT, VITE_BASE_URL, VITE_API_URL, VITE_API_PROXY_URL } = env
  20. const gitShort = readGitShort(() =>
  21. execSync('git rev-parse --short HEAD', {
  22. stdio: ['ignore', 'pipe', 'ignore']
  23. }).toString()
  24. )
  25. const appBuildMeta = createAppBuildMeta(VITE_VERSION || '', Date.now(), gitShort)
  26. console.log(`🚀 API_URL = ${VITE_API_URL}`)
  27. console.log(`🚀 VERSION = ${VITE_VERSION}`)
  28. return defineConfig({
  29. define: {
  30. __APP_VERSION__: JSON.stringify(VITE_VERSION),
  31. __APP_BUILD_ID__: JSON.stringify(appBuildMeta.buildId),
  32. global: 'globalThis'
  33. },
  34. base: VITE_BASE_URL,
  35. server: {
  36. port: Number(VITE_PORT),
  37. proxy: {
  38. '/api': {
  39. target: VITE_API_PROXY_URL,
  40. changeOrigin: true
  41. },
  42. // Web端接口代理 - 转发到后端 /api 前缀
  43. '/web': {
  44. target: 'http://192.168.2.178:8000/api',
  45. changeOrigin: true,
  46. rewrite: (path) => `/api${path}`
  47. },
  48. // 小程序端接口代理
  49. '/mini': {
  50. target: 'http://192.168.2.178:8000/api',
  51. changeOrigin: true,
  52. rewrite: (path) => `/api${path}`
  53. }
  54. },
  55. host: true
  56. },
  57. // 路径别名
  58. resolve: {
  59. alias: {
  60. '@': fileURLToPath(new URL('./src', import.meta.url)),
  61. '@views': resolvePath('src/views'),
  62. '@imgs': resolvePath('src/assets/images'),
  63. '@icons': resolvePath('src/assets/icons'),
  64. '@utils': resolvePath('src/utils'),
  65. '@stores': resolvePath('src/store'),
  66. '@styles': resolvePath('src/assets/styles'),
  67. // 合同 Word 导出:强制 browser 构建,避免 Vite 落到 Node ESM
  68. '@turbodocx/html-to-docx': resolvePath(
  69. 'node_modules/@turbodocx/html-to-docx/dist/html-to-docx.browser.esm.js'
  70. ),
  71. buffer: 'buffer/'
  72. }
  73. },
  74. build: {
  75. target: 'es2015',
  76. outDir: 'dist',
  77. chunkSizeWarningLimit: 2000,
  78. // 关闭构建末尾 gzip 体积统计,避免大项目在该阶段 OOM
  79. reportCompressedSize: false,
  80. minify: 'terser',
  81. terserOptions: {
  82. compress: {
  83. // 生产环境去除 console
  84. drop_console: true,
  85. // 生产环境去除 debugger
  86. drop_debugger: true
  87. }
  88. },
  89. dynamicImportVarsOptions: {
  90. warnOnError: true,
  91. exclude: [],
  92. include: ['src/views/**/*.vue']
  93. }
  94. },
  95. plugins: [
  96. {
  97. name: 'emit-version-json',
  98. apply: 'build',
  99. closeBundle() {
  100. writeVersionJson(path.resolve(root, 'dist'), appBuildMeta)
  101. }
  102. },
  103. vue(),
  104. tailwindcss(),
  105. // 自动按需导入 API
  106. AutoImport({
  107. imports: ['vue', 'vue-router', 'pinia', '@vueuse/core'],
  108. dts: 'src/types/import/auto-imports.d.ts',
  109. resolvers: [ElementPlusResolver()],
  110. eslintrc: {
  111. enabled: true,
  112. filepath: './.auto-import.json',
  113. globalsPropValue: true
  114. }
  115. }),
  116. // 自动按需导入组件
  117. Components({
  118. dts: 'src/types/import/components.d.ts',
  119. resolvers: [
  120. (componentName) => {
  121. if (componentName === 'ElTag') {
  122. return { name: 'default', from: '@/utils/patch-el-tag-empty' }
  123. }
  124. },
  125. ElementPlusResolver(),
  126. VantResolver()
  127. ]
  128. }),
  129. // 按需定制主题配置
  130. ElementPlus({
  131. useSource: true
  132. }),
  133. // 压缩
  134. viteCompression({
  135. verbose: false, // 是否在控制台输出压缩结果
  136. disable: false, // 是否禁用
  137. algorithm: 'gzip', // 压缩算法
  138. ext: '.gz', // 压缩后的文件名后缀
  139. threshold: 10240, // 只有大小大于该值的资源会被处理 10240B = 10KB
  140. deleteOriginFile: false // 压缩后是否删除原文件
  141. }),
  142. vueDevTools()
  143. // 打包分析
  144. // visualizer({
  145. // open: true,
  146. // gzipSize: true,
  147. // brotliSize: true,
  148. // filename: 'dist/stats.html' // 分析图生成的文件名及路径
  149. // }),
  150. ],
  151. // 依赖预构建:避免运行时重复请求与转换,提升首次加载速度
  152. optimizeDeps: {
  153. include: [
  154. 'echarts/core',
  155. 'echarts/charts',
  156. 'echarts/components',
  157. 'echarts/renderers',
  158. 'xlsx',
  159. 'xgplayer',
  160. 'crypto-js',
  161. 'file-saver',
  162. 'buffer',
  163. 'vue-img-cutter',
  164. 'element-plus/es',
  165. 'element-plus/es/components/*/style/css',
  166. 'element-plus/es/components/*/style/index'
  167. ]
  168. },
  169. css: {
  170. preprocessorOptions: {
  171. // sass variable and mixin
  172. scss: {
  173. additionalData: `
  174. @use "@styles/core/el-light.scss" as *;
  175. @use "@styles/core/mixin.scss" as *;
  176. `
  177. }
  178. },
  179. postcss: {
  180. plugins: [
  181. {
  182. postcssPlugin: 'internal:charset-removal',
  183. AtRule: {
  184. charset: (atRule) => {
  185. if (atRule.name === 'charset') {
  186. atRule.remove()
  187. }
  188. }
  189. }
  190. }
  191. ]
  192. }
  193. }
  194. })
  195. }
  196. function resolvePath(paths: string) {
  197. return path.resolve(__dirname, paths)
  198. }