原文见:语雀(https://www.yuque.com/deepstates/interview/xtt59x)
● 性能指标
● 分析工具
● 优化方式
○ 加载
○ 渲染
● 专题优化
○ 技术栈:react
○ 浏览器
○ 打包工具:webpack
● 项目
⭐️⭐️⭐️ 相关知识点参考:
性能指标
首屏和白屏时间如何计算?
一、首屏时间的计算,可以由 Native WebView 提供的类似 onload 的方法实现,在 ios 下对应的是 webViewDidFinishLoad,在 android 下对应的是onPageFinished事件。
二、白屏的定义有多种。可以认为“没有任何内容”是白屏,可以认为“网络或服务异常”是白屏,可以认为“数据加载中”是白屏,可以认为“图片加载不出来”是白屏。场景不同,白屏的计算方式就不相同。
方法1:当页面的元素数小于x时,则认为页面白屏。比如“没有任何内容”,可以获取页面的DOM节点数,判断DOM节点数少于某个阈值X,则认为白屏。
方法2:当页面出现业务定义的错误码时,则认为是白屏。比如“网络或服务异常”。
方法3:当页面出现业务定义的特征值时,则认为是白屏。比如“数据加载中”。
如何优化
优化方式
提升页面性能的方法有哪些?
一、加载页面和静态资源
1、静态资源压缩合并,减少http请求。
(1)减少http请求数量
(2)减少请求资源大小
2、非核心代码异步加载。
3、静态资源缓存:通过链接名称控制缓存,只有内容改变的时候,链接名称才会改变。
4、利用浏览器缓存
5、使用cdn让资源加载更快
6、预解析dns
7、使用ssr后端渲染,数据直接输出到html中(ssr:server site render)
二、页面渲染
1、css、js及放置位置
(1)尽量避免在HTML标签中写style属性
(2)css放前面,js放后面。
(3)避免使用CSS Expression
2、图片
(1)避免图片和iFrame等的空Src。空Src会重新加载当前页面,影响速度和效率
(2)懒加载(图片懒加载,下拉加载更多)
3、dom操作
(1)减少dom查询,对dom查询做缓存。
// 未缓存dom查询
var i;
for (i = 0; i < document.getElementsByTagName(‘p’).length; i++) {
// todo
}
// 缓存了dom查询
var pList = document.getElementByTagName(‘p’);
var i;
for (i = 0; i < pList.length; i++) {
// todo
}
(2)减少dom操作,多个操作尽量合并在一起执行。
var frag = document.createDocumentFragment(); // 片段,循环插入dom,改成先插入到片段,再append到文档流
(3)用innerHTML代替DOM操作,减少DOM操作次数,优化javascript性能
4、事件
(1)尽早执行操作(如DOMContentLoaded)
(2)事件节流
var textarea = document.getElementById(‘text’);
var timeoutId;
textarea.addEventListener(‘keyup’, function() {
if(timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(function() {
// 触发change事件
}, 100)
})
5、代码细节优化
(1)用hash-table来优化查找
(2)多个变量声明合并
(3)少用全局变量
(4)避免全局查询
(5)避免使用with(with会创建自己的作用域,会增加作用域链长度)
(6)用setTimeout来避免页面失去响应
三、移动端性能优化
1、css
(1)不滥用Float。Float在渲染时计算量比较大,尽量减少使用
(2)不滥用Web字体。Web字体需要下载,解析,重绘当前页面,尽量减少使用。
(3)避免使用css3渐变阴影效果。
2、css动画
(1)尽量使用css3动画,开启硬件加速。
可以用transform: translateZ(0)来开启硬件加速。
CSS中的属性(CSS3 transitions、CSS3 3D transforms、Opacity、Canvas、WebGL、Video)会触发GPU渲染,请合理使用。过渡使用会引发手机过耗电增加
3、合理使用requestAnimationFrame动画代替setTimeout
4、适当使用touch事件代替click事件。
你有用过哪些前端性能优化的方法?
加载
预解析dns
预解析dns的方式?
1、
2、强制打开a标签的dns预解析
页面中所有a标签,默认打开了dns预解析,如果链接是https开头的,默认关闭dns预解析
非核心代码异步加载
异步加载的方式?
1、动态脚本加载
script标签,加入到body中
2、defer
加载js的时候,script标签加defer和async
3、async
异步加载的区别?
1、defer是在html解析完之后才会执行,如果是多个,按照加载的顺序依次进行。
2、async是在加载完之后立即执行,如果是多个,执行顺序和加载顺序无关。
渲染
什么是防抖和节流?有什么区别?如何实现??
防抖
触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
思路:
每次触发事件时都取消之前的延时调用方法
function debounce(fn) {
let timeout = null; // 创建一个标记用来存放定时器的返回值
return function () {
clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
fn.apply(this, arguments);
}, 500);
};
}
function sayHi() {
console.log(‘防抖成功’);
}
var inp = document.getElementById(‘inp’);
inp.addEventListener(‘input’, debounce(sayHi)); // 防抖
节流
高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
思路:
每次触发事件时都判断当前是否有等待执行的延时函数
function throttle(fn) {
let canRun = true; // 通过闭包保存一个标记
return function () {
if (!canRun) return; // 在函数开头判断标记是否为true,不为true则return
canRun = false; // 立即设置为false
setTimeout(() => { // 将外部传入的函数的执行放在setTimeout中
fn.apply(this, arguments);
// 最后在setTimeout执行完毕后再把标记设置为true(关键)表示可以执行下一次循环了。当定时器没有执行的时候标记永远是false,在开头被return掉
canRun = true;
}, 500);
};
}
function sayHi(e) {
console.log(e.target.innerWidth, e.target.innerHeight);
}
window.addEventListener(‘resize’, throttle(sayHi));
图片优化
一个页面上有大量的图片(大型电商网站),加载很慢,你有哪些方法优化这些图片的加载,给用户更好的体验 ?
● 图片懒加载,在页面上的未可视区域可以添加一个滚动条事件,判断图片位置与浏览器顶端 的距离与页面的距离,如果前者小于后者,优先加载。
● 如果为幻灯片、相册等,可以使用图片预加载技术,将当前展示图片的前一张和后一张优先 下载。
● 如果图片为 css 图片,可以使用 CSSsprite,SVGsprite,Iconfont、Base64 等技术。 如果图片过大,可以使用特殊编码的图片,加载时会先加载一张压缩的特别厉害的缩略图, 以提高用户体验。
● 如果图片展示区域小于图片的真实大小,则因在服务器端根据业务需要先行进行图片压缩, 图片压缩后大小与展示一致。
优化专题
技术栈
react
浏览器
针对浏览器做的优化?(阿里)
需要了解浏览器相关的原理,如缓存/存储、代理、SSR等
针对渲染引擎的工作内容想到的优化,如css解析会影响dom渲染、合成优化减少回流重绘、web worker、event loop等
打包工具
webpack
请求优化
项目
项目性能优化?
● 技术栈
● 浏览器
● 打包工具
● 针对具体的页面做了哪些优化,比如首页该做什么,首页最新指标
● 应用场景,项目中用到了哪些方法
● 针对中等项目、大型项目的性能选择