学一点Webpack配置:Webpack的优化
特别声明:小站对部分原创文章已开启付费阅读,并开通年费VIP通道,年费价格为 ¥365.00元。如果您喜欢小站的内容,可以点击开通会员进行全站阅读。如果您对付费阅读有任何建议或想法,欢迎发送邮件至: airenliao@gmail.com!(^_^)
在上一篇中花了14小节主要和大家一起探讨了Webpack 4.x的一些基本配置,比如初始化项目,添加各种Loader、React、Typescript、Sass、PostCSS、CSS Modules等配置、图片加载、字体加载以及各种代码检测的能力,比如ESLint的配置、Prettier的配置和StyleLint的配置。在接下来这个部分,主要和大家一起来探讨Webpack 4.x中的一些优化方面的配置。比如开发环境的优化、Webpack自身的优化、文件压缩和依赖监控以及应用分析相关的配置。如果感兴趣的话,欢迎继续往下阅读。
在阅读接下来的内容之前,如果你没有阅读上一篇,建议你先花点时间阅读上一篇,这样会更有系统性的学习。
Step15:开发环境优化
请把分支切换到
step15查看代码。
开启局部模块热重载
在这一节中我们来对基本环境做一些优化。在开发环境中引入webpack.HotModuleReplacementPlugin用于启用局部模块热重载,方便我们开发。
我们在Step03中将Webpack的环境分离出来了,有关于Webpack开发环境的配置都将在webpack.dev.js做调整。如果我们要在开发环境加上webpack.HotModuleReplacementPlugin就需要在webpack.dev.js的plugins来做调整:
// ...
module.exports = merge(commonConfig, {
// ...
// 开发环境下需要的相关插件配置
plugins: [new webpack.HotModuleReplacementPlugin()],
// ...
});
另外在devServer也做一些调整:
// 开发服务器
devServer: {
hot: true, // 热更新,无需手动刷新
contentBase: DIST_PATH, //
host: '0.0.0.0', // host地址
port: 8080, // 服务器端口
historyApiFallback: true, // 该选项的作用所用404都连接到index.html
overlay: {
// 当出现编译错误或警告时,就在页面上显示一层黑色的背景层和错误信息
errors: true,
},
inline: true,
},
使用静态资源路径
网页中总是会使用到一些静态资源,将这些静态资源部署到CDN服务上,使用得用户可以就近访问资源,加快访问速度。在Webpack中,我们可以通过publicPatch来配置CDN服务器对应的URL。
就我们这个工程而言,可以在webpack.common.js中output中指定publicPath:
// webpack.common.js
// 编译输出的JS入路径
// 告诉Webpack在哪里输出它所创建的bundle,以及如何命名这些文件
output: {
path: DIST_PATH, // 创建的bundle生成到哪里
filename: '[name].bundle.js', // 创建的bundle的名称
sourceMapFilename: '[name].js.map', // 创建的SourceMap的文件名
publicPath: '/', // 指定存放静态资源的CDN地址
},
为导出的JS文件添加hash
当我们修改代码,bundle被重新打包,很可能在客户端上看到的效果并不是最新的效果,这有可能是缓存所造成的,有的时候需要多次刷新浏览器,甚至是要手动去清除缓存。不管是在开发环境还是生产环境,这直接影响我们的开发效率。在Webpack中我们可以很轻易的解决这个问题。只需要在输出的JS文件上加上hash值,这样一来,每次输出的JS文件名都会不同,那么文件也就不会被缓存。
只需要在output的filename值上添加hash值:
// webpack.common.js
output: {
path: DIST_PATH, // 创建的bundle生成到哪里
filename: '[name].bundle.[hash].js', // 创建的bundle的名称
sourceMapFilename: '[name].js.map', // 创建的SourceMap的文件名
publicPath: '/', // 指定存放静态资源的CDN地址
},
输出的bundle.js会每次都带上相应的hash值:

注意,如果你在Webpack配置中使用了webpack.HotModuleReplacementPlugin()的话,那么在output.filename中的值不能使用[chunkhash],只能使用[hash]。
这样一来每次修改代码都会生成一个带hash的JS文件。要是你执行npm run build同样会这样,并且会让你项目中/dist目录下有关于bundle.js的文件会越来越多,比如:

