webpack.prod.conf.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. 'use strict'
  2. const path = require('path')
  3. const utils = require('./utils')
  4. const webpack = require('webpack')
  5. const config = require('../config')
  6. const merge = require('webpack-merge')
  7. const baseWebpackConfig = require('./webpack.base.conf')
  8. const CopyWebpackPlugin = require('copy-webpack-plugin')
  9. const HtmlWebpackPlugin = require('html-webpack-plugin')
  10. const ScriptExtHtmlWebpackPlugin = require('script-ext-html-webpack-plugin')
  11. const MiniCssExtractPlugin = require('mini-css-extract-plugin')
  12. const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin')
  13. const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
  14. function resolve(dir) {
  15. return path.join(__dirname, '..', dir)
  16. }
  17. const env = process.env.NODE_ENV === 'uat'
  18. ? require('../config/uat.env')
  19. : require('../config/prod.env')
  20. // For NamedChunksPlugin
  21. const seen = new Set()
  22. const nameLength = 4
  23. const webpackConfig = merge(baseWebpackConfig, {
  24. mode: 'production',
  25. module: {
  26. rules: utils.styleLoaders({
  27. sourceMap: config.build.productionSourceMap,
  28. extract: true,
  29. usePostCSS: true
  30. })
  31. },
  32. devtool: config.build.productionSourceMap ? config.build.devtool : false,
  33. output: {
  34. path: config.build.assetsRoot,
  35. filename: utils.assetsPath('js/[name].[chunkhash:8].js'),
  36. chunkFilename: utils.assetsPath('js/[name].[chunkhash:8].js')
  37. },
  38. plugins: [
  39. // http://vuejs.github.io/vue-loader/en/workflow/production.html
  40. new webpack.DefinePlugin({
  41. 'process.env': env
  42. }),
  43. // extract css into its own file
  44. new MiniCssExtractPlugin({
  45. filename: utils.assetsPath('css/[name].[contenthash:8].css'),
  46. chunkFilename: utils.assetsPath('css/[name].[contenthash:8].css')
  47. }),
  48. // generate dist index.html with correct asset hash for caching.
  49. // you can customize output by editing /index.html
  50. // see https://github.com/ampedandwired/html-webpack-plugin
  51. new HtmlWebpackPlugin({
  52. filename: config.build.index,
  53. template: 'index.html',
  54. inject: true,
  55. favicon: resolve('favicon.ico'),
  56. title: 'waimai-manage',
  57. templateParameters: {
  58. BASE_URL: config.build.assetsPublicPath + config.build.assetsSubDirectory,
  59. },
  60. minify: {
  61. removeComments: true,
  62. collapseWhitespace: true,
  63. removeAttributeQuotes: true
  64. // more options:
  65. // https://github.com/kangax/html-minifier#options-quick-reference
  66. }
  67. // default sort mode uses toposort which cannot handle cyclic deps
  68. // in certain cases, and in webpack 4, chunk order in HTML doesn't
  69. // matter anyway
  70. }),
  71. new ScriptExtHtmlWebpackPlugin({
  72. //`runtime` must same as runtimeChunk name. default is `runtime`
  73. inline: /runtime\..*\.js$/
  74. }),
  75. // keep chunk.id stable when chunk has no name
  76. new webpack.NamedChunksPlugin(chunk => {
  77. if (chunk.name) {
  78. return chunk.name
  79. }
  80. const modules = Array.from(chunk.modulesIterable)
  81. if (modules.length > 1) {
  82. const hash = require('hash-sum')
  83. const joinedHash = hash(modules.map(m => m.id).join('_'))
  84. let len = nameLength
  85. while (seen.has(joinedHash.substr(0, len))) len++
  86. seen.add(joinedHash.substr(0, len))
  87. return `chunk-${joinedHash.substr(0, len)}`
  88. } else {
  89. return modules[0].id
  90. }
  91. }),
  92. // keep module.id stable when vender modules does not change
  93. new webpack.HashedModuleIdsPlugin(),
  94. // copy custom static assets
  95. new CopyWebpackPlugin([
  96. {
  97. from: path.resolve(__dirname, '../static'),
  98. to: config.build.assetsSubDirectory,
  99. ignore: ['.*']
  100. }
  101. ])
  102. ],
  103. optimization: {
  104. splitChunks: {
  105. chunks: 'all',
  106. cacheGroups: {
  107. libs: {
  108. name: 'chunk-libs',
  109. test: /[\\/]node_modules[\\/]/,
  110. priority: 10,
  111. chunks: 'initial' // 只打包初始时依赖的第三方
  112. },
  113. elementUI: {
  114. name: 'chunk-elementUI', // 单独将 elementUI 拆包
  115. priority: 20, // 权重要大于 libs 和 app 不然会被打包进 libs 或者 app
  116. test: /[\\/]node_modules[\\/]element-ui[\\/]/
  117. }
  118. }
  119. },
  120. runtimeChunk: 'single',
  121. minimizer: [
  122. new UglifyJsPlugin({
  123. uglifyOptions: {
  124. mangle: {
  125. safari10: true
  126. }
  127. },
  128. sourceMap: config.build.productionSourceMap,
  129. cache: true,
  130. parallel: true
  131. }),
  132. // Compress extracted CSS. We are using this plugin so that possible
  133. // duplicated CSS from different components can be deduped.
  134. new OptimizeCSSAssetsPlugin()
  135. ]
  136. }
  137. })
  138. if (config.build.productionGzip) {
  139. const CompressionWebpackPlugin = require('compression-webpack-plugin')
  140. webpackConfig.plugins.push(
  141. new CompressionWebpackPlugin({
  142. asset: '[path].gz[query]',
  143. algorithm: 'gzip',
  144. test: new RegExp(
  145. '\\.(' + config.build.productionGzipExtensions.join('|') + ')$'
  146. ),
  147. threshold: 10240,
  148. minRatio: 0.8
  149. })
  150. )
  151. }
  152. if (config.build.generateAnalyzerReport || config.build.bundleAnalyzerReport) {
  153. const BundleAnalyzerPlugin = require('webpack-bundle-analyzer')
  154. .BundleAnalyzerPlugin
  155. if (config.build.bundleAnalyzerReport) {
  156. webpackConfig.plugins.push(
  157. new BundleAnalyzerPlugin({
  158. analyzerPort: 8080,
  159. generateStatsFile: false
  160. })
  161. )
  162. }
  163. if (config.build.generateAnalyzerReport) {
  164. webpackConfig.plugins.push(
  165. new BundleAnalyzerPlugin({
  166. analyzerMode: 'static',
  167. reportFilename: 'bundle-report.html',
  168. openAnalyzer: false
  169. })
  170. )
  171. }
  172. }
  173. module.exports = webpackConfig