前端面试-性能优化篇
1. 怎么实现大文件的上传?
- 分片上传(Chunked Upload):将大文件拆分成小的文件块(chunk),然后通过多个并行的请求依次上传这些文件块。服务器接收到每个文件块后进行存储,最后合并所有文件块以还原原始文件。这种方法可以降低单个请求的负载,并允许在网络中断或上传失败时可以从断点续传。
- 流式上传(Streaming Upload):客户端使用流方式逐步读取文件的内容,并将数据流通过 POST 请求发送给服务器。服务器端能够逐步接收并处理这些数据流,而无需等待完整的文件上传完成。这种方法适用于较大的文件,减少了内存占用和传输延迟。
- 使用专门的文件上传服务:有一些第三方服务可供使用,例如云存储服务(如 Amazon S3、Google cloud3.Storage)、文件传输协议(如 FTP、SFTP)等。这些服务通常提供了高可靠性、可扩展性和安全性,并且针对大文件上传进行了优化。
- 压缩文件上传:如果可能,可以在客户端先对文件进行压缩,然后再进行上传。压缩后的文件大小更小,可以减少上传时间和网络带宽消耗。
- 并发上传:通过多个并行的请求同时上传文件的不同部分,以加快整个上传过程。这需要服务器端支持并发上传并正确处理分片或部分文件的合并。
- 断点续传:记录上传进度和状态,以便在网络中断或上传失败后能够从上次中断的位置继续上传。可以使用客户端或服务器端的断点续传机制来实现。
2. 说说常规的前端性能优化手段?
- content 方面
- 减少HTTP请求:合并文件、CSS精灵、inline Image
- 减少DNS查询: DNS查询完成之前浏览器不能从这个主机下载任何文件。方法:DNS缓存、将资源分布到恰当数量的主机名,平衡并行下载和DNS拆线呢
- 避免重定向:多余的中间件访问
- 使用Ajax可缓存
- 非必须组件延迟加载
- 未来所需组件预先加载
- 减少DOM元素数量
- 将资源放到不同域下:浏览器同时从一个域下载资源的数目有限,增加域可以提高并行下载量
- 减少iframe数量
- Server 方面
- 使用CDN
- 添加Expires或者Cache-Conntrol响应头
- 对组件使用Gzip压缩
- 配置ETag
- Flush Buffer Early
- Ajax使用GET进行请求
- 避免空链接
- Cookie方面
- 减少cookie大小
- 引入资源的域名不要包含cookie
- CSS 方面
- 将样式表放到页面顶部
- 不适用CSS表达式
- 不使用IE的Filter
- JS 方面
- 将脚本放到页面底部
- 将JS和CSS外部引入
- 压缩JS CSS
- 删除不需要的脚本
- 减少对DOM的访问
- 合理设计事件监听器
3. 前端性能优化指标?
前端核心性能指标(Core Web Vitals)
| 指标 | 全称 | 含义 | 推荐值 | 工具/方法 |
|---|---|---|---|---|
| LCP | Largest Contentful Paint 最大内容绘制 |
页面中最大元素渲染完成的时间(如大图、标题块) | ≤ 2.5s | Chrome DevTools, Lighthouse |
| FID | First Input Delay 首次输入延迟 |
用户第一次交互(点击/输入)到页面响应的时间 | ≤ 100ms | 实验性(逐步被 INP 替代) |
| INP | Interaction to Next Paint 互动响应延迟 |
衡量所有交互的响应时间(新标准,取代 FID) | ≤ 200ms | Chrome UX Report, RUM |
| CLS | Cumulative Layout Shift 累计布局偏移 |
页面加载过程中意外布局跳动的程度 | ≤ 0.1 | DevTools, PageSpeed Insights |
4. 虚拟DOM一定更快吗?
在某些情况下快。
可能带来提升的情况:
- 批量更新:虚拟DOM可以将多个DOM操作合并为一次更新。
- 局部封信:通过比较新旧DOM树,只有发生变化的部分会重新渲染到真实DOM中
- 跳过昂贵计算:在虚拟DOM的比较过程中,可以通过判断节点是否相同来跳过一些计算。
- 跨平台支持。
可能的性能开销:
- 额外的内存占用:虚拟DOM需要额外的内存来保存节点信息。
- 操作的复杂度:虚拟DOM需要比较、计算和递归遍历等操作,会有额外计算开销。
5. 什么是内存泄漏?什么原因导致的?
内存泄漏是指程序运行过程中已分配的堆内存由于某些原因未释放或者无法释放。
- 全局变量过多
- 闭包
- 事件监听未移除
6. 在script标签中,script标签的defer属性和async属性有什么区别?
defer
1 | |
行为特点:
- 异步下载:脚本在后台异步下载,不阻塞 HTML 解析。
- 延迟执行:脚本等到整个 HTML 文档解析完成后(DOMContentLoaded 事件触发前),才按顺序执行。
- 执行顺序:多个 defer 脚本按声明顺序执行。
适用场景:
- 脚本依赖 DOM 元素(如操作 document.getElementById)。
- 多个脚本之间有依赖关系(需按顺序执行)。
- 你想在 DOM 构建完成后才执行脚本。
async
1 | |
行为特点:
- 异步下载:脚本在后台异步下载,不阻塞 HTML 解析。
- 下载完立即执行:一旦脚本下载完成,立即中断 HTML 解析来执行它。
- 执行顺序不确定:多个 async 脚本谁先下载完谁先执行,不保证顺序。
适用场景:
- 独立脚本,不依赖其他脚本或 DOM(如统计代码、广告脚本)。
- 对执行时机要求不高,希望尽快运行。
7. SPA(单页应用)首屏加载慢的原因和怎么解决?
原因:
- 网络延时问题( DNS 查询、TCP 连接耗时)
- 资源文件体积过大
- 资源是否重复发送请求去加载
- 加载脚本的时候,渲染内容堵塞了
解决方案:
- 减小入口文件体积(路由懒加载)
- 静态资源本地缓存
- UI框架按需加载 (按需引用)
- 图片资源的压缩
- 组件重复打包(假设A.js文件是一个常用的库,现在有多个路由使用了A.js文件,这就造成了重复下载。解决方案:在webpack的config文件中,修改CommonsChunkPlugin的配置)
- 开启GZip压缩
- 使用SSR
8. 如何减少页面加载时间?
1. 资源加载优化
- 代码分割(Code Splitting):使用
import()动态导入,按路由或功能拆分 JS,减少首屏体积。 - 懒加载(Lazy Load):图片、组件、路由组件延迟加载。
- 资源压缩:启用 Gzip/Brotli 压缩,压缩 JS/CSS/HTML。
- CDN 加速:静态资源部署到 CDN,就近访问。
- 预加载/预连接:
<link rel="preload">预加载关键资源<link rel="preconnect">提前建立 DNS 和 TCP 连接
2. 渲染性能优化
- 减少关键渲染路径(Critical Rendering Path):
- 内联关键 CSS
- 异步加载非关键 JS(
async/defer)
- 避免阻塞渲染:避免长时间运行的 JavaScript
3. 缓存策略
- HTTP 缓存:合理设置
Cache-Control、ETag - Service Worker:实现离线缓存和网络请求拦截
4. 图片优化
- 使用 WebP/AVIF 格式
- 响应式图片(
srcset) - 图片懒加载
9. 虚拟列表(Virtual List)实现原理
原理
只渲染可视区域内的列表项,而非全部数据。当用户滚动时,动态计算哪些项进入/离开可视区,并更新 DOM。
滚动处理
- 监听滚动容器的
scroll事件 - 根据
scrollTop计算当前可视区域的起始索引和结束索引 - 只渲染这个范围内的列表项
- 用一个占位元素(
padding或transform)撑起总高度,保持滚动条位置
长列表性能优化:定高 vs 不定高
定高场景
- 实现简单:每项高度固定
- 计算快:
startIndex = Math.floor(scrollTop / itemHeight) - 滚动条稳定:总高度 =
itemHeight * totalCount,无抖动
不定高场景
- 挑战:每项高度不同,无法直接计算
- 解决方案:
- 预估高度 + 动态修正:
1. 为每项设置一个预估高度(如平均值)
2. 列表项渲染后,通过ref.getBoundingClientRect()获取真实高度
3. 更新缓存中的真实高度,并重新计算总高度和滚动条 - 缓存真实高度:避免重复计算
10. CSR和SSR 分别是什么?
CSR 和 SSR 是前端开发中两种主要的页面渲染方式,它们决定了网页内容是在客户端(用户浏览器)还是在服务器端生成并发送给用户的。
CSR(Client-Side Rendering,客户端渲染)
核心思想:
服务器只返回一个空的 HTML 骨架(通常只有一个 <div id="app"></div>)和一个 JavaScript 文件。
所有页面内容、数据获取、DOM 操作都由浏览器下载 JS 后,在客户端动态生成。
工作流程:
- 用户访问页面。
- 服务器返回一个极简的 HTML 文件(几乎为空)。
- 浏览器下载并执行 JavaScript 文件。
- JS 代码向后端 API 请求数据。
- JS 根据数据动态构建 DOM,最终显示完整页面。
SSR (Server-Side Rendering) - 服务端渲染
核心思想:
- 服务器在接收到请求时,提前将页面内容渲染成完整的 HTML 字符串,然后直接发送给浏览器。
- 用户打开页面时,看到的是一个已经包含内容的完整页面。
工作流程:
- 用户访问页面。
- 服务器接收到请求,调用后端逻辑或前端框架(在服务端运行)生成完整的 HTML。
- 服务器将包含数据的完整 HTML 发送给浏览器。
- 浏览器直接渲染出可视页面(首屏快)。
- 同时,JavaScript 也会被下载并“激活”(称为 Hydration),使页面具备交互能力。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!