跳到主要内容

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可以自动加载这些模块,而不必到处importrequire

使用方法如下

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 功能十分强大,还有很多高级用法,需要在实践中不断积累和学习。希望这篇文章对你有所帮助。