vite.config.ts 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import react from '@vitejs/plugin-react';
  2. import { defineConfig, loadEnv } from 'vite';
  3. import removeConsole from 'vite-plugin-remove-console';
  4. import topLevelAwait from 'vite-plugin-top-level-await';
  5. import wasm from 'vite-plugin-wasm';
  6. import legacy from '@vitejs/plugin-legacy';
  7. import { viteBuildInfo } from './build/buildInfo';
  8. import { configCompressPlugin } from './build/compress';
  9. import svgConvert from './build/svgConvert';
  10. import { root, alias, wrapperEnv } from './build/utils';
  11. // https://vitejs.dev/config/
  12. export default defineConfig(({ mode }) => {
  13. const env = wrapperEnv(loadEnv(mode, root));
  14. const isProd = mode === 'production';
  15. return {
  16. base: env.VITE_BUILD_PUBLIC_PATH,
  17. plugins: [
  18. react(),
  19. wasm(),
  20. topLevelAwait(),
  21. legacy({
  22. targets: [
  23. 'chrome >= 87',
  24. 'safari >= 13',
  25. 'firefox >= 78',
  26. 'edge >= 88',
  27. 'not IE 11',
  28. ],
  29. }),
  30. isProd &&
  31. removeConsole({
  32. includes: ['log', 'warn'],
  33. external: ['error'],
  34. }),
  35. svgConvert(),
  36. viteBuildInfo(),
  37. configCompressPlugin(env.VITE_BUILD_COMPRESSION!),
  38. ].filter(Boolean),
  39. resolve: { alias },
  40. optimizeDeps: {
  41. exclude: ['brotli-wasm'],
  42. },
  43. css: {
  44. preprocessorOptions: {
  45. less: {
  46. javascriptEnabled: true,
  47. },
  48. scss: {
  49. additionalData: `@use "@/styles/variables" as *;`,
  50. },
  51. },
  52. },
  53. server: {
  54. port: env.VITE_DEV_PORT,
  55. host: '0.0.0.0',
  56. open: true,
  57. proxy: {
  58. '/dev/api/v1': {
  59. target: env.VITE_DEV_PROXY_TARGET_API_BASE_URL,
  60. changeOrigin: true,
  61. rewrite: (path) => path.replace(/^\/dev\/api\/v1/, ''),
  62. secure: false,
  63. configure: (proxy) => {
  64. proxy.on('error', (err) => {
  65. console.log('proxy error', err);
  66. });
  67. proxy.on('proxyReq', (_, req) => {
  68. console.log(
  69. 'Sending Request to the Target:',
  70. req.method,
  71. req.url,
  72. env.VITE_DEV_PROXY_TARGET_API_BASE_URL
  73. );
  74. });
  75. proxy.on('proxyRes', (proxyRes, req) => {
  76. console.log(
  77. 'Received Response from the Target:',
  78. proxyRes.statusCode,
  79. req.url
  80. );
  81. });
  82. },
  83. },
  84. },
  85. warmup: {
  86. clientFiles: ['./index.html', './src/{pages,components}/*'],
  87. },
  88. },
  89. build: {
  90. outDir: 'dist',
  91. sourcemap: !isProd,
  92. // 为了处理 brotli-wasm 的引用问题,target 已改为使用 plugin-legacy 的 targets 控制
  93. // target: ['es2015', 'chrome87', 'safari13', 'firefox78', 'edge88'],
  94. // 与 plugin-legacy targets 对齐,使 CSS 压缩/转换兼容同一批浏览器(plugin-legacy 不处理 CSS)
  95. cssTarget: ['chrome87', 'safari13', 'firefox78', 'edge88'],
  96. rollupOptions: {
  97. output: {
  98. // 产物文件名:入口/代码块用 [name]-[hash:8].js,静态资源用 [name]-[hash:8][extname]
  99. entryFileNames: 'assets/[name]-[hash].js',
  100. chunkFileNames: 'assets/[name]-[hash].js',
  101. assetFileNames: 'assets/[name]-[hash][extname]',
  102. manualChunks: {
  103. 'react-vendor': ['react', 'react-dom', 'react-router-dom'],
  104. 'antd-vendor': ['antd', '@ant-design/icons'],
  105. 'utils-vendor': ['lodash-es', 'ramda'],
  106. 'i18n-vendor': [
  107. 'i18next',
  108. 'react-i18next',
  109. 'i18next-browser-languagedetector',
  110. ],
  111. },
  112. },
  113. },
  114. chunkSizeWarningLimit: 1500,
  115. },
  116. };
  117. });