webpack.prod.conf.js 5.8 KB

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