Skip to content
On This Page

面试题[性能优化]

INFO

在实际的业务场景下...

1. 前端性能优化思路

优化前端性能是提升用户体验和网站整体效率的关键。以下是一些常见的前端性能优化思路:

  1. 减少HTTP请求:
    • 合并多个 CSS 或 JavaScript 文件。
    • 使用 CSS Sprites 技术合并小图片。
    • 使用字体图标(如 Font Awesome)替代图片图标。
    • 利用数据 URI(Base64)将小文件嵌入到 HTML 或 CSS 中。
    • 使用 HTTP/2 协议,它支持多路复用,能够在一个连接中并行处理多个请求。
  2. 压缩和优化资源:
    • 压缩 CSS、JavaScript 和 HTML文件(如使用 Gzip)。
    • 使用 CSS 和 JavaScript 的压缩工具(如 UglifyJS、Terser、PurgeCSS 等)。
    • 压缩图片(如使用 JPEG、PNG、WebP 等格式,并调整质量)。
  3. 减少 DOM 操作:
    • 避免不必要的 DOM 操作,减少页面重排(reflow)和重绘(repaint)。
    • 使用 DocumentFragment 或离线 DOM 来创建和修改元素,然后再一次性添加到页面中。
    • 使用 requestAnimationFrame 来执行动画或复杂的 DOM 操作。
  4. 优化 CSS 选择器:
    • 避免使用复杂的CSS选择器,因为它们可能导致浏览器花费更多时间来解析和渲染页面。
    • 使用ID选择器代替类选择器或标签选择器,因为它们具有更高的优先级和更快的查找速度。
  5. 优化动画:
    • 使用 CSS3 动画代替 JavaScript 动画,利用 CSS3 提供的硬件加速特性,可以提高动画的性能和流畅度。
  6. 使用 CDN(内容分发网络):
    • 将静态资源(如图片、CSS、JavaScript 等)部署到 CDN上,以加快全球用户的访问速度。
  7. 优化缓存:
    • 设置合适的 HTTP 缓存头(如 Expires、Cache-Control 等),使浏览器缓存静态资源。
    • 使用浏览器缓存 API(如 localStorage、sessionStorage、IndexedDB 等)缓存动态数据。
  8. 异步加载和延迟加载:
    • 使用异步加载(如 async 和 defer 属性)来异步加载 JavaScript 脚本。
    • 延迟加载图片、视频等非关键资源,以改善页面初始加载速度。
  9. 代码拆分和按需加载:
    • 使用 Webpack 等构建工具进行代码拆分,按需加载不同的代码块。
    • 对于单页面应用(SPA),使用路由级别的代码拆分和懒加载。
  10. 使用 Web Workers 进行多线程处理:
    • 将耗时的计算任务或数据处理任务交给 Web Workers 来处理,以避免阻塞主线程并影响页面性能。
  11. 性能监控和分析:
    • 使用 Chrome DevTools、Lighthouse 等工具进行性能分析和优化建议。
    • 使用 Performance API 收集和分析页面性能数据。
    • 监控和分析真实用户的性能数据(如使用 RUM - Real User Monitoring)。
  12. 减少重定向和4xx/5xx错误:
    • 避免不必要的重定向,因为它们会增加额外的 HTTP 请求并可能导致性能下降。
    • 确保服务器配置正确,以减少4xx和5xx错误的发生。
  13. 使用前端框架和库的优化版本:
    • 使用经过优化的前端框架和库(如 React 的 Production 模式、Vue 的 Production 构建等)。
    • 定期更新前端依赖项,以利用最新的性能改进和优化。
  14. 利用浏览器缓存机制:
    • 利用浏览器的本地存储(如 localStorage、sessionStorage)来缓存数据和状态,以减少网络请求。
    • 使用浏览器的预加载(prefetch)和预渲染(prerender)功能来提前加载和渲染页面。
  15. 代码质量:
    • 编写高效、简洁的代码,避免不必要的计算和循环。
    • 使用 ES6+ 的新特性(如 let、const、箭头函数、解构赋值等)来提高代码质量和性能。
    • 对代码进行单元测试和集成测试,以确保其稳定性和性能。

2. 什么情况下会重绘和回流,常见的改善方案

浏览器请求到对应页面资源的时候,会将 HTML 解析成 DOM,把 CSS 解析成 CSSDOM,然后将 DOM 和 CSSDOM 合并就产生了 Render Tree。在有了渲染树之后,浏览器会根据流式布局模型来计算它们在页面上的大小和位置,最后将节点绘制在页面上。

