浏览器原理面试题:渲染、V8、安全与性能
浏览器原理常用来判断你是否只会写业务,还是理解页面从输入 URL 到展示、交互、优化的完整链路。
浏览器架构
多进程模型
知识点讲解
现代浏览器通常包含浏览器进程、网络进程、GPU 进程、渲染进程、插件进程等。每个标签页一般会有独立渲染进程,隔离页面执行环境,提高稳定性和安全性。
面试常问
问:为什么浏览器要多进程?
答:主要是稳定性、安全性和性能隔离。某个页面崩溃不至于拖垮整个浏览器,不同站点之间也能做更好的安全隔离。
从输入 URL 到页面展示
知识点讲解
核心流程是:URL 解析、缓存检查、DNS 解析、TCP/TLS 握手、发送 HTTP 请求、接收响应、解析 HTML、构建 DOM 和 CSSOM、合成 Render Tree、Layout、Paint、Composite。
面试常问
问:输入 URL 后发生了什么?
答:先从网络链路讲到资源获取,再从渲染链路讲到页面展示。回答时不要只背步骤,要补充缓存、重定向、HTTPS、关键渲染路径和性能优化点。
渲染流水线
DOM、CSSOM 与 Render Tree
知识点讲解
HTML 解析生成 DOM,CSS 解析生成 CSSOM。两者合并形成 Render Tree,但 display: none 的节点不会进入 Render Tree。随后浏览器计算布局、绘制像素、最后合成图层。
面试常问
问:CSS 会阻塞渲染吗?
答:会。浏览器需要 CSSOM 才能计算最终样式,所以 CSS 是渲染阻塞资源。JS 如果访问样式或 DOM,也可能被 CSS 阻塞。
重排、重绘与合成
知识点讲解
重排是重新计算布局,成本较高;重绘是重新绘制外观;合成是把已有图层交给合成线程处理。动画优先使用 transform 和 opacity,因为更容易走合成路径。
面试常问
问:如何减少重排?
答:批量读写 DOM、避免频繁访问触发布局的属性、使用 class 批量改样式、复杂动画用 transform、离线操作 DOM、列表虚拟化。
V8 与 JS 执行
编译与执行
知识点讲解
V8 会把 JS 解析成 AST,再生成字节码执行,热点代码会被 JIT 优化成机器码。对象形状稳定、类型稳定的代码更容易优化;频繁改变对象结构会影响性能。
面试常问
问:为什么说 JS 是解释型语言但也有编译?
答:现代 JS 引擎不是简单逐行解释。它会先解析、生成中间表示和字节码,并对热点代码做即时编译优化。
垃圾回收
知识点讲解
GC 主要判断对象是否仍可达。常见算法有标记清除、分代回收。新生代对象生命周期短,回收频繁;老生代对象存活久,回收成本更高。
面试常问
问:前端常见内存泄漏有哪些?
答:未清理定时器、事件监听、闭包长期持有大对象、缓存无限增长、DOM 被移除但仍被 JS 引用。
存储、安全与性能
浏览器存储
知识点讲解
Cookie 适合随请求携带少量数据;LocalStorage 同源持久存储,容量有限且同步阻塞;SessionStorage 随标签页生命周期;IndexedDB 适合大量结构化数据;Cache API 常配合 Service Worker 做离线缓存。
面试常问
问:Cookie、LocalStorage、SessionStorage 区别?
答:Cookie 会随请求发送,适合认证标识但要注意安全属性;LocalStorage 持久保存;SessionStorage 关闭标签页失效。敏感 token 不建议直接放 LocalStorage。
XSS、CSRF 与 CORS
知识点讲解
XSS 是攻击者注入脚本,防护重点是输入校验、输出转义、CSP、避免危险 API。CSRF 是利用用户登录态伪造请求,防护重点是 SameSite Cookie、CSRF Token、校验 Origin/Referer。CORS 是浏览器的跨域访问控制机制,不是服务器之间的限制。
面试常问
问:CORS 预检请求是什么?
答:复杂请求前浏览器会先发 OPTIONS 请求,询问服务端是否允许真实请求。服务端返回允许的方法、头和源后,浏览器才继续发送真实请求。
性能优化
知识点讲解
性能可以按加载、渲染、运行时拆解。加载侧关注缓存、CDN、压缩、代码分割、预加载;渲染侧关注关键 CSS、减少阻塞、图片优化;运行时关注长任务、虚拟列表、Web Worker、防抖节流。
面试常问
问:白屏时间怎么优化?
答:减少关键资源体积,启用缓存和 CDN,SSR/SSG,关键 CSS 内联,路由级代码分割,图片懒加载,压缩资源,减少首屏不必要 JS。
底层追问与代码示例
强制同步布局
知识点讲解
浏览器为了性能会批量处理样式计算和布局。如果代码先写 DOM,再立即读布局属性,浏览器必须提前刷新布局,这叫 forced synchronous layout。
1 | const box = document.querySelector('.box') |
更好的方式是把读写分离:
1 | const boxes = [...document.querySelectorAll('.box')] |
面试常问
问:哪些属性会触发布局读取?
答:常见有 offsetWidth、offsetHeight、clientWidth、scrollTop、getBoundingClientRect()、getComputedStyle() 等。它们可能要求浏览器拿到最新布局结果。
长任务与主线程阻塞
知识点讲解
浏览器主线程负责 JS 执行、样式计算、布局、绘制和用户事件。单个任务超过 50ms 通常会被视为 Long Task,可能导致输入延迟和卡顿。
1 | const observer = new PerformanceObserver(list => { |
拆分长任务可以使用 requestIdleCallback 或分片调度:
1 | function runChunks(items, handler, chunkSize = 500) { |
缓存策略:强缓存与协商缓存
知识点讲解
强缓存命中时不会请求服务器,核心响应头是 Cache-Control 和 Expires。协商缓存会请求服务器验证资源是否变化,核心是 ETag / If-None-Match、Last-Modified / If-Modified-Since。
1 | Cache-Control: public, max-age=31536000, immutable |
生产实践:
- JS/CSS 使用内容哈希文件名,配合长期强缓存。
- HTML 不做长期强缓存,避免引用旧资源。
- 图片和字体按更新频率设置缓存。
面试常问
问:ETag 和 Last-Modified 谁更准?
答:ETag 更准。Last-Modified 只能精确到秒,且依赖文件修改时间;ETag 可以基于内容生成,更适合判断资源是否真的变化。
Service Worker 缓存
知识点讲解
Service Worker 是浏览器和网络之间的代理层,可以拦截请求并自定义缓存策略。常见策略有 Cache First、Network First、Stale While Revalidate。
1 | self.addEventListener('fetch', event => { |
面试里要补一句:Service Worker 必须在 HTTPS 或 localhost 下运行,并且更新策略要谨慎,否则可能缓存旧版本。