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