编译前清理dist目录
上一节我们看到了,每次都会为bundle.js新增文件,如果多次修改,再次编译或打包就会在/dist目录下生成一堆的JS文件,但上一次打包的文件对于我们来说没有实际用处。因此,我们需要在每次打包时清除/dist目录下的旧文件。
实现该功能,可以借助Webpack的CleanWebpackPlugin来实现,在配置之前先安装该插件:
⇒ npm i clean-webpack-plugin -D
然后webpack.common.js中添加相应的配置:
// webpack.common.js
// 注意最新版本引用CleanWebpackPlugin 不能使用 const CleanWebpackPlugin = require('clean-webpack-plugin')
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
module.exports = {
// ...
// 模块解析
module: {
rules: [
// ...
]
// 插件
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
inject: true,
template: HtmlWebpackTemplate,
appMountId: 'root',
filename: 'index.html',
}),
],
};
另外一个细节,如果配置中同时出现CleanWebpackPlugin和HtmlWebpackPlugin时,CleanWebpackPlugin需要放置在HtmlWebpackPlugin的前面。
配置完成之后,你在命令终端执行npm run build的时候,/dist目录下中以前的bundle.js会自动清除。
这里额外提一下,在HtmlWebpackPlugin的配置中我们可以添加minify相关的配置,这样会将打包生的.js和.css文件引入到.html文件中:
// webpack.common.js
plugins: [
new CleanWebpackPlugin(),
new HtmlWebpackPlugin({
inject: true,
template: HtmlWebpackTemplate,
appMountId: 'root',
filename: 'index.html',
minify: {
removeComments: true, // 去掉注释
collapseWhitespace: true, // 去掉多余空白
removeAttributeQuotes: true, // 去掉一些属性的引号,例如id="moo" => id=moo
},
}),
],
有了上面的配置之后,在代码中的注释、空白等就会自动清除,比如App.tsx中的注释:
<!-- App.tsx -->
<div style={{ textAlign: 'center' }}>
<img src={String(Security)} />
{/* 下面这样引用,图片会报404错误 */}
{/* <img src="../../../../assets/images/security.svg" alt=""/> */}
</div>
编译出来.html中就看不到了。如下图所示:

Step16:Webpack的优化
请把分支切换到
step16查看代码。
在这一步我们主要来一起探讨Webpack中的一些优化。
文件路径优化
在Webpack中我们配置了resolve.extension之后可以不用在require或import的时候加文件扩展名,Webpack会依次尝试添加扩展名进行匹配。在resolve中还可以通过alias来配置别名,可以加快Webpack查找模块的速度。
// webpack.common.js
alias: {
'@': path.resolve(__dirname, '../src'),
'@components': path.resolve(__dirname, '../src/components'),
'@pages': path.resolve(__dirname, '../src/pages'),
'@images': path.resolve(__dirname, '../src/assets/images'),
'@fonts': path.resolve(__dirname, '../src/assets/fonts'),
'@icons': path.resolve(__dirname, '../src/assets/icons'),
},
在实际使用的时候,我们就可以使用定义好的别名了:
<!-- App.tsx -->
const Security = require('@images/security.svg');
// app.css
body {
background: url("~@images/body-background.jpg") no-repeat center,
linear-gradient(to bottom, #f560a9, #09aefa, #2390af) no-repeat center;
}
有一点需要特别注意,在TypeScript环境下,如果仅在Webpack中配置别名是不够的,比如:
<!-- App.tsx -->
import Button from '@components/Button/Button';
编译的时候会报错:
Failed to compile.
[at-loader] ./src/pages/index/components/App/App.tsx:5:20
TS2307: Cannot find module '@components/Button/Button'.
我们需要在tsconfig.json中添加paths的配置:
{
"compilerOptions": {
"sourceMap": true,
"noImplicitAny": false,
"noUnusedLocals": true,
"noUnusedParameters": true,
"module": "es2015",
"target": "es6",
"lib": [
"es2015",
"es2017",
"dom"
],
"removeComments": true,
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"moduleResolution": "node",
"pretty": true,
"jsx": "preserve",
"allowJs": true,
"baseUrl": ".",
"rootDir": "./src",
"outDir": "./dist/",
"paths": {
"@/*": ["./src/*"],
"@components/*": ["./src/components/*"],
"@pages/*": ["./src/pages/*"],
"@images/*": ["./src/assets/images/*"],
"@fonts/*": ["./src/assets/fonts/*"],
"@icons/*": ["./src/assets/icons/*"],
}
},
"include": ["./src/**/*"],
"exclude": ["node_modules"]
}
上面的问题就解决了。
优化CSS文件
如果不做相关的配置,打包的时候CSS代码会直接打到JavaScript文件中。在Webpack中使用MiniCssExtractPlugin插件可以单独生成.css文件。这样CSS和JavaScript文件可以并行下载,提高页面加载性能。
先安装mini-css-extract-plugin:
⇒ npm i mini-css-extract-plugin -D
由于MiniCssExtractPlugin插件还不支持HMR,为了不影响开发效率,因为需要对开发环境做一下判断。目前有两种方式:
- 把
webpack.common.js中有关于样式的配置分开到webpack.dev.js和webpack.prod.js中分别处理,在webpack.prod.js中配置MiniCssExtractPlugin插件 - 在
webpack.common.js中通过process.env.NODE_ENV的值来做判断,如果值为production时才配置MiniCssExtractPlugin插件
在这里我们采用第二种方式:
// webpack.common.js
// ...
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// ...
// 模块解析
module: {
rules: [
// ...
// CSS Loader
{
test: /\.(sc|sa|c)ss$/,
exclude: /node_modules/,
include: path.resolve(__dirname, '../src'),
use: [
{
loader: process.env.NODE_ENV !== 'dev' ? MiniCssExtractPlugin.loader : 'style-loader',
options: {
sourceMap: true,
},
},
{
loader: 'css-modules-typescript-loader',
options: {
named
如需转载,烦请注明出处:https://www.w3cplus.com/javascript/webpack-config-part2.html
如果文章中有不对之处,烦请各位大神拍正。如果你觉得这篇文章对你有所帮助,打个赏,让我有更大的动力去创作。(^_^)。看完了?还不过瘾?点击向作者提问!



