跳到正文
前端知识库
面试真题

性能、渲染与大数据真题

从 Web Vitals、构建与运行时优化,到移动端 1px、虚拟列表、Worker 和大数据传输,整理可验证的面试回答。

6 分钟性能 · LCP · INP · CLS · 虚拟列表 · Web Worker · 渲染 · 大数据

性能、渲染与大数据真题

1. 性能题先给指标和场景

不要直接罗列“压缩、懒加载、缓存”。先确认用户路径(首屏、输入、滚动、提交)、设备/网络和数据规模,再选择指标:

目标 优先指标 说明
首屏主要内容出现 LCP、FCP、TTFB LCP 在真实用户中通常看 P75;还要保留候选元素和归因
点击/输入响应 INP、长任务、事件耗时 INP 已取代 FID,覆盖整个页面生命周期;TBT 主要是实验室指标
页面不跳动 CLS 预留图片/广告/字体空间,排除用户主动触发的偏移
资源是否命中 Resource Timing、缓存头 区分浏览器缓存、Service Worker、CDN 和回源
发布是否退化 RUM 分位数、错误率、构建体积 按路由、版本、设备和网络切分,保留回滚阈值

“LCP 小于 2.5 秒”只是常见分段参考,不是脱离页面和样本的承诺。测量条件、样本量、P75/P95 和优化前后基线必须一起记录。

深入阅读:性能知识地图指标采集与诊断

2. 编译构建时如何优化?

2.1 体积和请求

  1. 用 bundle analyzer 或 source map 追溯大模块、重复依赖和意外引入,而不是凭感觉删除包。
  2. 用路由/功能动态导入做 Code Splitting;共享依赖按更新频率与缓存收益拆分。
  3. 生产启用压缩、Tree Shaking 和合适的 sideEffects 声明;动态 CommonJS、全局注册和错误副作用标记会破坏摇树。
  4. 图片使用合适格式、尺寸和 srcset;关键字体/图片才 preload,下一步资源才 prefetch
  5. 静态资源使用内容 hash 和长期缓存,HTML/接口使用短缓存或协商缓存;发布要保留旧资源以支持回滚。

HTTP/2 多路复用减少了“合并所有文件”的必要性,但不意味着请求数量、压缩、缓存粒度和解析成本可以忽略。每次改动都要用 Network 与构建报告对照。

2.2 开发和 CI 构建

记录冷启动、增量构建、CI 构建、压缩和类型检查分别耗时;确认文件系统缓存、loader 范围和插件耗时。构建变快不能以跳过类型检查、测试、source map 或安全扫描为代价。详见 构建体积与性能治理

3. 运行时卡顿怎么拆?

浏览器主线程大致经历 JavaScript、样式计算、布局、绘制和合成。排查卡顿时先用 Performance 录制定位长任务,再判断是哪一层:

现象 常见原因 可验证改动
输入延迟高 同步计算、过大的状态更新、事件处理过长 分片/Worker、缩小更新边界、记录 Event Timing/INP
滚动掉帧 滚动回调读写布局、过多 DOM、图片解码 IntersectionObserver、虚拟列表、分帧和占位尺寸
页面跳动 图片/字体/异步内容未预留空间 width/heightaspect-ratio、字体策略、CLS 归因
内存持续上涨 detached DOM、监听器、闭包、缓存无上限 Heap Snapshot、释放监听器/对象 URL、LRU 上限
动画耗时 频繁触发布局/绘制、图层过多 优先 transform/opacity,核对图层和 GPU 内存

requestAnimationFrame 只适合把视觉更新对齐到下一帧;requestIdleCallback 可能长期得不到执行;Worker 能移出计算但不能直接操作 DOM,消息序列化/Transferable 也有成本。不要把任何一个 API 当万能解法。

4. 后端一次返回大量数据,如何减轻渲染负担?

