1. 简介
接上节4-1 Tree Shaking 概念详解末尾,我们可以看到,在 mode 进行切换时,webpack.config.js 的配置也是不一样的。这很好理解,开发环境中我们更多地是考虑开发和调试方便,生产环境我们更多考虑性能。但我们总不会每次切换环境的时候,还要手动去更改配置吧。最简单就是保存两份配置,对应不同的环境。
2. 开发环境配置
// webpack.dev.js
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin');
var path = require('path');
var webpack = require('webpack');
module.exports = {
mode: 'development',
entry: {
index: "./src/index.js",
},
devtool: "cheap-module-eval-source-map",
output: {
path: path.resolve(__dirname, 'dist'),
filename: "[name].js"
},
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
open: true,
port: 3000,
hot: true // 开启热更新
},
module: {
rules: [
{
test: /\.(jpg|jpeg|png|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
limit: 2048
}
}
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader',
]
},
{
test: /\.(eot|svg|ttf|woff)$/,
use: 'file-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
}),
new CleanWebpackPlugin(),
new webpack.HotModuleReplacementPlugin()
]
};
"dev": "webpack-dev-server --config webpack.dev.js"
3. 生产环境配置
// webpack.prod.js
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin');
var path = require('path');
module.exports = {
mode: 'production',
entry: {
index: "./src/index.js",
},
devtool: "cheap-module-source-map",
output: {
path: path.resolve(__dirname, 'dist'),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.(jpg|jpeg|png|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
limit: 2048
}
}
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader',
]
},
{
test: /\.(eot|svg|ttf|woff)$/,
use: 'file-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
}),
new CleanWebpackPlugin()
]
};
"build": "webpack --config webpack.prod.js"
4. 公共配置抽取
可以看到开发环境和生产环境配置,存在很多一致的地方,写两套即浪费代码体积,又增加维护成本,我们尝试将其抽取。
// webpack.common.js
var HtmlWebpackPlugin = require('html-webpack-plugin');
var { CleanWebpackPlugin } = require('clean-webpack-plugin');
var path = require('path');
module.exports = {
entry: {
index: "./src/index.js",
},
output: {
path: path.resolve(__dirname, 'dist'),
filename: "[name].js"
},
module: {
rules: [
{
test: /\.(jpg|jpeg|png|gif)$/,
use: {
loader: 'url-loader',
options: {
name: '[name].[ext]',
limit: 2048
}
}
},
{
test: /\.css$/,
use: [ 'style-loader', 'css-loader' ]
},
{
test: /\.scss$/,
use: [
'style-loader',
'css-loader',
'postcss-loader',
'sass-loader',
]
},
{
test: /\.(eot|svg|ttf|woff)$/,
use: 'file-loader'
}
]
},
plugins: [
new HtmlWebpackPlugin({
template: "./src/index.html"
}),
new CleanWebpackPlugin()
]
};
提取后,dev 和 prod 如下:
// webpack.dev.js
var path = require('path');
var webpack = require('webpack');
module.exports = {
mode: 'development',
devtool: "cheap-module-eval-source-map",
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
open: true,
port: 3000,
hot: true // 开启热更新
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
};
// webpack.prod.js
module.exports = {
mode: 'production',
devtool: "cheap-module-source-map"
};
5. 合并配置
上面提取公共配置以后,dev 和 prod 的配置只剩很小一部分了,那么如何将公共配置与单独的环境配置合并到一起呢?需要使用 webpack-merge 库。
npm i webpack-merge -D
// webpack.dev.js
var path = require('path');
var webpack = require('webpack');
var merge = require('webpack-merge');
var commonConfig = require('./webpack.common');
var devConfig = {
mode: 'development',
devtool: "cheap-module-eval-source-map",
devServer: {
contentBase: path.resolve(__dirname, 'dist'),
open: true,
port: 3000,
hot: true // 开启热更新
},
plugins: [
new webpack.HotModuleReplacementPlugin()
]
};
module.exports = merge(commonConfig, devConfig);
// webpack.prod.js
var merge = require('webpack-merge');
var commonConfig = require('./webpack.common');
var prodConfig = {
mode: 'production',
devtool: "cheap-module-source-map"
};
module.exports = merge(commonConfig, prodConfig);
6. mode 选择
webpack 可以使用 mode 告知 webpack 使用相应模式的内置优化。可以理解为一系列配置的合集就是 mode。
7. 移动配置文件
现在的配置文件很分散,我们将他们挪到同一个目录 build 下:
"scripts": {
"dev": "webpack --config ./build/webpack.dev.js --watch",
"dev-server": "webpack-dev-server --config ./build/webpack.dev.js",
"build": "webpack --config ./build/webpack.prod.js"
},
运行打包命令 npm run dev
发现,build 目录下多了一个 dist。我们修改源码后,重新打包,发现 build/dist 的页面更新,但是 dist 下没有更新。这说明,代码输出的地址发生了改变,并且清除旧的打包代码插件的作用地址也发生了改变。这两个分别对应 output 和 CleanWebpackPlugin。
我们先改一下 output,如下:
output: {
path: path.resolve(__dirname, '../dist'),
filename: "[name].js"
},
删掉两个 dist,打包后如下:
说明输出地址已经正确了。我们在 dist 加一个文件 temp.js,重新打包,如下:
temp.js 消失了,说明 CleanWebpackPlugin 已经正确生效。这一点和视屏讲述不一样,因为 CleanWebpackPlugin 已经升级,会将作用目标定为 output.path,不需要再像旧版一样传入 root 来指定根目录。详见 https://github.com/johnagan/clean-webpack-plugin/issues/106。
参考
https://www.webpackjs.com/concepts/mode/
https://www.npmjs.com/package/clean-webpack-plugin