前端性能优化---首屏加载速度
众所周知,首屏时间加载是页面性能的一个重要指标。下面提供几种优化方案。
路由懒加载
组件不异步引入的时候,打包会生成一个文件,首屏加载资源大小会大,降低用户体验
使用
const route = [{path:"/",name:'home',component:()=>import(/* webpackChunkName: "main" */ "@/views/home/index.vue")},{path:"/",name:'about',component:()=>import(/* webpackChunkName: "about" */ "@/views/about/index.vue")}
]
重点
- import() 函数异步引入组件
- webpack打包后会生成多个js文件,降低首屏加载资源大小
- webpackChunkName 设置异步打包后资源名字,名称相同会合并
组件懒加载
未懒加载前,如进入home页面会将home页所需资源全部加载出来,包括某些操作才会触发的资源 如弹窗
使用
<script>const dialog = ()=>import(/* webpackChunkName: "about" */ "@/components/dialog/index.vue") export default{components:{dialog}}
</script>
重点
- import() 函数异步导入
tree shaking
tree-shaking可以去除无用代码,降低打包体积
使用
未使用的方法就不会被打包
export const func1 = ()=>{console.log('111')
}export const func2 = ()=>{console.log('2222')
}// 不会判断对象里面的方法
export default util {const func1 = ()=>{console.log('111')}const func2 = ()=>{console.log('2222')}
}
重点
- 未使用的会被移除
- 导出 一整个对象中某个方法不被使用,则不移除
骨架屏
使用骨架屏,页面出现内容时间缩短,提高用户体验
使用
spa 单页面 html内容默认只有一个空的
&需加载的jscss文件;使用骨架屏后的html文件中会多出骨架屏的内容
使用后
<div id="app">
<div class="skeleton loading"><div class="header"> </div><div class="content"><h4> </h4><div class="place"></div></div><div class="content"></div>
</div>
</div>
重点
- 骨架屏后获取到html即可给用户呈现内容
长列表虚拟滚动
长列表加载数据过多,渲染时间会增加,可能会造成页面卡顿
使用
只渲染可视区域的列表
const list = [] // 总列表
const totalHeight = list.length * 200;// 假定每个item高度200
const realList = [];
const initNum =Math.floor( document.clientHeight / 200)
realList.push(...list.slice(0,initNum))
window.addEventListener('scroll',()=>{const num = (window.scrollTop + document.clientHeight -realList.length*200)/ 200;realList.push(list.slice(initNum,initNum+num)) // 增加到真实渲染列表中
})
重点
- 监听滚动,判断是否要增加元素到渲染列表中
web-worker优化长任务
浏览器GUI线程和js引擎是互斥的,长任务会造成gui渲染崩溃,影响用户体验
使用
// 会崩溃
let sum = 0;
for (let i = 0; i < 200000; i++) {for (let i = 0; i < 10000; i++) {sum += Math.random()}}// web-worker
// worker.js
onmessage = function (e) {let sum = e.data;for (let i = 0; i < 200000; i++) {for (let i = 0; i < 10000; i++) {sum += Math.random()}}postMessage(sum);}
重点
- 任务的运算时长-通信市场>50ms时,推荐使用web-worker.js
requestAnimationFrame 制作动画
requestAnimationFrame 此方法的刷新频率和显示器的频率保持一致,比settimeout执行动画效果更优秀
使用
window.requestAnimationFrame(()=>{el.style.width ='200px'})
重点
- setTimeout/setInterval 属于 JS引擎,requestAnimationFrame 属于 GUI引擎
- requestAnimationFrame 刷新时间固定
- requestAnimationFrame页面未激活的时候,会暂停; setTimeout/setInterval 不会
js加载方式的合理应用
可以通过script中的中的属性来合理进行js的加载
使用
// 默认 会阻塞dom渲染
<script src="index.js"></script>// async 无顺序的 异步加载 加载完立马执行// js无和dom相关 可使用<script async src="index.js"></script>// defer异步加载 有顺序 domload之后会执行// 一般情况下&控制资源加载顺序时<script defer src="index.js"></script>// type=module 主流现代浏览器,对import的资源发起请求,行为类似defer// 跳过打包编译过程 需浏览器支持原生esmodule模块<script type="module">import { a } from './a.js'</script>// preload 提前加载需要的资源// 浏览器渲染机制之前执行,不会阻塞dom渲染// 加载和执行是分离的 预加载 等需要时执行// vue2默认首屏加载时资源加上preload<link rel="preload" as="script" href="index.js"></link>// prefetch 浏览器空闲时间,加载可能用到的资源// 方便打开其他页面<link rel="prefetch" as="script" href="index.js"></link>
图片优化
图片优化也是页面性能的重要部分,过多过大的图片影响渲染速度
使用
1 图片剪裁
- 图片链接上加上参数,图片服务可能会返回更小的图片
'https://pic.xxx.com/xx.png?w=100&=100''https://wos.xxx.com/xx.png??wimages=/crop/1000x600'
2 图片懒加载
const callback = (entries: any) => {// entries 为 IntersectionObserverEntry对像数组entries.forEach((item: IntersectionObserverEntry) => {if (item.isIntersecting) {imgRef.value.src = props.imgSrc;// 图片加载完停止监听该元素observer.unobserve(item.target);}});
};
3 使用字体图标
- 如iconfont
- 轻量(字体加载,图标就会加载,无http请求)
- 灵活
- 无兼容性问题
4 图片转为base64
- 过小的图片转base64,减少请求
// 安装
npm install url-loader --save-dev// 配置
module.exports = {module: {rules: [{test: /.(png|jpg|gif)$/i,use: [{loader: 'url-loader',options: {// 小于 10kb 的图片转化为 base64limit: 1024 * 10}}]}]}
};
参考文档
1性能优化