Webpack 常用配置项
HtmlWebpackPlugin
HtmlWebpackPlugin 可以简化 HTML 文件的创建。它会自动生成一个 HTML 文件,并将打包后的 JS 文件自动引入到这个 HTML 文件中。
使用方法如下
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
// ...
plugins: [
new HtmlWebpackPlugin({
template: './src/index.html',
}),
],
};
更多配置项可以参考官方文档:HtmlWebpackPlugin | webpack 中文网
sourceMap
sourceMap 可以建立源文件和打包文件之间的映射关系。当代码出错时,可以利用 sourceMap 快速定位到源文件中的错误位置,方便调试。
使用方法如下
module.exports = {
// ...
devtool: 'source-map',
};
更多配置项可以参考官方文档:source-map-loader | webpack
WebpackDevServer
WebpackDevServer 可以启动一个开发服务器,并提供一些实用的功能,比如自动编译、自动刷新浏览器、请求转发等。
使用方法如下
module.exports = {
// ...
devServer: {
contentBase: './dist',
hot: true,
},
};
更多配置项可以参考官方文档:webpack-dev-server API | webpack
HMR 热更新
HMR(Hot Module Replacement)可以在不刷新浏览器的情况下,更新页面中的模块。这样可以保留应用的状态,提高开发效率。
使用方法如下
const webpack = require('webpack');
module.exports = {
// ...
devServer: {
hot: true,
},
plugins: [new webpack.HotModuleReplacementPlugin()],
};
在 JS 模块中,可以通过module.hot.accept
来接受模块更新:
if (module.hot) {
module.hot.accept('./library.js', function () {
// 更新逻辑
});
}
更多使用方法可以参考官方文档:Hot Module Replacement | webpack
使用 Babel 处理 ES6 代码
现代 JS 代码大多使用了 ES6+语法,而有些浏览器并不支持这些新语法。我们可以使用 Babel 将 ES6 代码转换为 ES5 代码。
如果是开发普通项目,可以使用@babel/polyfill
来处理:
module.exports = {
// ...
entry: ['@babel/polyfill', './app/js'],
};
如果是开发工具库,为了避免全局污染,可以使用babel-plugin-transform-runtime
:
{
"plugins": [
[
"@babel/plugin-transform-runtime",
{
"corejs": 3
}
]
]
}
更多使用方法可以参考: @babel/polyfill · Babel babel-plugin-transform-runtime · Babel 中文文档 - 印记中文 GitHub - zloirock/core-js: Standard Library
Loader 的概念
Webpack 本身只能处理 JS 模块,如果要处理其他类型的文件,就需要使用对应的 loader。比如:
- 使用
css-loader
处理 CSS 文件 - 使用
file-loader
处理图片文件 - 使用
babel-loader
处理 ES6 代码
使用方法如下
module.exports = {
// ...
module: {
rules: [
{
test: /\.css$/,
use: ['style-loader', 'css-loader'],
},
],
},
};
更多 loader 可以参考官方文档:style-loader | webpack
打包 React 代码
使用 Webpack 打包 React 代码,需要安装一些额外的依赖:
npm install --save-dev @babel/preset-react
然后在.babelrc
中添加@babel/preset-react
:
{
"presets": ["@babel/preset-react"]
}
更多使用方法可以参考:@babel/preset-react · Babel 中文文档
Tree Shaking
Tree Shaking 可以移除代码中未引用的部分,减小打包体积。Webpack 4 默认支持这个功能。
需要注意的是,Tree Shaking 依赖 ES Modules 的静态结构特性。CommonJS 是动态引入,无法分析依赖关系。
更多信息可以参考:Tree shaking - 术语表 | MDN
不同环境的配置
我们的项目通常需要在不同的环境下使用不同的配置,比如开发环境和生产环境。可以通过设置不同的配置文件来实现:
webpack.common.js
存放公共配置webpack.dev.js
存放开发环境配置webpack.prod.js
存放生产环境配置
然后使用webpack-merge
合并配置:
const merge = require('webpack-merge');
const common = require('./webpack.common.js');
module.exports = merge(common, {
mode: 'development',
// ...
});
JS 代码分割
随着项目越来越大,打包后的 JS 文件也会越来越大。我们可以使用代码分割将代码拆分为多个文件,按需加载。
Webpack 4 内置了SplitChunksPlugin
来实现代码分割。它会自动提取公共模块,生成单独的 chunk。
使用方法如下
module.exports = {
// ...
optimization: {
splitChunks: {
chunks: 'all',
},
},
};
更多配置项可以参考官方文档:SplitChunksPlugin | webpack
懒加载
懒加载可以延迟加载不是立即需要的代码,加快页面初始加载速度。比如路由组件、图片等。
使用方法如下
const Login = () => import('./login.js');
const routes = [
{
path: '/login',
component: Login,
},
];
当路由切换到/login
时,才会加载login.js
文件。
module、chunk、bundle 的区别
这三个概念容易混淆,这里简单说明一下:
- module - 各个源码文件,比如 JS 模块、CSS 模块、图片等
- chunk - 代码分割后的产物,一个 chunk 由多个模块组成,用于代码的合并和分割
- bundle - 最终的输出文件,一个 bundle 对应一个 chunk,可以根据需要生成多个 bundle
它们的关系如下图:
CSS 代码分割
CSS 代码也可以像 JS 代码一样实现分割,生成单独的文件。这可以使用MiniCssExtractPlugin
实现:
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
module.exports = {
// ...
module: {
rules: [
{
test: /\.css$/,
use: [MiniCssExtractPlugin.loader, 'css-loader'],
},
],
},
plugins: [
new MiniCssExtractPlugin({
filename: '[name].css',
}),
],
};
这样 CSS 代码会生成单独的文件,而不是内嵌在 JS 中。
更多配置项可以参考官方文档:MiniCssExtractPlugin | webpack
文件指纹
每次项目发布,我们常常会修改文件的内容。但是如果文件名不变,浏览器可能会使用缓存中的老文件,不能及时获取最新内容。
为了解决这个问题,我们可以给文件名加上 hash 值。当文件内容变化时,hash 值也会变化,从而请求新的文件。这个过程叫做"文件指纹"。
使用方法如下
module.exports = {
// ...
output: {
filename: '[name].[contenthash].js',
},
};
这样生成的文件名类似main.a2c0ab.js
,每次文件修改后,hash 值会变化,文件名也会变化。
更多信息可以参考官方文档:Caching | webpack
Shimming
有些第三方库(比如 jQuery)可能会引用一些全局依赖(比如$
)。这些库一般要求使用者也提供这些全局变量。
Webpack 的ProvidePlugin
可以自动加载这些模块,而不必到处import
或require
。
使用方法如下
const webpack = require('webpack');
module.exports = {
// ...
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
_: 'lodash',
}),
],
};
这样在代码中就可以直接使用$
和_
变量,而不需要手动引入。
更多信息可以参考官方文档:Shimming | webpack
Webpack 4/5 的区别
Webpack 5 相比 Webpack 4 有了很多改进,这里列举几点主要区别:
默认打包区别:
- Webpack 5 打包生产环境代码时,默认会压缩代码、开启 Tree Shaking 等优化
- Webpack 4 需要手动配置优化项
自带 Tree Shaking:
- Webpack 5 内置了更完善的 Tree Shaking 功能,代码优化更彻底
- Webpack 4 需要配合一些插件才能实现完整的 Tree Shaking
总的来说,Webpack 5 的默认配置更加优化,开箱即用,上手更加方便。
以上就是我对 Webpack 常用配置项的一些理解和总结。Webpack 功能十分强大,还有很多高级用法,需要在实践中不断积累和学习。希望这篇文章对你有所帮助。