theme: channing-cyan
导语
来到这家公司之后,一直在使用webpack,也写了不少笔记,但是都比较零散,现在决定整理一下webpack相关的知识点,由浅入深,方便自己后续查漏补缺,后续会一直更新。
前言
本文将从几个方面,介绍webpack如何优化打包后的运行体验,所谓运行体验,就是用户在使用我们打包后的应用时,能够快速加载页面,渲染关键信息。
目录
- splitChunks
- 懒加载
- prefetch 与 preload
- css内联
splitChunks
当我们打包的模块比较大的时候,我们可以通过splitChunks来进行分包配置,从 webpack v4 开始,移除了 CommonsChunkPlugin,取而代之的是 optimization.splitChunks,先来看一下它的默认配置
代码语言:javascript复制module.exports = {
//...
optimization: {
splitChunks: {
chunks: 'async',
minSize: 20000,//当导入的模块最小是多少字节才会进行代码分割
minRemainingSize: 0,//解析见代码下面的文字说明,不用设置
minChunks: 1,//当一个模块被导入(引用)至少多少次才对该模块进行代码分割
maxAsyncRequests: 30,//按需加载时的最大并行请求数
maxInitialRequests: 30,//入口点的最大并行请求数
enforceSizeThreshold: 50000,//解析见代码下面的文字说明,不用设置
cacheGroups: {//缓存组
defaultVendors: {
test: /[\/]node_modules[\/]/,
priority: -10,//优先级
reuseExistingChunk: true,
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
},
},
},
},
};
更多配置请参阅: https://webpack.docschina.org/plugins/split-chunks-plugin/
chunks
- all模式下,入口文件和动态引入文件都会进行打包,作用最强大
- initial 模式下,会将入口文件中的依赖包重新切割为一个新的文件,其它文件中动态引入的不会进行拆分
- async(默认值)模式下,入口文件中的模块输出一个依赖包,对于动态加载的模块,默认配置会将该模块单独打包。
cacheGroups
cacheGroups是让我们自定义打包策略的地方,我们想抽取的各类公共模块,都再这个地方配置,存组可以继承和/或覆盖来自 splitChunks.*
的任何选项,比较常用的几个参数有
- priority:优先级,只配置在缓存组的每一项,决定执行的顺序。
- minChunks:最小块,即当块的数量大于等于minChunks时,才起作用
- minSize:最小大小,即当抽取的公共模块的大小,大于minSize所设置的值,才起作用
- maxSize:如果引入的包大小已经超过了设置的最大值,那么webpack会尝试对该包再进行分割
- test:匹配规则,说明要匹配的项,这里是匹配匹配绝对模块资源路径或 chunk 名称
- name: 打包之后的文件名,从 webpack 5 开始,不再允许将 entry 名称传递给 {cacheGroup}.test 或者为 {cacheGroup}.name 使用现有的 chunk 的名称。
比如,我们想在默认缓存组的基础上,抽离react的相关依赖,我们可以这样配置
代码语言:javascript复制cacheGroups: {
// 配置提取模块的方案
defaultVendors: {
test: /[/]node_modules[/]/,
priority: -10,
reuseExistingChunk: true,
name: 'vendors',
},
default: {
minChunks: 2,
priority: -20,
reuseExistingChunk: true,
name: 'default',
},
react: {
test: /(react|react-dom)/, // 匹配chunk的名称
name: 'react', //打包后的文件名
chunks: 'all',
priority: 13, // 优先级 越高则先处理
},
},
在打包后,就会看到react的依赖包
懒加载
懒加载其实也叫动态加载,顾名思义,就是在项目中,不一开始就加载所有资源,而是在使用到的时候再进行加载,依赖于ES Module,比如说,
有一个asyncImportModule.js的文件,里面的方法返回一个新的组件
代码语言:javascript复制// 用于动态引入的module
console.log('console一下证明引入了文件');
const AsyncImportModule = () => {
return <div class='module'>这是一个新的module</div>;
};
export default AsyncImportModule;
然后我们在页面中的方法动态引用它
代码语言:javascript复制onclick=() => {
import('./base/asyncImportModule').then((res) => console.log(res));
}
通过splitchunks的配置,我们动态引用到的文件会打包成一个额外的包
在页面中运行时,一开始并不会加载这个js文件,只有当我们执行方法时才会加载这个js文件。
内联注释
通过在 import 中添加注释,我们可以进行诸如给 chunk 命名或选择不同模式的操作。比如,我们可以通过传入webpackChunkName来指定打包后的文件名
代码语言:javascript复制import(/* webpackChunkName: "changeModuleName" */'./base/asyncImportModule').then((res) => console.log(res));
更多配置请参阅: https://webpack.docschina.org/api/module-methods/#magic-comments
react中使用懒加载
react提供了React.lazy
和 Suspense
方法来实现懒加载以及代码分割
const Home = lazy(() => import(/* webpackChunkName: "home" */ './home/index'));
const SuspenseComponent = (Component: any) => (props: any) => (
<Suspense fallback={Loading}>
<Component {...props}></Component>
</Suspense>
);
const App = () => {
return <div>
{SuspenseComponent(Home)}
</div>
}
prefetch 与 preload
前面说到了我们可以动态的引入资源,但是如果需要异步加载的文件比较大时,在点击的时候去加载也会影响到我们的体验,这个时候我们就可以考虑使用 prefetch 来进行预拉取,使用preload进行预加载。
prefetch和preload也是通过内联注释进行配置
prefetch (预获取):浏览器空闲的时候进行资源的拉取
代码语言:javascript复制// 按需加载
img.addEventListener('click', () => {
import( /* webpackPrefetch: true */ './desc').then(({ default: element }) => {
console.log(element)
document.body.appendChild(element)
})
})
preload (预加载):提前加载后面会用到的关键资源,因为会提前拉取资源,如果不是特殊需要,谨慎使用
官网示例:
代码语言:javascript复制import(/* webpackPreload: true */ 'ChartingLibrary');
css内联
在打包时,我们可以将css通过style标签内联到页面中,这样做的好处是可以让页面样式更快的渲染出来,也能避免页面闪动,不过在webpack5已经放弃了这种方法。
使用postcss-loader实现
代码语言:javascript复制{
loader: 'postcss-loader',
options: {
//将样式标签插入到header
insertAt: 'top',
//将所有style标签合成为一个
singleton: true,
plugins: () => [
require('autoprefixer')({
//配置浏览器版本
browsers: ['Android 4.1', 'iOS 7.1', 'Chrome > 31', 'ff > 31', 'ie >= 8'],
}),
],
},
},
项目链接
https://github.com/AdolescentJou/webpack-base-demo
最后
感谢你能看到这里,本文总结了优化运行体验的几种配置,希望对你有所帮助,之后会陆续更新其他webpack相关的文章。
参考链接
https://webpack.docschina.org
https://juejin.cn/post/7023242274876162084#heading-52