我们总是在想,如何让一些代码先不加载,而是先让核心代码加载,让用户能够快速的看到主页代码,而像一些事件按钮、其他页面通过某些操作再进行加载,或者在浏览器休息时候再进行加载呢!这里我们讲了三种方法去让代码优化。本节还介绍一些打包代码的工具,能够更好的去分析代码,然后去分析代码的使用情况,然后找一个最优的解决办法,使代码找到一个平衡点。
一、二节工具介绍,三节、懒加载,四节、preload与Prefetch
一、打包后代码的分析
我们会对打包的过程做分析,分析步骤:
1.先在package.json里面的script上面写上这个,--profile --json > stats.json,如下面所示:
打包会生成一个stats.json的文件
2.然后Install
# NPM
npm install --save-dev webpack-bundle-analyzer
# Yarn
yarn add -D webpack-bundle-analyzer
3.然后Usage (as a plugin)
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
module.exports = {
plugins: [
new BundleAnalyzerPlugin()
]
}
打包就会生成下面一样的图片:
里面会包含着各种打包的内容,包括依赖包文件等等,这个可以帮助我们分析哪些东西需要做进一步的优化。
这个模块会帮助你:
- 了解你的包里真正有什么东西。
- 找出什么模块构成最大的大小。
- 找出错误打包的模块文件。
- 通过这个我们可以让我们的打包文件达到最优。
在vue-cli4 以后需要使用在vue.config.js中配置,配置如下
/* vue.config.js */
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
const isPro = process.env.NODE_ENV === 'production'
module.exports = {
...
configureWebpack: config => {
if (isPro) {
return {
plugins: [
// 使用包分析工具
new BundleAnalyzerPlugin()
]
}
}
},
...
}
然后在 http://127.0.0.1:8888/查看
二、查看代码的利用率
首先,我们介绍一种浏览器的工具使用:
我们打开浏览器控制台,然后ctrl + shift + p,输入showCover,然后出现下面这个界面:
然后点击上图黑色按钮:如下图,就会出现代码利用率的景象。
我们可以用这个来查看代码的利用率情况,这也是我们经常用来研究页面性能常用的工具。以后我们可以用代码覆盖率去优化我们的性能,而不是讲如何去做缓存了。
三、webpack中的懒加载
- 懒加载,也称为按需加载,是一种可以提高网站初始响应速度的方式。
- 在网站初次加载时,并不会加载全部代码,而是当用户完成某些特定操作后,才会引用新的代码块。
安装依赖:
"webpack": "^4.42.0",
"webpack-cli": "^3.3.11",
"lodash": "^4.17.15"
文件结构:
+ node_modules
+ src
- index.js
+ dist
- index.html
入口文件代码index.js:
import _ from 'lodash';
function getComponent() {
var element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
return element;
}
document.addEventListener('click', () => {
var element = getComponent();
document.body.appendChild(element);
})
问题1:上面这种方法会很早的将getComponent()加载到页面中,如果代码一多就会造成卡顿的情况,如果是在首页加载,可能会造成白屏的状况,用户体验贼差,我们可以用懒加载(按需加载)的方式,也就是异步加载代码(需要异步的方法)的形式
懒加载的案例代码1:
setTimeout(()=>{
// 也是一个chunk.js,加载后会是一个带数字的js文件
import('./xxx.js').then(res => {
// res就是import返回的数据
console.log(res.data.message)
})
}, 1500);
也可以让用户需要的时候再加载。
懒加载的案例代码2:
import _ from 'lodash';
//async返回的是一个promise对象
async function getComponent() {
const _ = await import('lodash');
var element = document.createElement('div');
element.innerHTML = _.join(['Hello', 'webpack'], ' ');
// 返回值做为resolve的参数
return element;
}
// 懒加载
document.addEventListener('click', () => {
// element就是上面return的资源
getComponent().then((element) => {
document.body.appendChild(element);
})
})
因为 lodash 模块仅在 getComponent 函数中使用,而 getComponent 函数仅在 click 事件后执行所以我们可以将加载 lodash 模块的代码放在 getComponent 函数当中这样,只有在发生点击事件之后,才会去加载 lodash 模块,从而达到按需加载的效果。
我们也可以从下图中可以看到,在打开也买你中先不加载代码,而是在点击时候加载代码,从而提高代码的利用率。
问题2:懒加载是好的,但是当点击按钮时候或者每隔一段时间,才能下载相应页面的js文件,这就导致体验极其不好,每一次点击访问新页面都要等待js文件下载,然后再去请求接口获取数据。频繁出现loading动画的体验真的不好。那么我们可以使用prefetch方式,让代码在空闲时候加载出来,而不是点击某个按钮或者延迟时间。
四、webpack中prefetch
我们在想,有没有一种方式让代码第一次加载时候就能达到最优,而不是利用缓存或是点击按钮时候下次加载才能提高访问的速度。
比如说下面这段代码:
// click.js
function handleClick() {
const element = document.createElement('div');
element.innerHTML = 'hansen';
document.body.appendChild(element)
}
export default handleClick;
// index1.js
document.addEventListener('click', ()=>{
import('./click.js').then(({default: func}) =>{
func()
})
})
当点击document时候,实现异步加载,这种方式可以让一些代码可以慢点加载,在需要使用的时候再进行加载,这也是我们说的但是也会出现一个问题,比如,我们在使用vue做单页面开发时候,由于单页面应用页面过多,可能会导致代码体积过大,从而使得首页打开速度过慢。所以切分代码,优化首屏打开速度尤为重要。
所以如果我们在进入首页后,在浏览器的空闲时间提前下好用户可能会点击页面的js文件,这样首屏的js文件大小得到了控制,而且再点击新页面的时候,相关的js文件已经下载好了,就不再会出现loading动画。
所以我们引入了prefetch,让文件可以在空闲时候加载,具体方法如下:在模块里面添加魔法注释/* webpackPrefetch: true */
// index1.js
document.addEventListener('click', ()=>{
import(/* webpackPrefetch: true */'./click.js').then(({default: func}) =>{
func()
})
})
这样子,0.js会在空闲时候被加载,注意:0.js只是被加载,没有被利用。
当点击document时候,0.js被加载出来,他只需要1ms钟了,是不是更快了呢。
说到了这里应该就结束了吧,小伙伴会问,Proload还没说呢!哈哈,你们可细心,那这里就介绍下proload,Preload是和父级元素并行加载的,可以被立即使用,通常用于本页面要用到的关键资源。如果使用webpack打包,他也是通过在import模块中添加魔法注释就可以了,像这样子/* webpackPreload: true */。其实有时候,我们可以直接将preload和prefetch用于link标签使用。
附加:
我们可以把Preload和Prefetch直接写在link标签上:
1.Preload
<link rel=“preload”>
preload 提供了一种声明式的命令,让浏览器提前加载指定资源(加载后并不执行),需要执行时再执行
这样做的好处在于:
- 将加载和执行分离开,不阻塞渲染和document的onload事件
- 提前加载指定资源,不再出现依赖的font字体隔了一段时间才刷出的情况
preload通常用于本页面要用到的关键资源,包括关键js、字体、css文件。preload将会把资源得下载顺序权重提高,使得关键数据提前下载好,优化页面打开速度。
2.prefetch
<link rel=“prefetch”>
这段代码告诉浏览器,这段资源将会在未来某个导航或者功能要用到,但是本资源的下载顺序权重比较低。也就是说prefetch通常用于加速下一次导航,而不是本次的,比如下一个页面会用到的资源,点击事件后弹出model框等等。
被标记为prefetch的资源,将会被浏览器在空闲时间加载。
Preload和Prefetch的区别:
下面是Preload和Prefetch的区别吧:
- 一个预加载块(preload)开始与父块并行加载。预取的块(prefetch)在父块完成加载后启动。
- 预加载块(preload)具有中等优先级,可以立即下载。而预取块(prefetch)在浏览器空闲时下载预取的块。
- 一个预加载的块(preload)应该被父块立即请求。预取的块(prefetch)可以在将来的任何时候使用。
- 浏览器的支持能力是不同的。
虽然说prefetch或者是preload好,但是我们千万要记得,不要所有的异步加载模块都使用这个东西,我们应该根据自己的业务去加载,否则页面性能不是达到最优而是长时间的等待加载。
总结:
不管懒加载还是预加载,只有适合自己,适合业务的才是最好的!