各位前端小伙伴们!新的一年那大幕已经 “哗啦” 一声拉开啦,年初这阵儿啊,项目上就跟刚松了绑似的,相对宽松得很。这时候,我猜不少小伙伴眼睛都放光了,瞅准了传说中的 “金三银四” 跳槽黄金档。
咱都知道,现在前端面试啊,翻来覆去就那几个常见问题,都快被大家念叨成 “八股文” 了。好多人就寻思着,把答案背得滚瓜烂熟,不就能一路绿灯、顺风顺水啦?嘿,您要是这么想,可就太天真咯!这面试的门道啊,深着呢,哪有那么容易。到底咋回答,才能在面试官那儿 “哐哐” 拿高分,一下子就脱颖而出,成全场最靓的仔呢?巧了,我最近也没闲着,正在面试新同学呢,今儿就给大伙透个底,让大家瞅瞅面试官到底想听啥样的答案。
问题:前端如何做性能优化?
这道题不说100%,也有90%会遇到,而且会有好多种变体:如何做白屏优化?如何做卡顿优化?大部分人是怎么回答的呢?
常规回答
- 减少Http请求
- 文件压缩
- 图片精灵
- 浏览器缓存
- 使用CDN
- 使用异步函数
- 优化dom结构
- ...
相信这些答案大家都见过,太多我就不列举了,而且GPT回答的也是这一套,回答了这些其实仅仅是代表你了解过,并不代表你有过思考。
加分的回答
其实如果你答的好,这道题完全可以体现出你的前端水平。 思考问题,要有大局观,说白了,web前端就是加载H5页面的一个过程,所以你应该从页面加载的角度来回答。 一个页面加载过程是什么样的呢?
- DNS解析
- 建立连接
- 发送HTTP请求
- 服务器响应
- 浏览器渲染
- 执行脚本
- 加载其他资源
我们可以细分从每一步进行优化。
DNS解析怎么优化?
- DNS 预解析:通过在 HTML 中添加
<link rel="dns-prefetch" href="//example.com">标签,浏览器可提前对指定域名进行 DNS 解析,为后续请求节省时间。 - 控制域名数量:将资源尽量放置在同一个域名下,减少 DNS 查询次数。每一次 DNS 查询都需要消耗一定时间,减少查询次数能显著加快整体加载速度。
- 使用 CDN:CDN 服务器可根据用户地址提前分发节点。在解析时,用户能从最近的节点获取资源,大大缩短解析时间与传输距离。
- 利用 DNS 缓存:合理设置并延长 DNS 缓存的生效时间,避免重复解析已缓存的域名,提高解析效率。
建立连接怎么优化?
- 避免重定向:每次重定向都意味着需要重新建立连接,这会耗费额外的时间与资源。在设计网站架构与 URL 时,应尽量避免不必要的重定向。
- 网址预链接:使用
<link rel="preconnect" href="//example.com">标签,让浏览器提前与指定域名建立连接,当实际请求到来时,能快速进行数据传输。 - 采用新版本协议:HTTP2.0 和 3.0 版本支持多路复用,允许在同一个连接中同时处理多个请求和响应,降低了建立连接的成本,提高了传输效率。
发送HTTP请求怎么优化?
- 减少请求数量:合并多个小的请求为一个大请求,例如将多个 CSS 文件或 JavaScript 文件合并成一个文件进行请求,减少网络请求的开销。
- 巧用浏览器缓存:对于静态资源,合理设置缓存策略,确保浏览器在后续访问时能直接从本地缓存读取,减少重复请求。
- 延迟加载:对于一些非关键的 JavaScript 脚本、图片等资源,采用延迟加载技术,在页面主要内容加载完成后再进行加载,避免占用初始传输资源,加快页面首屏加载速度。
服务器响应怎么优化?
- 内容压缩:对服务器返回的 JavaScript 代码、CSS 样式表等内容进行压缩,减少传输的数据量,从而加快传输速度。
- 分担服务器计算:将部分不涉及安全问题的逻辑从服务器转移到前端进行计算,减轻服务器的负担,使其能更快地响应请求。
浏览器渲染怎么优化?
- 语义化标签使用:使用语义化的 HTML 标签,如
<header>、<nav>、<main>等,有助于浏览器更好地理解页面结构,提高渲染效率,同时也有利于搜索引擎优化。 - 减少重绘与重排:尽量避免频繁修改会导致重绘(repaint)和重排(reflow)的元素属性,如布局属性、样式属性等。若需修改多个属性,可通过一次性修改或使用 CSS 类切换来减少重绘与重排的次数。
- DOM 渲染优化:采用组件懒加载和动态加载技术,仅在需要时才渲染相关的 DOM 元素,减少初始渲染的工作量。
- CSS 动画优先:在实现动画效果时,优先使用 CSS 动画而非 JavaScript 动画。CSS 动画由浏览器的渲染引擎直接处理,性能更优。
- 精简 CSS:减少多层嵌套的 CSS 规则,简化样式表,降低浏览器解析和计算样式的复杂度。
- GPU 加速:对于一些需要频繁更新的元素,如动画元素,可通过设置特定的 CSS 属性(如
transform和opacity)来启动 GPU 加速,提高渲染性能。 - 避免昂贵属性:尽量减少使用如
box-shadow、filter等对性能影响较大的 CSS 属性,这些属性在计算和渲染时会消耗较多资源。 - 骨架屏应用:在页面数据加载完成前,展示骨架屏,给用户一种页面正在快速加载的视觉反馈,提升用户体验。
执行脚本怎么优化?
- 变量作用域优化:使用局部变量代替全局变量,减少变量查找的时间复杂度,提高脚本执行效率。全局变量的查找需要在整个全局作用域中进行,而局部变量的查找范围更小。
- 控制循环使用:减少不必要的循环操作,避免在循环中执行复杂的计算或频繁的 DOM 操作。如果必须使用循环,可考虑优化循环条件和内部逻辑。
- 关注垃圾回收:确保及时释放不再使用的变量和对象,让 JavaScript 的垃圾回收机制能够高效工作,避免内存泄漏和性能下降。
- 计时器管理:在使用完计时器(如
setTimeout和setInterval)后,记得及时销毁,防止计时器持续运行占用资源。 - 避免递归深度问题:在使用递归函数时,注意控制递归深度,避免因深度调用导致栈溢出,影响脚本执行。
- 异步处理非关键代码:对于一些非重要的代码逻辑,采用异步处理方式,如使用
Promise、async/await等,避免阻塞主线程,保证页面的流畅性。 - 代码去重:消除重复的代码片段,减少代码体积,提高执行效率。重复代码不仅增加了脚本的大小,还可能导致重复计算。
- 减少类型转换:避免频繁进行数据类型转换,如从
string转为number。类型转换会消耗一定的计算资源,尽量在数据输入时就确保其类型的正确性。
加载其他资源怎么优化?
- 图片精灵技术:将多个小图片合并成一个大图片(即图片精灵),通过 CSS 背景定位来显示不同的图片区域,减少图片资源的请求数量。
- 图片懒加载:对于页面中位于视窗外的图片,采用懒加载技术,当图片即将进入视窗时再进行加载,节省初始加载时的带宽资源。
- 脚本异步加载:对于一些不影响页面初始渲染的脚本,设置为异步加载,让浏览器在下载脚本的同时继续进行其他渲染工作,提高页面加载速度。
- 离线包利用:使用离线包技术,将部分常用的资源预先下载并存储在本地,当用户访问页面时,优先从本地加载资源,减少网络请求,提高加载速度,尤其适用于网络环境不稳定的场景。
- 提前请求资源:在页面加载的早期阶段,通过 JavaScript 提前请求一些后续可能会用到的资源,如图片、脚本等,当实际需要使用这些资源时,能直接从缓存中获取,加快页面响应速度。
- 模块懒加载:对于页面中的模块,采用懒加载策略,只有当用户真正需要访问某个模块时,才进行加载和初始化,减少初始加载的资源量,提高页面加载效率。
按照上述从页面加载流程出发的全面优化思路进行回答,不仅展现了对前端知识的深入理解,更体现了系统性解决问题的能力,必然能在面试中给面试官留下深刻印象,凸显自身的前端技术水平。