Webpack4 配置详解
# # Webpack4 配置详解
Webpack4后包拆成webpack和webpack-cli两个包:
// 安装webpack
npm install --save-dev webpack webpack-cli
2
3
主要有以下这些一级配置:
module.exports = {
mode: 'development', // 模式配置,webpack4.0新增
entry: '', // 入口文件
output: {}, // 出口文件
module: {
rules: [/*loader setting*/]
}, // 配置modules,包括loader
plugins: [], // 对应的插件
devServer: {}, // 开发服务器配置
optimization: {}, // 最佳实践
devtool: '',
resolve: { alias: {}},
}
2
3
4
5
6
7
8
9
10
11
12
13
14
# # 1. mode
Webpack 4 引入了 mode 这个选项。这个选项的值可以是 development 或者 production。 设置了 mode 之后会把 process.env.NODE_ENV 也设置为 development 或者 production。然后在 production 模式下,会默认开启 UglifyJsPlugin 等一堆插件。
webpack4支持ES6的方式导入JSON文件,并且支持Tree-shaking
# # 2. entry/output
默认的入口为'./src/'和默认出口'./dist'。
# # 3. mudule - rules - loader配置
webpack4中移除loaders配置,必须使用rules。rules 配置模块的读取和解析规则, 通常用来配置loader, 其类型是一个数组, 数组里每一项都描述了如何去处理部分文件。
配置一项rules大致通过以下方式:
- 条件匹配: 通过test、include、exclude三个配置来命中Loader要应用的规则文件。(三个配置都可以是正则,也支持数组)
- 应用规则: 对选中后的文件通过use配置项来应用loader,可以应用一个loader或者按照从后往前的顺序应用一组loader。同时还可以分别给loader传入参数。
- 重置顺序: 一组loader的执行顺序默认是从右到左执行,通过exforce选项可以让其中一个loader的执行顺序放到最前或者是最后。
module: {
rules: [
{
test: /\.m?js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
options: {
presets: ['@babel/preset-env']
}
}
},
{
test: /\.scss$/,
use: ['style-loader', 'css-loader', 'sass-loader'],
exclude: path.resolve(__dirname, 'node_modules')
}
]
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
常用loader:(待补充)
- css
- style-loader
- css-loader
- postcss-loader
- sass-loader
# # 4. optimization
在Webpack4中引入,根据mode(production/development)的不同,配置项默认值不同,具体有以下:
optimization.minimize
: 是否自动压缩打包后的代码。mode = production时,为true。压缩默认使用uglifyjs-webpack-plugin插件,如果想要使用别的压缩插件,可以使用optimization.minimizer
设置。optimization.splitChunks
: 根据不同的策略来分割打包出来的bundle。配置基于SplitChunksPlugin (opens new window) (opens new window),剔除了老的CommonsChunkPlugin(webpack4移除)。- optimization.splitChunks.chunks: async/all/initial
零配置
optimization.nodeEnv
: 告诉webpack process.env.NODE_ENV的值,值来自于mode的取值。代替webpack.DefinePlugin (opens new window) (opens new window)(webpack4移除)optimization.namedModules
: 代替webpack.NamedModulesPlugin(webpack4移除)optimization.noEmitOnErrors
: 代替webpack.NoEmitOnErrorsPlugin(webpack4移除)optimization.concatenateModules
: 代替webpack.optimize.ModuleConcatenationPlugin(webpack4移除)
# # plugins
- 常用插件
HtmlWebpackPlugin
自动在html中加载打包后的js文件DLLPlugin/DllReferencePlugin
提高打包速度- DLLPlugin:创建一个只有dll的bundle
- DllReferencePlugin: 打包生成的dll文件引用到需要的预编译依赖上来
- happyPack 多进程打包,加快打包速度。
webpack.DefinePlugin
webpack4设置mode会自动使用uglifyjs-webpack-plugin
webpack4 mode = production默认使用
- 废弃插件
- CommonsChunkPlugin 拆分依赖包,生成单独文件,使得文件大小减小。在webpack4被废弃,替代optimization.splitChunks
- ExtractTextWebpackPlugin 拆分css样式的插件(webapck4已废弃)。由于webpack4以后对css模块支持的逐步完善和commonchunk插件的移除,在处理css文件提取的计算方式上也做了些调整,之前我们首选使用的extract-text-webpack-plugin也完成了其历史使命,将让位于mini-css-extract-plugin (opens new window) (opens new window)。
# # devServer
举个完整例子:
const path = require('path');
const webpack = require('webpack');
// 插件都是一个类,所以我们命名的时候尽量用大写开头
const HtmlWebpackPlugin = require('html-webpack-plugin'); //打包html
const MiniCssExtractPlugin = require("mini-css-extract-plugin"); // 提取出来css
const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); // 压缩打包后的js
const HappyPack = require('happypack'); // 多线程构建
const happyThreadPool = HappyPack.ThreadPool({ size: 5 }); // 构造出共享进程池,进程池中包含5个子进程
const OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin')// 最大化压缩css
console.log('process.env.NODE_ENV------->', process.env.NODE_ENV)
// 解决css 分离后图片引入路径不正确问题
if (process.env.type == 'build') { // 判断package.json里面是build还是dev命令
// 开发
var website ={
publicPath:"/"
}
} else {
// 生产
var website ={
publicPath:"/"
}
}
module.exports = {
// devtool:'eval-source-map',
mode: 'development', // 模式配置
entry: {
main: './src/index.js',
},
output: {
filename: 'bundle.[chunkhash:6].js',
path: path.resolve(__dirname, 'dist'),
publicPath: website.publicPath, // 解决css 分离后图片引入路径不正确问题
},
module: {
rules: [
{
test: /\.css/,
exclude: /node_modules/,
use: ['style-loader', MiniCssExtractPlugin.loader, 'css-loader'],
},
{
test: /\.less$/,
exclude: /node_modules/,
use: ['style-loader', MiniCssExtractPlugin.loader, 'css-loader', 'less-loader'],
},
{
test: /\.(png|jpe?g|gif|svg)$/,
use: [
{
loader: 'url-loader',
options: {
limit: 10000,
name: '[name]_[hash:7].[ext]',
outputPath:'static/images/'
}
}
]
},
{
test: /\.(htm|html)$/,
use: 'html-withimg-loader'
},
// babel 解析es7 es6 jsx
{
test:/\.(jsx|js)$/,
include: [
path.resolve(__dirname, 'src'),
],
use:['babel-loader'],
/*
如果开启多线程进行构建
use:['happypack/loader?id=js'],
loader这样写 匹配下面注释的插件
*/
exclude:/node_modules/
},
]
},
plugins: [
// 打包html
new HtmlWebpackPlugin({
template: './src/index.html',
hash: true,
minify: {
minifyCSS: true,
minifyJS: true,
removeAttributeQuotes: true
},
}),
new MiniCssExtractPlugin({
filename: "static/css/[name].[chunkhash:8].css",
chunkFilename: "[id].css"
}),
new UglifyJsPlugin({
parallel: true,
}),
new webpack.DefinePlugin({
NODE_ENV: JSON.stringify('DEV')
}),
// 多线程构建 匹配上面的loader
// new HappyPack({
// id: 'js',
// //threads: 4,
// loaders: ['babel-loader'],
// threadPool: happyThreadPool, // 使用共享进程池中的子进程去处理任务
// }),
],
// 提取公共代码
optimization: {
minimizer: [
// 自定义js优化配置,将会覆盖默认配置 最大化压缩成js
new UglifyJsPlugin({
exclude: /\.min\.js$/, // 过滤掉以".min.js"结尾的文件,我们认为这个后缀本身就是已经压缩好的代码,没必要进行二次压缩
cache: true,
parallel: true, // 开启并行压缩,充分利用cpu
sourceMap: false,
extractComments: false, // 移除注释
uglifyOptions: {
compress: {
unused: true,
warnings: false,
drop_debugger: true
},
output: {
comments: false
}
}
}),
// 用于优化css文件 最大化压缩成css 并且去掉注释掉的css
new OptimizeCssAssetsPlugin({
assetNameRegExp: /\.css$/g,
cssProcessorOptions: {
safe: true,
autoprefixer: { disable: true },
mergeLonghand: false,
discardComments: {
removeAll: true // 移除注释
}
},
canPrint: true
})
],
splitChunks: {
cacheGroups: {
vendor: { // 抽离第三方插件
test: /node_modules/, // 指定是node_modules下的第三方包
chunks: 'initial',
name: 'vendor', // 打包后的文件名,任意命名
// 设置优先级,防止和自定义的公共代码提取时被覆盖,不进行打包
priority: 10
},
// utils: { // 抽离自己写的公共代码,utils这个名字可以随意起 (css/js公用的都会单独抽离出来生成一个单独的文件)
// chunks: 'initial',
// name: 'utils', // 任意命名
// minSize: 0 // 只要超出0字节就生成一个新包
// }
}
}
},
devServer: {
historyApiFallback: true,
inline: true
},
// externals: {
// jquery: "jQuery",
// },
resolve: {
// alias 别名配置,它能够将导入语句里的关键字替换成你需要的路径
alias: {
// 比如我们就可以直接写 import Nav from '@/Nav'
'@': './app/component'
},
// 省略后缀
extensions: ['.js', '.jsx', '.less', '.json', '.css'],
},
performance: {
hints: false // 选项可以控制 webpack 如何通知「资源(asset)和入口起点超过指定文件限制」
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183