「这是我参与2022首次更文挑战的第5天,活动详情查看:2022首次更文挑战」。
前言
本人用了约一周的业余时间,大致看了一遍react与vue官方脚手架中的webpack配置项,从中看到了一些对开发效率以及生产性能相关但又容易忽略的配置项与插件记录了下来,然后有了本文。
先决条件
有一定webpack基础,本文用意在于用另一个视觉去温故或知新部分webpack配置项以及插件。
React脚手架中的webpack配置项
脚手架源码:create-react-app
本文使用react-scripts版本为5.0.0,webpack版本5.69.1
如何查看webpack配置项
使用命令行工具,执行npx create-react-app wpstudy从远端获取react脚手架模版工程,并自动安装相关的依赖。
脚本执行完毕后,进入wpstudy目录:
进入package.json查看script配置项:
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
}
其中eject脚本是不可逆的运行脚本,其作用是把react-scripts封装的webpack配置“喷射”出来,方便开发者查看和修改。eject指令只会输出webpack配置,babel以及eslint等依赖的配置还是会继续引用react-scripts。
接下来义无反顾执行npm run eject,执行后目录新增内容如下:
比eject前新增的config目录和script目录,并且package.json文件中依赖项也发生了变化。其中config目录下的webpack.config.js是本文主要讲述的内容。
webpack.config.js的内容查看,若不想折腾上述过程可以直接访问:
github1s.com/facebook/cr…
部分配置介绍
bail
默认值为false,当设置为true时候,打包过程中一旦遇到异常将会中断。create-react-app在生产打包下把此项设置为true。
// 193行
bail: isEnvProduction,
resolve 中的 modules
指定寻找第三方模块引用的路径范围,提升构建速度。
// 308行
modules: ['node_modules', paths.appNodeModules].concat(
modules.additionalModulePaths || []
),
ModuleScopePlugin
指定非第三方模块的路径目录解释范围,防止开发者使用系统相对路径引用其他项目的模块。
// 24 行
const ModuleScopePlugin = require('react-dev-utils/ModuleScopePlugin');
// 337 行
new ModuleScopePlugin(paths.appSrc, [
paths.appPackageJson,
reactRefreshRuntimeEntry,
reactRefreshWebpackPluginRuntimeEntry,
babelRuntimeEntry,
babelRuntimeEntryHelpers,
babelRuntimeRegenerator,
]),
module 中的 Rule.oneOf
配置值类型为数组,数组每个项为配置文件规则以及对应处理该规则文件相对应的loader配置项。当前处理的文件将从前往后便利数组,一旦符合规则执行完对应loader编译逻辑后,将不会再继续往后遍历其他规则。使用oneOf能提升构建速度,并能提供配置都可读性。
相关配置代码片段:
// 361行
oneOf: [
//...
]
InlineChunkHtmlPlugin
此插件用在生产可选配置中,用户通过process.env.INLINE_RUNTIME_CHUNK选用,默认为false。
相关配置代码片段:
// 59行
const shouldInlineRuntimeChunk = process.env.INLINE_RUNTIME_CHUNK !== 'false';
// 634行
isEnvProduction &&
shouldInlineRuntimeChunk &&
new InlineChunkHtmlPlugin(HtmlWebpackPlugin, [/runtime-.+[.]js/]),
开启后会把runtime脚本内联到html之中。
优点:
- 减少http并发请求
- 加速runtime脚本初始化执行
缺点:
- 增大html体积
CaseSensitivePathsPlugin
环境变量区分大小写。
WebpackManifestPlugin
主要用于服务端渲染:我们打包出来的js,css都是带上版本号的,通过HtmlWebpackPlugin可自动帮我们在index.html里面加上带版本号的js和css。但是在某些情况,index.html模板由后端渲染,那么我们就需要一份打包清单,知道打包后的文件对应的真正路径。
// 21行
const { WebpackManifestPlugin } = require('webpack-manifest-plugin');
// 676行
new WebpackManifestPlugin({
fileName: 'asset-manifest.json',
publicPath: paths.publicUrlOrPath,
generate: (seed, files, entrypoints) => {
const manifestFiles = files.reduce((manifest, file) => {
manifest[file.name] = file.path;
return manifest;
}, seed);
const entrypointFiles = entrypoints.main.filter(
fileName => !fileName.endsWith('.map')
);
return {
files: manifestFiles,
entrypoints: entrypointFiles,
};
},
}),
WorkboxWebpackPlugin
生成PWA相关的worker脚本以及配置文件。
Vue脚手架中的webpack配置项
脚手架源码: vue-cli
本文 @vue/cli版本为5.0.1,webpack版本为5.69.1。
如何查看webpack配置
全局安装@vue/cli:
npm install -g @vue/cli
# OR
yarn global add @vue/cli
创建模版工程:
vue create wpstudy
命令行执行指令,输出webpack配置:
cd wpstudy
vue inspect --mode=development > webpack.config.dev.js
vue inspect --mode=production > webpack.config.pro.js
生成webpack.config.dev.js与webpack.config.pro.js为当前模版工程开发环境与生产环境对应的webpack配置。
部分配置介绍
大部分配置项与CRA(create-react-app)大同小异,以下介绍一些本人觉得有意思的配置项。
Pug
配置中默认支持Pug模版引擎,还没了解过Pug的同学可以点击了解一下。
splitChunks.cacheGroups
cacheGroups 是 splitChunks 的核心配置,splitChunks 里的配置相当于是 cacheGroups 里每一项的默认值,而 splitChunks 会根据 cacheGroups 的配置去拆分模块。
cacheGroups 里可以定义每种类型包的抽离规则,比如defaultVendors配置,test 值为 node_modules,意为只匹配 node_modules 的内容,即只打包第三方库,所以 defaultVendors 配置就是抽离的第三方库。
splitChunks: {
cacheGroups: {
defaultVendors: {
name: 'chunk-vendors',
test: /[\\/]node_modules[\\/]/,
priority: -10,
chunks: 'initial'
},
common: {
name: 'chunk-common',
minChunks: 2,
priority: -20,
chunks: 'initial',
reuseExistingChunk: true
}
}
}
thread-loader
使用多线程方式去编译/\.m?jsx?$/jsx和mjsx,加快编译速度。
引用官方说明:
把thread-loader放在其他loader之前, 放置在这个 loader 之后的 loader 就会在一个单独的 worker 池(worker pool)中运行。
在 worker 池(worker pool)中运行的 loader 是受到限制的。例如:
- 这些 loader 不能产生新的文件。
- 这些 loader 不能使用定制的 loader API(也就是说,通过插件)。
- 这些 loader 无法获取 webpack 的选项设置。
每个 worker 都是一个单独的有 600ms 限制的 node.js 进程。同时跨进程的数据交换也会被限制。
{
test: /\.m?jsx?$/,
exclude: [
function () { /* omitted long function */ }
],
use: [
/* config.module.rule('js').use('thread-loader') */
{
loader: '***/wpstudy/node_modules/thread-loader/dist/cjs.js'
},
...
]
}
总结
以上是本人读完两个主流框架脚手架的webpack配置后,把随笔中记录的配置重新梳理了一遍,主要作为索引的形式记录。若需要深入理解请查阅相关文档,谢谢阅读。