那么当 Render Tree 中部分或全部元素的尺寸、结构、或某些属性发生改变,浏览器就会重新渲染页面,这个就是浏览器的回流。常见的回流操作有:页面的首次渲染、浏览器窗口尺寸改变、部分元素尺寸或位置变化、添加或删除可见的 DOM、激活伪类、查询某些属性或调用方法(各种宽高的获取,滚动方法的执行等)。

当页面中元素样式的改变不影响它在文档流的位置时(如颜色、背景等),这个就是重绘。

回流必将导致重绘,重绘不一定会引起回流。回流比重绘的代价更高。

常见的改善方案:

  • 避免频繁操作 DOM,可以利用 DocumentFragment,来进行对应的 DOM 操作,将最后的结果添加到文档中。
  • 在进行频繁操作的时候,使用节流和防抖来控制调用频率。
  • 灵活使用 display: none 属性,操作结束后将其显示出来,因为 display 的属性为 none 的元素上进行的 DOM 操作不会引发回流和重绘。
  • 获取各种会引起重绘/回流的属性,尽量将其缓存起来,不要频繁的去获取。
  • 使用 CSS3 动画代替 JavaScript 动画:CSS3 动画会触发 GPU 加速,性能更好。
  • 对复杂动画采用绝对定位,使其脱离文档流,否则它会频繁的引起父元素及其后续元素的回流。

3. 动画优化

一般情况下,动画需要频繁的操作 DOM,就会导致页面的性能问题,我们可以对复杂的动画采用绝对定位(position 属性设置为 absolute 或者 fixed),使其脱离文档流,这样它的回流就不会影响到页面其它元素了。

4. 图片优化

图片优化是一种常见的性能优化策略,旨在减少网页加载时间和带宽占用。通过减少图片的体积,可以加快图片加载速度,提升用户体验,并节省用户流量。以下是一些具体的图片优化方法:

  1. 压缩图片: 使用图片压缩工具(如TinyPNG、ImageOptim等)可以无损或有损地减小图片的文件大小。有损压缩会略微降低图片的质量,但可以显著减小文件大小。无损压缩会保持图片质量不变,但压缩率较有损压缩低。
  2. 选择适当的图片格式: 对于不同类型的图片,选择合适的图片格式可以带来更好的优化效果。一般情况下:
    • 使用 JPEG 格式对于包含丰富颜色和复杂细节的照片效果较好。
    • 使用 PNG 格式对于图标、透明背景和简单图形效果较好。
    • 使用 WebP 格式(现代浏览器支持)可以在保持图片质量的同时大幅减小文件大小。
  3. 适当调整图片尺寸: 将图片调整为网页上实际显示的尺寸大小,避免加载过大的图片。通过在 HTML 或 CSS 中指定图片的宽高,可以确保浏览器不会拉伸图片,从而减少不必要的下载。
  4. 使用图像矢量化: 对于简单的图形和图标,可以使用 SVG(矢量图形)代替位图图片。SVG 是基于 XML 的矢量图形格式,它可以无损缩放而不失真,且文件大小较小。
  5. 懒加载: 对于页面上位于可视区域之外的图片,可以延迟加载,直到用户滚动到它们的位置。懒加载可以减少页面初次加载的图片数量,优化初始加载速度。
  6. 响应式图片: 使用响应式图片可以根据不同的设备和屏幕尺寸加载不同尺寸的图片,避免加载过大的图片。
  7. HTTP 缓存: 使用适当的 HTTP 缓存策略,使浏览器能够缓存图片,减少重复的下载请求。
  8. 使用图像 CDN:使用图像 CDN(内容分发网络)来加速图片加载和交付,提供快速的全球访问能力。

5. 什么是渐进式图像加载(Progressive Image Loading)?它如何改善网页加载性能?

6. 在实际的业务场景下怎么运用缓存机制

在实际的业务场景中,合理运用缓存机制可以提升网站的性能、减少网络请求、降低服务器负载,并提供更好的用户体验。以下是一些常见的应用场景和相应的缓存策略:

  1. 静态资源缓存:对于网站的静态资源(如 CSS、JavaScript 文件、图像等),可以通过设置适当的缓存头来让浏览器缓存这些资源。使用 Cache-Control 和 Expires 字段设置较长的缓存时间,使客户端在下次访问时可以直接从缓存获取资源。
  2. 页面级缓存:对于某些不频繁变化的页面(如首页、文章详情页等),可以在服务器端设置缓存策略,使这些页面在一定时间内不会重复生成,而是直接返回缓存的 HTML。可以使用 HTTP 头部字段如 Cache-Control、Expires 和 Last-Modified 来控制页面的缓存时间和验证机制。
  3. 数据接口缓存:对于频繁被访问的数据接口,可以将其结果缓存起来,以减少数据库查询或复杂计算的次数。可以使用内存缓存、分布式缓存或缓存服务器(如 Redis)来存储这些结果,并设置合适的缓存时间或失效策略。
  4. 动态内容缓存:对于一些动态生成的内容,可以使用缓存来提高性能。例如,可以将部分页面片段或动态生成的 HTML 片段缓存起来,以减少服务器端的计算和数据库查询。可以使用类似 Fragment Caching 或缓存模板片段的技术来实现。
  5. CDN 缓存:将静态资源部署到 CDN(内容分发网络)上,并配置合适的缓存策略,可以使这些资源更快地被用户访问,并减轻源服务器的负载。CDN 提供了全球分布的节点,能够将静态资源缓存到离用户更近的位置,提供更快的访问速度。

