性能优化
面试?现在的环境我哪来的面试, 我只是个标题狗罢了!
performance
性能优化要结合性能分析来说。 可以通过 performance 选项卡先对项目进行分析。
-
network
- 如有加载耗时文件, 像vue elementUI,或者地图geojson文件 可以放cdn静态资源加速(这里可能会问为什么会加速,还会牵扯到一个知识点,公司搭建npm私服,不知道这个就赶紧说完.别给面试官机会)在vite/webpack 配置 externals打包排除。
- 对于不重要的资源可以配置prefetch,让浏览器在空闲时间去加载,(如图片,视频, 其他非当前页面资源), 毕竟浏览器网络请求一次最多加载6个。 减少网络传输也可以提高页面加载 当然对于关键资源, 也可以加preload进行预加载。
- ask: prefetch和preload作用区别?prefetch,preload
- preload 预加载: 加载资源一般是当前页面需要的
- prefetch 预读取: 一般是其它页面有可能用到的资源。
- ask: prefetch和preload作用区别?prefetch,preload
- 顺口也可以说一下,目前像vue项目都会给打包之后的script标签增加defer属性, 让js本会在 HTML 文档完全解析完毕后执行 (毕竟说的越多显得你越吊)。
- ask:script标签的 defer属性和async属性作用和区别 , defer和async
- defer属性用于延迟加载脚本。这意味着浏览器会立即开始下载脚本,但不会阻塞 HTML 的解析。
- async 属性用于异步加载脚本。这意味着浏览器会立即开始下载脚本,而不会阻塞 HTML 的解析。
- ask:script标签的 defer属性和async属性作用和区别 , defer和async
-
frames
- 就是页面展示帧截图, 我也不知道有什么可以说的. 可以说页面的渲染帧16.666ms. 默认情况下 60fps 就是1秒刷新60次, 渲染帧就是 1 / 60 ≈ 16.67
-
animation
-
这里是动画,卡了就禁用吧, 优化的话。 可以适当的说使用GPU 渲染, css有几个属性可以开启GPU 渲染, will-change、 transform、opacity、filter (光栅化) 这里可能会问cpu, gpu 的区别, 不会也要赶紧跑. cpu,gpu详解,
-
ask: 为什么要用transform, 直接用transition修改width, height . 不也可以生成动画吗. 强制改变宽高会引起重绘还是回流?
-
修改元素的布局,几何属性会导致页面回流
-
修改不影响样式布局的属性会发生重绘
-
image that
在一片沙滩(干的沙子)斜坡上, 你从上到下写了个A,B,C。你现在要改变沙B(中间一个)的颜色, 你直接一个喷漆, 哇: 绿了。对吧, 你重绘了,而且只影响了沙B, 即元素本身。
所以你说:沙A,沙C没变(重绘不会导致回流)。
但是你情种劲犯了:你拍了个照片发给你女朋友看,女朋友回你一句大煞笔。你思索片刻,得出结论, 你女朋友觉得这个沙B画大了一点。你就两只手按住了沙B的两端, 往中间挤了挤。沙B变小了。但是上面的沙A会流淌下来,沙C的位置也发生一点变化
这个时候你说:沙A,沙C也动了呀(你改变了元素的几何属性,导致了页面回流, 重排一般也会导致重绘,嗯。有点道理。)
-
-
ask: 什么是重绘, 什么是回流. 有什么对应关系
重绘: 在浏览器重新绘制网页以显示由 UI 更改引起的视觉更新时发生,例如在交互式站点上进行更新后。这通常是在重排之后发生的,重排是浏览器重新计算网页的某些部分的位置和几何形状。
回流:mdn叫重排,发生在浏览器重新计算网页的某些部分的位置和几何形状时(例如在交互式站点更新后)。这通常会紧接着重绘(repaint),即浏览器重新绘制网页以显示更新后的视觉效果。
-
-
拔高:利用 requestAnimationFrame 执行动画。requestAnimationFrame
-
-
timings
-
这里就是关键指标的加载, 不展开了
- LCP - largest Contentful Paint
- CLS - Cumulative Layout Shift
- INP - Interaction to Next Paint
-
ask: 网页如何获取这些指标? (直接上代码吧)
const timing = performance.timing; // 1. 白屏时间(First Paint) const firstPaint = performance.getEntriesByName('first-paint')[0]?.startTime; console.log('白屏时间 (First Paint):', firstPaint !== undefined ? `${firstPaint.toFixed(2)} ms` : '未记录'); // 2. 首屏时间(First Contentful Paint, FCP) const firstContentfulPaint = performance.getEntriesByName('first-contentful-paint')[0]?.startTime; console.log('首屏时间 (First Contentful Paint, FCP):', firstContentfulPaint !== undefined ? `${firstContentfulPaint.toFixed(2)} ms` : '未记录'); // 3. 用户可交互时间(Time to Interactive, TTI) const timeToInteractive = timing.domInteractive - timing.navigationStart; console.log('用户可交互时间 (Time to Interactive, TTI):', timeToInteractive !== undefined ? `${timeToInteractive.toFixed(2)} ms` : '未记录'); // 4. 页面完全加载时间(Load Event End) const loadTime = timing.loadEventEnd - timing.navigationStart; console.log('页面完全加载时间 (Load Event End):', loadTime !== undefined ? `${loadTime.toFixed(2)} ms` : '未记录'); // 5. CLS, LCP, FID, INP, FCP 指标通过 Web Vitals 获取 // CLS (Cumulative Layout Shift) onCLS((metric) => { console.log('累积布局偏移 (CLS):', metric.value !== undefined ? `${metric.value.toFixed(2)}` : '未记录'); }); // LCP (Largest Contentful Paint) onLCP((metric) => { console.log('最大内容绘制时间 (LCP):', metric.value !== undefined ? `${metric.value.toFixed(2)} ms` : '未记录'); }); // FID (First Input Delay) onFID((metric) => { console.log('首输入延迟 (FID):', metric.value !== undefined ? `${metric.value.toFixed(2)} ms` : '未记录'); }); // INP (Input Delay) onINP((metric) => { console.log('用户输入延迟 (INP):', metric.value !== undefined ? `${metric.value.toFixed(2)} ms` : '未记录'); }); // FCP (First Contentful Paint) onFCP((metric) => { console.log('首屏内容绘制时间 (FCP):', metric.value !== undefined ? `${metric.value.toFixed(2)} ms` : '未记录'); }); // TTFB (Time to First Byte) 需要使用 Performance API 直接获取 const ttfb = performance.getEntriesByType('navigation')[0]?.responseStart - performance.timing.navigationStart; console.log('首字节时间 (TTFB):', ttfb !== undefined ? `${ttfb.toFixed(2)} ms` : '未记录');
-
-
Main
-
火焰图,性能优化的关键,也是放大镜找屎入口。这里越红,你代码越臭。
-
找到红色部分, long task。
点击查看summary, 先看总结, 到底是哪部分出了问题,如果是Scripting ,进入call tree 去一点点往下找找到你可以改的代码,观察一下是否是写的不合理, 由于现在框架的发展。 这里一般都不会有太多问题或者说太多能改的问题。
这里也可以说利用requestIdleCallback 执行耗时任务。requestIdleCallback
treeshaking 进行树摇打包去除无用的死代码.(对于一些全局引入的插件很有用, vite已经默认启用treeshaking)
...这里可以说的太多了, 有兴趣的看着补充吧
-
lighthouse
- 用来生成性能分析报告, 记录关键指标
-
Performance
-
Accessibility
-
Best Practices
-
SEO
不敢问,暂时没研究太多。。。
Performance monitor
- 运行时性能检测,打开控制台 ctrl + shift + p, 搜索一下 performance monitor就可以出来了。
- cpu usage。 cpu使用率, 看看你的网页消耗多少算力cpu一直居高不下, 很大概率就是过了一会你的网页就出现 “哎哟,崩溃了~”。
- js heap size。 可以检测运行时你的内存有没有泄露。 观察曲线走势, 和数字。 是否一致增加, 是的话就要检测代码中存在内存泄漏的地方了
- Dom Nodes , 可以检测游离节点是否一致增加。
- Js event listeners, 监听事件个数(游离节点多了, 可能也会导致这个变多)
- Documens
- Document Frames
- Layout /sec 应该是每秒的偏移量。 猜测跟指标 CLS 有点类似
- Style recalcs / sec。。。