vue.config.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. const timeStamp = new Date().getTime()
  2. module.exports = {
  3. publicPath: process.env.NODE_ENV === 'production' ? '/dashboard/' : '/',
  4. // 配置入口文件支持TypeScript
  5. pages: {
  6. index: {
  7. entry: 'src/main.ts',
  8. template: 'public/index.html',
  9. filename: 'index.html'
  10. }
  11. },
  12. devServer: {
  13. port: 8868,
  14. },
  15. pluginOptions: {
  16. quasar: {
  17. importStrategy: 'kebab',
  18. rtlSupport: false
  19. }
  20. },
  21. transpileDependencies: [
  22. 'quasar',
  23. 'resize-detector',
  24. '@kangc'
  25. ],
  26. // 项目打包文件夹
  27. outputDir: '../src/Masuit.MyBlogs.Core/wwwroot/dashboard',
  28. // 静态资源文件夹 *注:当生成的资源覆写 filename 或 chunkFilename 时,assetsDir 会被忽略。
  29. // assetsDir: 'static',
  30. // 关闭 sourcemap
  31. productionSourceMap: false,
  32. // 打包的时候不使用 hash 值
  33. filenameHashing: false,
  34. // Webpack 函数式配置
  35. configureWebpack: config => {
  36. // TypeScript 支持
  37. config.resolve.extensions.push('.ts')
  38. // 体积分析
  39. if (process.env.use_analyzer) {
  40. const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
  41. config.plugins.push(new BundleAnalyzerPlugin())
  42. }
  43. // 生产环境配置
  44. if (process.env.NODE_ENV === 'production') {
  45. // 优化配置但禁用CSS压缩器
  46. config.optimization = config.optimization || {}
  47. // 临时禁用CSS压缩以避免构建错误
  48. config.optimization.minimizer = config.optimization.minimizer || []
  49. config.optimization.minimizer = config.optimization.minimizer.filter(plugin =>
  50. !plugin.constructor.name.includes('CssMinimizerPlugin')
  51. )
  52. // 优化代码分割
  53. config.optimization.splitChunks = {
  54. chunks: 'all',
  55. cacheGroups: {
  56. // Vue核心库单独打包
  57. vue: {
  58. name: 'chunk-vue',
  59. priority: 20,
  60. test: /[\\/]node_modules[\\/](vue|vue-router|pinia)[\\/]/
  61. },
  62. // UI框架单独打包
  63. quasar: {
  64. name: 'chunk-quasar',
  65. priority: 15,
  66. test: /[\\/]node_modules[\\/]quasar[\\/]/
  67. },
  68. // 大型图表库单独打包
  69. echarts: {
  70. name: 'chunk-echarts',
  71. priority: 15,
  72. test: /[\\/]node_modules[\\/](echarts|vue-echarts)[\\/]/
  73. },
  74. // 其他第三方库
  75. vendor: {
  76. name: 'chunk-vendors',
  77. priority: 10,
  78. test: /[\\/]node_modules[\\/]/,
  79. minChunks: 1
  80. },
  81. // 公共组件
  82. common: {
  83. name: 'chunk-common',
  84. priority: 5,
  85. minChunks: 2,
  86. reuseExistingChunk: true
  87. }
  88. }
  89. }
  90. // 配置 Terser 插件移除 console
  91. if (config.optimization && config.optimization.minimizer && config.optimization.minimizer[0]) {
  92. const terserPlugin = config.optimization.minimizer[0]
  93. if (terserPlugin.options && terserPlugin.options.terserOptions && terserPlugin.options.terserOptions.compress) {
  94. terserPlugin.options.terserOptions.compress.drop_console = true
  95. terserPlugin.options.terserOptions.compress.drop_debugger = true
  96. }
  97. }
  98. // Gzip 压缩
  99. const CompressionPlugin = require('compression-webpack-plugin')
  100. config.plugins.push(
  101. new CompressionPlugin({
  102. algorithm: 'gzip',
  103. test: /\.(js|css|woff|woff2|svg)$/, // 匹配文件名
  104. threshold: 10240, // 对超过10k的数据压缩
  105. deleteOriginalAssets: false, // 不删除源文件
  106. minRatio: 0.8 // 压缩比
  107. })
  108. )
  109. // 将 js 文件夹添加时间戳,这样浏览器不会加载上个版本缓存的代码
  110. config.output.filename = `js/[name].${timeStamp}.js`
  111. config.output.chunkFilename = `js/[name].${timeStamp}.js`
  112. } else {
  113. // 开发环境配置
  114. }
  115. },
  116. chainWebpack: config => {
  117. // 移除 prefetch 插件减少不必要的预加载
  118. config.plugins.delete('prefetch')
  119. config.plugins.delete('preload')
  120. // 优先处理 .d.ts 文件 - 使用 null-loader 忽略它们
  121. config.module
  122. .rule('ignore-d-ts')
  123. .test(/\.d\.ts$/)
  124. .use('null-loader')
  125. .loader('null-loader')
  126. .end()
  127. // TypeScript 配置
  128. config.module
  129. .rule('typescript')
  130. .test(/\.ts$/)
  131. .exclude
  132. .add(/node_modules/)
  133. .add(/\.d\.ts$/)
  134. .end()
  135. .use('ts-loader')
  136. .loader('ts-loader')
  137. .options({
  138. appendTsSuffixTo: [/\.vue$/],
  139. transpileOnly: true
  140. })
  141. .end()
  142. // 生产环境配置CDN外部依赖
  143. if (process.env.NODE_ENV === 'production') {
  144. config.externals({
  145. // 'vue': 'Vue',
  146. // 'vue-router': 'VueRouter',
  147. // 'axios': 'axios',
  148. // 'echarts': 'echarts'
  149. // 注释掉CDN配置,先测试其他优化效果
  150. })
  151. }
  152. },
  153. css: {
  154. // 生产环境CSS优化
  155. sourceMap: false,
  156. extract: process.env.NODE_ENV === 'production'
  157. ? {
  158. // 合并CSS文件减少文件数量
  159. filename: `css/[name].${timeStamp}.css`,
  160. chunkFilename: `css/[name].${timeStamp}.css`,
  161. ignoreOrder: true // 忽略CSS顺序警告
  162. }
  163. : false
  164. }
  165. }