1 // 此文件是生產環境下webpack相關配置 2 'use strict' 3 const path = require('path') 4 const utils = require('./utils') 5 const webpack = require('webpack') 6 const config = require('../config') // 引入全局配置 7 const merge = require('webpack-merge') // webpack-merge插件提供合並功能,將多個對象合並創建一個新對象。 8 const baseWebpackConfig = require('./webpack.base.conf') 9 const CopyWebpackPlugin = require('copy-webpack-plugin') // 用來復制 10 const HtmlWebpackPlugin = require('html-webpack-plugin') // 自動生成html文件 11 // const ExtractTextPlugin = require('extract-text-webpack-plugin') // 用來抽離css 防止css打包壓縮到js中 12 const MiniCssExtractPlugin = require('mini-css-extract-plugin') //將css單獨打包成一個文件的插件,它為每個包含css的js文件都創建一個css文件 13 const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') // 用來壓縮單獨的css文件 14 const UglifyJsPlugin = require('uglifyjs-webpack-plugin') //用來壓縮 15 16 //導入prod.env.js 用來區分是生產環境 17 const env = process.env.NODE_ENV === 'testing' ? 18 require('../config/test.env') : 19 require('../config/prod.env') 20 21 // 合並 22 const webpackConfig = merge(baseWebpackConfig, { 23 mode: 'production', 24 module: { 25 // 配置獨立的css文件的解析規則 26 rules: utils.styleLoaders({ 27 sourceMap: config.build.productionSourceMap, 28 // 生成獨立的文件 29 extract: true, 30 usePostCSS: true 31 }) 32 }, 33 // 開發工具 用來調試 34 devtool: config.build.productionSourceMap ? config.build.devtool : false, 35 // 輸出 36 output: { 37 // 打包后的文件放在dist目錄下面 38 path: config.build.assetsRoot, 39 // 編譯生成的js文件存放在根目錄下的js目錄下,如果js文件夾不存在就自動創建 40 filename: utils.assetsPath('js/[name].[chunkhash].js'), 41 // 用來打包require.ensure方法中引入的模塊,如果該方法中沒有引入任何模塊,就不會生成chunk文件 42 chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 43 }, 44 // 優化 (https://webpack.docschina.org/configuration/optimization/) 45 optimization: { 46 moduleIds: 'hashed', // 告知 webpack 當選擇模塊 id 時需要使用哪種算法 ( 'hashed' 相應地會在 webpack 5 中廢棄,被 'deterministic' 代替 ) 47 // 拆分模塊 (https://www.cnblogs.com/kwzm/p/10314438.html) 48 splitChunks: { 49 chunks: 'async', // 選擇用於確定共享模塊的塊(默認為“async”、“initial”和“all”需要將這些塊添加到HTML中) 50 minSize: 30000, // 創建塊的大小 51 // minRemainingSize: 0, 52 maxSize: 0, 53 minChunks: 1, 54 maxAsyncRequests: 6, 55 maxInitialRequests: 4, 56 automaticNameDelimiter: '~', 57 cacheGroups: { 58 defaultVendors: { 59 test: /[\\/]node_modules[\\/]/, 60 priority: -10 61 }, 62 default: { 63 minChunks: 2, 64 priority: -20, 65 reuseExistingChunk: true 66 }, 67 elementUI: { 68 name: "chunk-elementUI", // 單獨將 elementUI 拆包 69 priority: 15, // 權重需大於其它緩存組 70 test: /[\/]node_modules[\/]element-ui[\/]/ 71 } 72 } 73 } 74 }, 75 //配置插件項 76 plugins: [ 77 // http://vuejs.github.io/vue-loader/en/workflow/production.html 78 // 自定義一個plugin 生成當前環境下的一個變量 79 new webpack.DefinePlugin({ 80 'process.env': env 81 }), 82 //壓縮 83 new UglifyJsPlugin({ 84 uglifyOptions: { 85 // 禁止壓縮警告信息 86 warnings: false 87 }, 88 sourceMap: config.build.productionSourceMap, //是否開啟sourceMap 用來調試 89 parallel: true //在系統的CPU有多於一個內核時自動啟用 僅作用於生產構建 90 }), 91 // 將css解壓縮到它自己的文件中 92 new MiniCssExtractPlugin({ 93 //文件名 94 filename: utils.assetsPath('css/app.[name].css'), 95 chunkFilename: utils.assetsPath('css/app.[contenthash:12].css'), // use contenthash * 96 }), 97 //壓縮提取CSS。我們使用這個插件,所以可以從不同的組件復制CSS。 98 new OptimizeCSSPlugin({ 99 cssProcessorOptions: config.build.productionSourceMap ? { 100 safe: true, 101 map: { 102 inline: false 103 } 104 } : { 105 safe: true 106 } 107 }), 108 // generate dist index.html with correct asset hash for caching. 109 // you can customize output by editing /index.html 110 // see https://github.com/ampedandwired/html-webpack-plugin 111 new HtmlWebpackPlugin({ 112 filename: process.env.NODE_ENV === 'testing' ? 113 'index.html' : config.build.index, 114 template: 'index.html', 115 favicon: path.resolve(__dirname, '../static/images/favicon.ico'), 116 inject: true, 117 minify: { 118 removeComments: true, 119 collapseWhitespace: true, 120 removeAttributeQuotes: true 121 // more options: 122 // https://github.com/kangax/html-minifier#options-quick-reference 123 }, 124 // necessary to consistently work with multiple chunks via CommonsChunkPlugin 125 chunksSortMode: 'manual', 126 dll: (function () { 127 let max = 2 128 let res = [] 129 for (let i = 0; i < max; i++) { 130 const dllName = require(path.resolve(__dirname, `../dllManifest/xuAdmin${i}-manifest.json`)).name.split('_') 131 res.push(`./static/dll/${dllName[0]}.${dllName[1]}.dll.js`) 132 } 133 return res 134 })() 135 }), 136 // keep module.id stable when vendor modules does not change 137 new webpack.HashedModuleIdsPlugin(), 138 // enable scope hoisting 139 new webpack.optimize.ModuleConcatenationPlugin(), 140 // split vendor js into its own file 141 142 // extract webpack runtime and module manifest to its own file in order to 143 // prevent vendor hash from being updated whenever app bundle is updated 144 145 // This instance extracts shared chunks from code splitted chunks and bundles them 146 // in a separate chunk, similar to the vendor chunk 147 // see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk 148 149 150 // 復制自定義靜態資產 151 new CopyWebpackPlugin([{ 152 from: path.resolve(__dirname, '../static'), 153 to: config.build.assetsSubDirectory, 154 ignore: ['.*'] 155 }]), 156 ] 157 }) 158 159 160 //壓縮 161 if (config.build.productionGzip) { 162 const CompressionWebpackPlugin = require('compression-webpack-plugin') 163 164 webpackConfig.plugins.push( 165 new CompressionWebpackPlugin({ 166 asset: '[path].gz[query]', // 目標資源名稱 [path]會被替換成原始資源的路徑 [query]會被替換成查詢字符串 167 algorithm: 'gzip', // 按照zlib的算法 168 // 所有匹配該正則的資源都會被處理 默認值是全部資源 169 test: new RegExp( 170 '\\.(' + 171 config.build.productionGzipExtensions.join('|') + 172 ')$' 173 ), 174 threshold: 10240, // 只有大小大於該值得資源會被處理,單位是bytes 175 minRatio: 0.8 // 壓縮率小於這個值得資源才會被處理 默認值是 0.8 176 }) 177 ) 178 } 179 180 //打包文件分析工具 181 if (config.build.bundleAnalyzerReport) { 182 const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 183 webpackConfig.plugins.push(new BundleAnalyzerPlugin()) 184 } 185 186 //導出 187 module.exports = webpackConfig