众所周知,首屏时间加载是页面性能的一个重要指标。下面提供几种优化方案。
组件不异步引入的时候,打包会生成一个文件,首屏加载资源大小会大,降低用户体验
const route = [
{
path:"/",
name:'home',
component:()=>import(/* webpackChunkName: "main" */ "@/views/home/index.vue")
},
{
path:"/",
name:'about',
component:()=>import(/* webpackChunkName: "about" */ "@/views/about/index.vue")
}
]
未懒加载前,如进入home页面会将home页所需资源全部加载出来,包括某些操作才会触发的资源 如弹窗
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文件中会多出骨架屏的内容
长列表加载数据过多,渲染时间会增加,可能会造成页面卡顿
只渲染可视区域的列表
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)) // 增加到真实渲染列表中
})
浏览器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);
}
requestAnimationFrame 此方法的刷新频率和显示器的频率保持一致,比settimeout执行动画效果更优秀
window.requestAnimationFrame(()=>{
el.style.width ='200px'
})
可以通过script中的中的属性来合理进行js的加载
// 默认 会阻塞dom渲染
// async 无顺序的 异步加载 加载完立马执行
// js无和dom相关 可使用
// defer异步加载 有顺序 domload之后会执行
// 一般情况下&控制资源加载顺序时
// type=module 主流现代浏览器,对import的资源发起请求,行为类似defer
// 跳过打包编译过程 需浏览器支持原生esmodule模块
// preload 提前加载需要的资源
// 浏览器渲染机制之前执行,不会阻塞dom渲染
// 加载和执行是分离的 预加载 等需要时执行
// vue2默认首屏加载时资源加上preload
// prefetch 浏览器空闲时间,加载可能用到的资源
// 方便打开其他页面
图片优化也是页面性能的重要部分,过多过大的图片影响渲染速度
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 使用字体图标
4 图片转为base64
// 安装
npm install url-loader --save-dev
// 配置
module.exports = {
module: {
rules: [{
test: /.(png|jpg|gif)$/i,
use: [{
loader: 'url-loader',
options: {
// 小于 10kb 的图片转化为 base64
limit: 1024 * 10
}
}]
}]
}
};
1性能优化