在运用缓存机制时,需要根据具体业务需求和资源特性来选择合适的缓存策略,并进行测试和性能优化。需要注意的是,缓存可能导致数据不一致性的问题,因此在更新或修改缓存的数据时,需要及时更新缓存或采用合适的缓存失效策略,以保证数据的一致性和准确性。

7. 用户反馈打开页面白屏时间很长,页面操作很卡,如何优化

采取以下措施进行优化:

  1. 页面加载优化:针对页面加载速度过慢的问题,可以采用以下方法进行优化:
    • 压缩和合并脚本和样式表
    • 减少 HTTP 请求,使用 CDN 加速
    • 使用流式加载,延迟加载图片和脚本
    • 优化图片大小和格式,使用 WebP 等格式
  2. 代码优化:为了提高页面性能,可以进行以下代码优化:
    • 删除无用的代码和文件
    • 将多个请求合并为一个请求
    • 避免过多的重绘和回流
    • 使用 Web Worker 进行异步操作
    • 避免使用过多的全局变量和 DOM 操作
  3. 数据优化:为了提高页面响应速度和性能,可以进行以下数据优化:
    • 使用缓存技术,尽量减少请求服务器
    • 对数据进行分页处理,避免一次性加载大量数据
    • 对数据进行压缩和加密,减少传输时间
  4. 测试和监测:对于页面性能进行测试和监测,可以采用以下工具:
    • Chrome 开发者工具
    • PageSpeed Insights
    • GTmetrix
    • WebPagetest
    • Pingdom

8. 什么是网页性能监测和分析?可以使用哪些工具来监测和分析网页性能?

9. Vue(或 React)有哪些性能优化方式,请结合项目说明

  1. 懒加载组件:在大型项目中,可以将页面分割成多个小模块,然后使用懒加载的方式,按需加载对应的模块。这样可以减少初始加载时的资源压力。
  2. 虚拟列表:对于长列表或表格数据,可以使用虚拟列表技术,只渲染当前可见区域的内容,而不是全部渲染,从而减少渲染开销。
  3. 避免不必要的渲染:使用 useEffect Hook、shouldComponentUpdate 或 Vue 的 watch 等方式,避免不必要的组件渲染,提高渲染效率。
  4. 代码拆分:将业务逻辑和组件进行拆分,按需引入,减少不必要的代码加载和执行。
  5. 使用 CDN 加速:将一些常用的库、框架等资源通过 CDN 加载,可以提高加载速度,减轻服务器压力。

举例说明: 假设在一个 Vue 项目中,有一个页面包含了一个较大的列表,可以通过虚拟列表技术来进行优化。首先,在组件中使用 Vue 的虚拟列表组件(比如 vue-virtual-scroller),根据当前滚动位置动态渲染可见区域的列表项,而不是一次性渲染所有列表项。这样可以显著减少页面渲染时的开销,提升页面加载和滚动的性能。

另外,如果列表中的每个项都是一个复杂的组件,还可以结合 useEffect Hook、shouldComponentUpdate 或 Vue 的 watch 来避免不必要的组件渲染,进一步提高性能。

10. 一个包含多视频流媒体的 H5 页面,滚动加载更多怎么优化

