作业帮全栈一面:浏览器进程、HTTP 缓存与 Vue3 响应式
- 轮次
- 一面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 介绍一下你的实习监控项目。
- 这个项目做了哪些优化?
- 项目里遇到的难点是什么?
- (类埋点项目)fetch 如何避免与业务上报抢占网络?
- 浏览器有哪些进程和线程?
- 数据上报的发送链路是怎样的?
- 如何实现页面一致性采样?
- (文档项目)协同算法是怎么做的?
- 如何保证网络波动时数据不丢失?
- 多集群部署如何实现?
- SSE 与 WebSocket 有什么区别?
- tiptap 的拓展机制是怎样的?
- HTTP/1.1 与 HTTP/2 有什么区别?
- AI Coding 的流程是怎样的?
- Vue3 的响应式是如何实现的?
- computed、watch、watchEffect 有什么区别?
- 响应式方案中,全局 vw 与断点、rem、transform 有什么区别?
- 强缓存与协商缓存有什么区别?
- 手撕:爬楼梯。
《参考解析》
浏览器进程与线程:Chrome 采用多进程架构,主要包括浏览器主进程(负责界面、标签页与进程调度)、渲染进程(通常每个标签页一个,运行 Blink 与 V8)、GPU 进程、网络进程和插件进程。渲染进程内又分主线程(执行 JS、解析 HTML/CSS、布局与绘制)、合成线程、光栅线程和 Worker 线程;主线程被长任务阻塞时页面会卡顿,而滚动与合成动画可以交给合成线程继续跑。回答时点明「进程隔离带来稳定性与安全沙箱,代价是内存占用和进程间通信」,比只背进程名更加分。
强缓存与协商缓存:强缓存由 Cache-Control 的 max-age、immutable(以及兼容用的 Expires)控制,命中时浏览器直接读本地副本、根本不发请求,开发者工具里显示 200 from disk/memory cache。协商缓存则是浏览器带上 If-None-Match(对应 ETag,优先级更高)或 If-Modified-Since(对应 Last-Modified)去问服务端,资源没变返回 304、不传响应体。工程上通常给带内容哈希的 JS/CSS 设一年强缓存加 immutable,HTML 用 no-cache 走协商,发版靠改文件名哈希破缓存。
Vue3 响应式与 computed/watch/watchEffect:Vue3 用 Proxy 代理对象,在 get 时通过 track 收集依赖、在 set 时通过 trigger 触发更新;reactive 做深层代理,ref 用 .value 包装(值是对象时内部仍转成 reactive),shallowRef 只代理第一层。三者区别要讲清定位:computed 是惰性求值且带缓存,依赖不变就不重算,适合派生状态;watch 显式指定侦听源,默认惰性,可配 deep、immediate、flush,回调能拿到新旧值,适合发请求、写存储这类副作用;watchEffect 立即执行并自动收集用到的依赖,拿不到旧值,适合依赖较多、只关心「变了就重跑」的场景。异步副作用里用 onCleanup 清理上一次的请求或定时器。
SSE 与 WebSocket:SSE 建立在普通 HTTP 之上,响应类型是 text/event-stream,只能服务端向客户端单向推送,浏览器自带断线重连并支持 Last-Event-ID 续传,实现简单、容易穿过代理,适合通知、进度和 AI 流式输出;缺点是单向、受浏览器连接数限制(HTTP/2 下好很多)。WebSocket 通过 HTTP Upgrade 握手后升级为全双工长连接,双方都能随时发消息、延迟低,适合聊天和协同编辑;代价是要自己处理心跳、重连、鉴权和扩容时的连接粘性。选型一句话:只需要服务端推就用 SSE,需要双向高频交互才上 WebSocket。
手撕爬楼梯:本质是斐波那契数列,每次只能走 1 或 2 阶,故 dp[i] = dp[i-1] + dp[i-2],边界 dp[0] = 1、dp[1] = 1。用两个滚动变量即可把空间降到 O(1),时间 O(n)。面试时先说出状态定义与转移方程,再写代码,并主动补一句 n 很大时可用矩阵快速幂把时间降到 O(log n),同时注意结果取模与整数溢出。