人民医院前端

webpack.prod.conf.js 6.1KB

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