1. 打包分析
我们需要在使用webpack的时候添加一些配置:
webpack --profile --json > stats.json
这个配置会在打包完成之后生成一个stats.json
文件,这个文件中就包含了一些打包过程和打包结果的很多信息,我们可以借助下面的几个网站来上传该文件并分析:
http://webpack.github.com/analyse/;
http://alexkuz.github.io/webpack-chart/;
这里我推荐使用Webpack Bundle Analyzer
npm install --save-dev webpack-bundle-analyzer
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
2. Preload,Prefetch
在我们之前学习的webpack Code Splitting的配置中,我们知道了splitChunks: { chunks: 'async'}
中chunks的默认选项就是async,也就是webpack默认只会对异步的模块进行代码分割。通过后文的分析,我们知道,同步导入的模块并不一定会提高用户第一次访问时的加载速度。接下来我们再看看这一段代码:
//inde.js
document.addEventListener('click',()=>{
var ele = document.createElement('div')
ele.innerHTML = "Niall August"
document.body.appendChild(ele)
})
打包后,打开网页文件,查看浏览器devtools的coverage:
我们发现main.js
的使用率为77.9%,查看代码我们发现:
中间的红色部分表示的是没有使用到的代码。当我们点击之后:
这时候,这段代码才发挥了它的作用。
这一段我们导入的代码,在页面没有被点击之前,其实都是没有存在的意义的,用户在没有点击之前,不需要这一段代码,但是这里却加载了这段代码,也就是增加了用户访问网站时的网络负荷。所以,我们采取异步导入模块的方法,而这,才能真正提高用户的访问体验。
修改代码如下:
//index.js
document.addEventListener('click',()=>{
import('./async').then(({default: func})=>{
func()
})
})
//async.js
module.exports = dosomething = ()=>{
var ele = document.createElement('div')
ele.innerHTML = "Niall August"
document.body.appendChild(ele)
}
现在我们再看看coverage:
在我们没有点击页面之前,利用率从77.9%提升到了79.4%,而这仅仅是一个小小的测试,当我们在项目合理使用异步引入,这将是很好地性能提升。这也是为什么webpack默认只对异步导入的模块进行代码分割的原因。
在我们进入segmentfault社区的时候,上图中的登录注册弹窗是否需要一并加载呢?
如果用户不点击登录注册按钮,这个弹窗就不会出现,所以,理想情况下,用户在加载页面的时候并不需要加载这个弹窗所需要的代码,而在用户点击登录注册按钮的时候,这部分代码再被加载。
看到这里,我们可能会有疑问,如果此弹窗的代码文件较大,那么按照上面的加载方式可能会导致用户在使用过程中等待,这种情况下,不就会弊大于利了吗?
当页面被加载完毕之后,网络带宽得到了释放,此时网络就是空闲状态,那么,我们可不可以在空闲状态下加载弹窗这一类的代码,而不是在点击按钮之后再去下载?
这时候,就是Prefetching的用武之地了!
修改代码如下:
document.addEventListener('click',()=>{
import(/* webpackPrefetch:true */'./async').then(({default: func})=>{
func()
})
})
这个注释/* webpackPrefetch:true */
就能使异步模块在网络空闲的时候能够被预先加赞。
那Preload又有什么用呢?
preload表示用户十分有可能需要在当前浏览中加载目标资源,所以浏览器必须预先获取和缓存对应资源。
这样看来:
preload主要用于预加载当前页面需要的资源;而prefetch主要用于加载将来页面可能需要的资源;
preload的特点:
- preload加载的资源是在浏览器渲染机制之前进行处理的,并且不会阻塞onload事件;
- preload可以支持加载多种类型的资源,并且可以加载跨域资源;
- preload加载的js脚本其加载和执行的过程是分离的。即preload会预加载相应的脚本代码,待到需要时自行调用;