前端性能优化思路
一、网络性能优化
1、网络请求个数优化
a)异步引用资源
i).vue文件中
defineAsyncComponent(() => import("vue文件地址"))
ii).js/.ts文件中
- import()异步加载
- 2、import.meta.glob("地址",{eager:false})
- 3、vue-router中的component自带defineAsyncComponent解析功能,可以直接传入import()
b) 异步插入
i)插入script:通过onMounted调用函数,函数中判断当前script中是否存在指定资源的url,存在则不请求,不存在则动态插入script
ii)插入link css:与插入script相同
c)文件优化
i)上传功能优化
- 上传队列控制
/**
* @class QueueLoader
* @classdesc 图片加载队列
*/
export class QueueLoader {
// 私有静态实例,用于实现单例模式
private static instance: QueueLoader;
// 任务队列,存储回调函数
private taskQueue: Array<() => Promise<boolean>> = [];
// 当前活跃任务数
private activeTasks: number = 0;
// 最大并发请求数
private maxConcurrentRequests: number = 4;
// 私有构造函数,防止实例化
private constructor() {}
/**
* 获取单例实例的方法
* @returns {QueueLoader} 单例的 QueueLoader 实例
*/
public static getInstance(): QueueLoader {
if (!QueueLoader.instance) {
QueueLoader.instance = new QueueLoader();
}
return QueueLoader.instance;
}
/**
* 向任务队列添加任务
* @param {() => Promise<boolean>} callback - 包含回调函数的任务
* @returns {void}
*/
public addTask(callback: () => Promise<boolean>): void {
this.taskQueue.push(callback);
this.runTasks();
}
/**
* 执行任务队列中的任务
* @returns {Promise<void>} 返回一个表示任务执行完成的 Promise
*/
private async runTasks(): Promise<void> {
while (this.activeTasks < this.maxConcurrentRequests && this.taskQueue.length > 0) {
const task = this.taskQueue.shift()!;
this.activeTasks++;
const result = await task();
this.activeTasks--;
if (result) {
this.runTasks();
}
}
}
}
- 文件切片上传 eg:参考广告机 加载功能优化 1、预加载 a)通过link preload预加载文件
b)通过script async/defer独立下载文档和解析
<script async></script>
<script defer></script>
c)通过symbol处理icon的复用和可维护
<svg aria-hidden="true" style="position: absolute; width: 0px; height: 0px; overflow: hidden;">
<symbol id="icon-keliu" viewBox="0 0 1024 1024">
<path d=""></path>
</symbol></svg>
d)在内容快要出现在浏览器窗口中时预先加载src资源 2、懒加载 a)当内容出现在浏览器窗口时才加载资源 eg:
<img loading="eager" /> <!-- 立即加载 -->
<img loading="lazy" /> <!-- 懒加载 -->
2、网络请求资源大小优化 d)分包
// 控制node_modules分包
manualChunks(id: string | string[]) {
if (id.indexOf("node_modules") != -1) {
return id.toString().split("node_modules/")[1].split("/")[0].toString();
}
}
//控制src目录下的资源分包
chunkFileNames: (chunkInfo) => {
if (chunkInfo.facadeModuleId?.indexOf("src") != -1) {
return "assets/[name]-[hash].js";
}
return "[name]-[hash].js";
}
// 控制资源名称和目录
assetFileNames: (chunkInfo:any)=> {
return '[name]-[hash].[ext]'
}
e)切片 使用ajax请求+ArrayBuffer加载大文件显示 i)文件上传切片 一般用于上传文件 ii)文件加载切片 一般用于加载大文件,例如:Threejs加载大模型控制加载队列 3、首页优化 f)index.html中不写script立即加载请求 g)加载动效 h)减少请求个数,参照1、网络请求个数优化 i)网络请求资源大小优化,参照2 4、页面加载和性能 j)watch监听过多/切换页面未卸载 5、GZIP/Brotli压缩优化
vitePluginCompress({
verbose: true, //是否开启gzip压缩
disable: false,
deleteOriginFile: false,
threshold: maxSplitFile,
algorithm: "gzip",
ext: ".gz",
})
二、打包性能优化思路
1、src目录打包分包
2、node_modules打包分包
三、排查优化思路
加载需要优化的重点:
- 页面加载时长:超过1秒
- 网络请求文件时间:超过1秒
- 网络请求个数:列表页超过15个、首页超过20个【非绝对指标,具体看页面功能】
- CPU使用情况长时间占用
- 页面切换后JSdom和堆长时间未卸载
- 警告过多/错误未处理
- 初次加载/每一次切换tab和页面都有多个相同请求
1、搜集每个页面/弹窗的情况和统计,针对情况进行优化
a)统计页面网络请求个数、请求资源大小、过大文件请求时长、总渲染时间和加载时间
b)统计哪些页面的按钮没有使用loading,导致用户可以频繁点击
c)相同网络请求可以重复频繁发送
2、排查【1】中每个指标哪些可以优化,特别标记页面以及对应的功能
3、排查方法
chrome检查 -> 网络
chrome检查->更多->性能监视器