按数据量和交互要求分层回答:

  1. 减少传输:分页、游标、按字段查询(REST 参数或 GraphQL)、压缩和服务端聚合;避免把用户永远看不到的字段发到浏览器。
  2. 控制请求:无限滚动用 IntersectionObserver 触发下一页,设置并发上限、取消旧请求和去重;失败要能重试或回到已确认页。
  3. 控制 DOM:虚拟列表只保留可视窗口及缓冲区,维护占位高度和滚动位置;动态高度、键盘焦点、跳转定位和可访问性必须纳入设计。
  4. 控制计算:解析、排序、聚合等重任务放到 Worker;主线程分批提交更新,并在任务之间让出帧时间。
  5. 控制缓存:对稳定查询使用带版本/权限的缓存;IndexedDB 适合离线结构化数据,不能无限增长。
  6. 服务端流式化:SSE/WebSocket 或 chunked 响应可降低首个结果等待,但仍需定义顺序、断线、取消、超时和最终一致性。

虚拟列表解决的是 DOM 数量,不会自动解决数据传输、排序和组件重复渲染;先分页/裁剪数据,才有机会让列表真正可用。

5. 移动端 1px 线怎么回答?

设备像素比(DPR)使 CSS 像素和物理像素不总是一一对应。常见方案及代价:

/* 伪元素缩放:不改变布局占位,适合单条边框 */
.hairline {
  position: relative;
}

.hairline::after {
  content: '';
  position: absolute;
  inset: auto 0 0;
  height: 1px;
  background: currentColor;
  transform: scaleY(0.5);
  transform-origin: 0 100%;
}
  • transform: scale 可绘制半物理像素,但要确认 transform origin、圆角和命中区域。
  • box-shadow 或渐变能做视觉细线,浏览器差异和颜色控制要实测。
  • 依赖 rem/viewport 的方案会改变全局尺寸,老项目迁移成本高,不应为一条线改动整套布局。
  • 现代浏览器可直接使用合适的边框渲染,但仍要按目标设备截图验证;不要保证所有屏幕都能稳定呈现物理 1px。

6. 主题切换有哪些实现?

优先用 CSS 自定义属性,让布局和颜色切换不依赖重新生成大量样式:

:root {
  color-scheme: light;
  --surface: #ffffff;
  --text: #202124;
}

[data-theme='dark'] {
  color-scheme: dark;
  --surface: #202124;
  --text: #f1f3f4;
}

body { background: var(--surface); color: var(--text); }

脚本只切换 data-theme 并持久化用户偏好;初始化时在首屏 HTML 或极早脚本读取偏好,避免闪烁。主题数量固定、需要编译时消除分支时可用 Sass 等预处理器;主题包很大时可动态加载 CSS,但要处理旧样式替换、加载失败和无 JS 降级。CSS-in-JS、Tailwind 令牌也只是实现方式,关键是令牌契约、可访问对比度和发布兼容。

7. 高频追问

Q: React.memouseMemouseCallback 都用了,为什么仍然卡?

A: 先看 Performance 和 React Profiler:可能是状态放得太高、Context value 每次变化、子组件 key 不稳定、昂贵计算在 memo 之前执行,或单次更新本身就超过帧预算。稳定引用只是跳过部分渲染的条件,不是性能保证。回到 React 与 Vue 运行时优化 对照更新边界。

Q: preload 越多越好吗?

A: 不是。preload 会提高资源优先级并占用连接/带宽;只预加载当前路径确定会影响 LCP 的资源,并设置正确的 as、跨源属性和失败降级。下一步可能用到的资源用 prefetch,低概率资源不要抢首屏。

Q: Worker 一定能让页面更快吗?

A: 只有当计算足够重且消息传输成本可接受时才可能收益。先量化主线程阻塞,再比较结构化克隆和 Transferable、Worker 启动、内存和取消成本;DOM 操作仍需回主线程。

Q: 如何证明优化有效?

A: 固定版本、设备、网络、数据和操作脚本,做对照或灰度,观察 P75/P95、错误率和业务完成率,并保留停止条件与回滚路径。没有现场数据时只能称为实验结果或验证计划。

8. 来源与索引

本篇融合 高频真题解析与9月考点预测中.pdf高频真题解析与9月考点预测下.pdf 和三份性能 PDF 中的技术问题。旧资料的 FID 统一指向现代 INP;演示中的性能百分比、课程名称和推广话术未纳入。