打包分析
什么是打包分析
webapck打包分析是指在webpack打包后,通过一些插件来对我们的打包是否合理做出的分析。
对于这样的工具,有官网提供的,也有一些第三方的插件。我们可以参考官网去做相应的配置和选择webpack打包分析
我个人比较常用的是webpack-bundle-analyzer
,他的打包分析就像下面这样
可以很清晰的通过可视化的方式,让我们了解当前的打包情况,大家可以根据自己的选择,选择相应的插件进行配置和打包分析,通过打包分析,我们可以很清楚的发现打包中的潜在问题,并作出相应的调试。
Preloading/Prefetch
之前我们了解了代码分割,并用lodash的例子做了演示,我们通过代码分割的方式,将第三方库做了单独的打包,这样可以提高第二次访问的速度,显然,这样是有一些不太满足我们的预期的,我们更期望,第一次访问页面的速度就很快。这就涉及到了我们下面要讲解的内容Preloading/Prefetch
性能分析
我们将index.js改成下面这样,然后打包并运行index.html
document.addEventListener('click', () => {
const element = document.createElement('div')
element.innerHTML = 'hello Preloading'
document.body.appendChild(element)
})
首先代码运行是没有一点问题的,我们通过点击事件去给body中插入一个元素,但这真的就是最佳的写法吗?没有再精简的余地了吗?我们通过浏览器运行index.html,并在控制台中输入ctrl
+shift
+P
,在弹出的选择输入框中输入coverage这样的字,并打开show Coverage
,像下面这样
点击标黄区域的按钮,刷新页面,这时候,发现下面出现了分析条,这就是对代码中利用率的分析,我们通过分析条进入到index.js中,到最下面找到我们自己的逻辑,发现代码的利用率是这样的
当我们点击页面,这个时候代码的利用率才变成100%,也就是说,在页面刚加载的时候
const element = document.createElement('div')
element.innerHTML = 'hello Preloading'
document.body.appendChild(element)
这段代码是没有被利用的,再点击的时候,才利用起来。也就是我们一开始没有执行的代码,也会随着页面加载加载进来,这就造成了性能的浪费,webpack希望,我们这样的交互应该这样去处理
document.addEventListener('click', () => {
import('./click').then(({default: func}) => {
func()
})
})
click.js
function handleClick () {
const element = document.createElement('div')
element.innerHTML = 'hello Preloading'
document.body.appendChild(element)
}
export default handleClick
这个时候,再执行上面的分析操作,你会发现,代码的利用率提高了,当然哈,不同版本的浏览器可能和我操作的不一样,展示的也不一样,这里通过我的实验做说明,理论上都是这样的,通过上面的实验我们会发现,webpack更希望我们把代码的逻辑写成上面的样子。这样就会让代码的利用率变高,同时加载的也会更快。所以只有多写异步组件,才能真正的提升意面性能这也就是为什么在splitChunksPlugin
中的chunks
选项,默认是async
的原因。因为同步的代码,对于优化来说只能增加一个缓存,而对于页面性能的优化,也是非常有限的。
那么,在实际项目中,我们怎么去使用这样的异步的引入呢?比如在一些业务场景中,经常会有弹层的操作,那么其实我们就可以将弹层代码加载变成异步,但这样又会导致,点击呼出弹层的交互变得比较慢,为解决这一问题,我们将使用Preloading/Prefetch
Preloading/Prefetch
设想这样一种场景,我们在加载整个首页资源的时候不去加载弹层的资源,也不在去点击的时候才去加载对应的资源,而是在首页资源加载完毕到点击呼出弹层这个空闲时间去操作,是不是就既能满足首页加载快,又能满足呼出弹层快的操作呢?我们还是通过模拟代码来做这个实验,我们对之前的index.js做下面的修改
document.addEventListener('click', () => {
import(/*webpackPrefetch: true*/'./click').then(({default: func}) => {
func()
})
})
上面魔法注释的意思是,我们等主要代码加载完毕后,不用等点击事件去执行就去加载对应的资源,我们打包后,通过netWork来监控一下资源的加载,我们发现,当页面刚一加载的时候就已经是这样的
这一点也是符合我们上面所说的,但是当你去执行点击事件的时候,你会发现,0.js又被加载了一次,但这一次,加载时间缩短了不少,这样就达到了我们上面的预期,这就是Prefetch
那关于preload呢,其实和prefetch使用方法差不多,之类就不带着大家演示了,其区别在于,PreLoad是和页面主代码一起加载的,这样其实有点不是我们所期望的,但大家也应该知道这个概念
写在最后
本文通过打包分析,发现了打包过程中的性能问题,并通过Prefetch和Preload的方式解决,同时我们也应该注意到,关于页面性能优化,我们不能把希望寄托于浏览器的缓存,应该更去关注代码的利用率。