处理一个包含多个视频流媒体的 H5 页面并实现滚动加载更多视频时,需要考虑以下性能优化方案:

  1. 懒加载视频: 初始时只加载可见区域内的视频,当用户滚动页面时,动态加载进入可视区域的视频,而不是一次性加载所有视频。这可以减少页面初始加载时的资源消耗。
  2. 视频预加载: 可以提前预加载下一个即将进入视野的视频,以避免用户在切换视频时出现卡顿或加载延迟。可以通过 JavaScript 预加载视频的 metadata 来实现。
  3. 视频尺寸优化: 确保视频尺寸适应其在页面中的显示大小,避免加载过大尺寸的视频。使用适当的视频压缩技术和分辨率以提高加载速度和节省带宽。
  4. 节流和防抖: 当用户滚动页面时,使用节流(throttling)和防抖(debouncing)技术来限制滚动事件的触发频率,减少不必要的资源加载请求,提高页面性能。
  5. 资源缓存: 对于已经加载过的视频资源,可以使用浏览器的缓存机制进行缓存,避免重复加载相同的资源。
  6. 分页加载: 将视频按照一定的分页策略进行加载,例如每次加载固定数量的视频,当用户滚动到页面底部时再加载下一页的视频,以避免一次性加载大量视频导致页面性能下降。
  7. 使用 Web Workers: 将视频加载任务放在 Web Workers 中进行处理,以避免阻塞主线程,提高页面的响应速度和性能。
  8. 优化网络请求: 对视频资源的请求进行合并、压缩和减少重定向等优化,减少网络请求的数量和资源加载的时间。

综合利用以上性能优化方案,可以有效提高包含多个视频流媒体的 H5 页面的加载速度和性能。

11. WebWorker 为什么能提升 JavaScript 执行的性能

WebWorker是HTML5提供的一种浏览器多线程编程的解决方案,它可以让JavaScript代码在后台线程中运行,从而减轻主线程的负担,提高JavaScript执行的性能。以下是WebWorker能够提高JavaScript执行性能的原因:

  1. 多线程处理:WebWorker允许JavaScript代码在后台开启一个独立的线程运行,在这个线程中可以执行一些耗时的计算、IO操作等任务,从而可以避免在主线程中进行这些操作时造成的卡顿和阻塞。
  2. 分离UI线程:WebWorker可以将长时间运行的JavaScript代码分离到一个独立的线程中,从而避免主线程被阻塞,导致UI失去响应。这样用户可以在UI线程上继续进行其他操作,提高了用户体验。
  3. 线程间通信:WebWorker提供了一种线程间通信的机制,可以让主线程和后台线程之间进行数据传输和消息通信,这样可以更加灵活地控制代码的执行流程。
  4. 充分利用CPU资源:在一些多核CPU的设备上,WebWorker可以充分利用CPU资源,把计算密集型任务分配到不同的线程中运行,从而加速了JavaScript代码的执行速度。

总之,WebWorker通过将JavaScript代码运行在独立的后台线程中,可以避免阻塞UI线程和主线程,提高了JavaScript执行的性能。需要注意的是,WebWorker并不是万能的,在某些场景下可能会带来额外的开销,需要根据具体情况进行使用和优化。

12. 单页面应用如何提高加载速度

单页面应用(SPA)提高加载速度的方法可以归纳为以下几个关键方面:

  1. 路由懒加载
    • 对于SPA的路由,实现按需加载,即在用户导航到相关页面时再加载该页面的资源,而不是一次性加载所有页面的资源。
  2. 代码分割
    • 将代码分割成多个小块,按需加载。可以使用动态导入(dynamic import)、Webpack的代码分割功能或者使用第三方库(如Loadable Components)来实现。
  3. 代码优化
    • 压缩和精简代码:使用工具如Webpack、UglifyJS或Terser对JavaScript、CSS和HTML代码进行压缩和精简,以减少文件大小。
    • 删除未使用的代码和依赖库:减少加载和执行时间。Tree Shaking 是一种通过静态分析代码依赖关系,去除未使用代码的技术。
    • 使用最小化版本:许多CSS和JavaScript库提供了最小化版本,这些版本已经经过压缩和优化,使用它们可以进一步减少文件大小。
  4. 服务端渲染(SSR)或预渲染(Prerendering)
    • 将部分页面在服务器端渲染,这样首次加载时用户能更快看到内容。
    • 对于不频繁变化的内容,可以预渲染生成静态 HTML 文件。
  5. 图片优化
    • 缩小图片尺寸:使用合适的图片尺寸,避免不必要的大尺寸图片。
    • 压缩图片文件大小:使用图像压缩工具来减少文件大小。
    • 采用适当的图片格式:如WebP,它通常具有更好的压缩效果。
    • 懒加载:将图片划分为多个模块或组件,只在需要时才进行加载和渲染,以减少初始加载时间。
  6. 缓存策略
    • 合理设置缓存策略:利用浏览器缓存来减少网络请求。可以通过HTTP头中的Cache-Control和ETag等机制来控制缓存行为。
  7. 使用CDN
    • 内容分发网络(CDN)可以将网站的静态文件缓存到多个服务器上,从而提供更快的访问速度。CDN会根据用户的地理位置选择最近的服务器,从而减少网络延迟。
  8. 启用Gzip压缩
    • 通过启用服务器级别的Gzip压缩,可以减少传输的数据量,从而提高加载速度。