vite.config.ts 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import vue from "@vitejs/plugin-vue";
  2. import { type ConfigEnv, type UserConfig, loadEnv, defineConfig } from "vite";
  3. import AutoImport from "unplugin-auto-import/vite";
  4. import Components from "unplugin-vue-components/vite";
  5. import { ElementPlusResolver } from "unplugin-vue-components/resolvers";
  6. import UnoCSS from "unocss/vite";
  7. import { resolve } from "path";
  8. import { name, version, engines, dependencies, devDependencies } from "./package.json";
  9. // 平台的名称、版本、运行所需的 node 版本、依赖、构建时间的类型提示
  10. const __APP_INFO__ = {
  11. pkg: { name, version, engines, dependencies, devDependencies },
  12. buildTimestamp: Date.now(),
  13. };
  14. const pathSrc = resolve(__dirname, "src");
  15. // Vite配置 https://cn.vitejs.dev/config
  16. export default defineConfig(({ mode }: ConfigEnv): UserConfig => {
  17. const env = loadEnv(mode, process.cwd());
  18. const isProduction = mode === "production";
  19. return {
  20. base: "/",
  21. resolve: {
  22. alias: {
  23. "@": pathSrc,
  24. },
  25. },
  26. css: {
  27. preprocessorOptions: {
  28. // 定义全局 SCSS 变量
  29. scss: {
  30. api: "modern-compiler",
  31. additionalData: `@use "@/styles/variables.scss" as *;`,
  32. },
  33. },
  34. },
  35. server: {
  36. host: true,
  37. port: Number(env.VITE_APP_PORT),
  38. open: true,
  39. proxy: {
  40. // 代理 /dev-api 的请求
  41. [env.VITE_APP_BASE_API]: {
  42. target: env.VITE_API_BASE_URL, // 代理目标地址:https://后端地址
  43. secure: false, // 请求是否https
  44. changeOrigin: true, // 是否跨域
  45. // rewrite: (path: string) => path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""),
  46. },
  47. },
  48. },
  49. plugins: [
  50. vue(),
  51. // 生产环境禁用 visualizer(仅用于开发分析)
  52. // visualizer({
  53. // open: true,
  54. // gzipSize: true,
  55. // brotliSize: true,
  56. // }),
  57. UnoCSS(),
  58. // API 自动导入
  59. AutoImport({
  60. // 导入 Vue 函数,如:ref, reactive, toRef 等
  61. imports: ["vue", "@vueuse/core", "pinia", "vue-router", "vue-i18n"],
  62. resolvers: [
  63. // 导入 Element Plus函数,如:ElMessage, ElMessageBox 等
  64. ElementPlusResolver({ importStyle: "sass" }),
  65. ],
  66. eslintrc: {
  67. enabled: false,
  68. filepath: "./.eslintrc-auto-import.json",
  69. globalsPropValue: true,
  70. },
  71. vueTemplate: true,
  72. // 导入函数类型声明文件路径 (false:关闭自动生成)
  73. dts: "src/types/auto-imports.d.ts",
  74. }),
  75. // 组件自动导入
  76. Components({
  77. resolvers: [
  78. // 导入 Element Plus 组件
  79. ElementPlusResolver({ importStyle: "sass" }),
  80. ],
  81. // 指定自定义组件位置(默认:src/components)
  82. dirs: ["src/components", "src/**/components"],
  83. // 导入组件类型声明文件路径 (false:关闭自动生成)
  84. dts: "src/types/components.d.ts",
  85. }),
  86. ],
  87. // 预加载项目必需的组件
  88. optimizeDeps: {
  89. include: [
  90. "vue",
  91. "vue-router",
  92. "element-plus",
  93. "pinia",
  94. "axios",
  95. "@vueuse/core",
  96. "@wangeditor-next/editor-for-vue",
  97. "codemirror-editor-vue3",
  98. "default-passive-events",
  99. "exceljs",
  100. "path-to-regexp",
  101. "echarts",
  102. "vue-i18n",
  103. "nprogress",
  104. "qs",
  105. "path-browserify",
  106. "@element-plus/icons-vue",
  107. ],
  108. },
  109. // 构建配置
  110. build: {
  111. chunkSizeWarningLimit: 4000, // 消除打包大小超过4000kb警告
  112. minify: isProduction ? "terser" : false, // 只在生产环境启用压缩
  113. terserOptions: isProduction
  114. ? {
  115. compress: {
  116. keep_infinity: true, // 防止 Infinity 被压缩成 1/0,这可能会导致 Chrome 上的性能问题
  117. drop_console: true, // 生产环境去除 console.log, console.warn, console.error 等
  118. drop_debugger: true, // 生产环境去除 debugger
  119. pure_funcs: ["console.log", "console.info"], // 移除指定的函数调用
  120. },
  121. format: {
  122. comments: true, // 删除注释
  123. },
  124. }
  125. : {},
  126. rollupOptions: {
  127. output: {
  128. // manualChunks: {
  129. // "vue-i18n": ["vue-i18n"],
  130. // },
  131. experimentalMinChunkSize: 20 * 1024,
  132. manualChunks(id) {
  133. // 1. 排除 .pnpm 目录
  134. if (id.includes(".pnpm/")) {
  135. return undefined;
  136. }
  137. // 2. 大型库单独拆分
  138. if (id.includes("node_modules")) {
  139. if (id.includes("echarts")) {
  140. return "echarts";
  141. }
  142. if (id.includes("element-plus")) {
  143. return "element-plus";
  144. }
  145. if (id.includes("@wangeditor-next")) {
  146. return "wangeditor";
  147. }
  148. if (id.includes("codemirror")) {
  149. return "codemirror";
  150. }
  151. if (id.includes("exceljs")) {
  152. return "exceljs";
  153. }
  154. // 3. 小型依赖合并到 vendor(避免过度拆分)
  155. const module = id.toString().split("node_modules/")[1].split("/")[0];
  156. return module; // 其他包单独拆分
  157. }
  158. },
  159. // 用于从入口点创建的块的打包输出格式[name]表示文件名,[hash]表示该文件内容hash值
  160. entryFileNames: "js/[name].[hash].js",
  161. // 用于命名代码拆分时创建的共享块的输出命名
  162. chunkFileNames: "js/[name].[hash].js",
  163. // 用于输出静态资源的命名,[ext]表示文件扩展名
  164. assetFileNames: (assetInfo: any) => {
  165. const info = assetInfo.name.split(".");
  166. let extType = info[info.length - 1];
  167. // console.log('文件信息', assetInfo.name)
  168. if (/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/i.test(assetInfo.name)) {
  169. extType = "media";
  170. } else if (/\.(png|jpe?g|gif|svg)(\?.*)?$/.test(assetInfo.name)) {
  171. extType = "img";
  172. } else if (/\.(woff2?|eot|ttf|otf)(\?.*)?$/i.test(assetInfo.name)) {
  173. extType = "fonts";
  174. }
  175. return `${extType}/[name].[hash].[ext]`;
  176. },
  177. },
  178. },
  179. },
  180. define: {
  181. __APP_INFO__: JSON.stringify(__APP_INFO__),
  182. },
  183. };
  184. });