炎魂网络前端秋招一二面:扫码登录场景题与埋点项目深挖
- 轮次
- 一二面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
一面:
- 场景题:移动端扫描网页二维码登录怎么实现?
- 讲讲印象最深的实习项目
- 项目中降采样为什么在后端实现?
- 项目中如何做懒加载?
- 性能优化的数据指标如何获取?
- 响应式断点的作用是什么?
- 响应式布局里
transform: scale的用法;为什么可以局部缩放却不能全局缩放? - 为什么选择 IndexedDB 而不是其他存储方式?如何考量数据库 TTL 等约束?
- 如何选择监听指标?
- 协同算法的技术选型
- 流式输出的中断与重连怎么处理?
requestAnimationFrame的作用是什么?- Vue 响应式原理
- 浏览器输入 URL 全过程
- 如何避免重排重绘?
- 如何使用 AI 进行开发?
二面:
- 一个类似前端埋点的个人项目,整体设计架构是什么?
- 如何处理用户关闭页面的遗留数据?
- 多个标签页同时关闭如何处理?
- 如何处理弱网、重发、竞态等各种特殊情况?
- 如何测试验证?如何保证一致性?
- 如何不依赖现有 API 实现页面停留时长上报?
- 场景题:校园活动网页的报名、取消报名、通知等业务功能如何设计?
- 开发团队扯皮如何处理?
- 如何使用 AI 学习新技术?
- 场景题:用户无感更新怎么实现?
- AI 与前端的关系,AI 时代前端的个人优势?
《参考解析》
扫码登录的本质是「用已登录的手机端给未登录的网页端授权」。 流程:网页端生成一次性 sceneId(或二维码 ticket)并向服务端建立连接(轮询或 WebSocket/SSE),二维码里只放这个随机标识;手机端扫码后由已登录态发起「确认」请求,把用户身份与 sceneId 绑定到服务端;服务端下发授权凭证(一次性 token)给网页端,网页端换取正式会话。安全要点:sceneId 必须一次性、短有效期(通常 1–2 分钟)且只能被确认一次,确认环节要防止钓鱼(展示登录设备信息、二次确认),凭证要有防重放机制。追问「为什么不用长轮询」时可以对比:轮询实现简单但有延迟与空请求成本,长轮询/SSE 延迟低,WebSocket 双向但要心跳与重连治理。
前端性能指标的采集靠标准 API。 核心指标用 Web Vitals:LCP(最大内容绘制)、INP(交互到下次绘制)、CLS(布局偏移),框架库 web-vitals 直接可用;导航与资源耗时用 Performance API(performance.getEntriesByType('navigation'/'resource')、PerformanceObserver 监听 longtask 与 element timing)。采集时要注意:在 visibilitychange 隐藏时用 navigator.sendBeacon 上报(普通 XHR 在页面卸载时可能被丢弃)、做采样与聚合避免上报量爆炸、并在上报里带上设备、网络类型、版本与路由,否则数据无法归因。
IndexedDB 的选型理由是「容量 + 离线 + 结构化」。 localStorage 只有 5MB 左右、同步 API 会阻塞主线程、只能存字符串;IndexedDB 容量按磁盘配额(通常数百 MB 起)、异步不阻塞、支持索引与事务,适合缓存大量结构化数据(离线素材、埋点队列、协同文档历史)。代价是 API 繁琐(现在可用 idb/Dexie 封装)、需要自己设计版本迁移(onupgradeneeded),以及没有自动 TTL——过期清理要自己实现:存 expireAt 字段,读取时过滤并在空闲时批量删除,或用 setTimeout/Service Worker 定期清理;同时要处理配额超限(QuotaExceededError,需降级到只保留最新记录)。
埋点项目的几个追问都是「浏览器关闭时的不确定性」问题。 遗留数据:优先用 visibilitychange(移动端与桌面端都比 unload 可靠)触发 sendBeacon 上报;beforeunload 只做同步的轻量兜底;未上报的数据留在 IndexedDB 里,下次启动时补传,并带本地自增序号供服务端去重。多标签页同时关闭:用 navigator.sendBeacon 的天然去重(同一条记录带唯一 id)或 BroadcastChannel/localStorage 事件选一个主标签页统一上报,避免 N 个标签页重复发送。弱网、重发与竞态:上报接口按「幂等 id + 服务端去重」设计,客户端做本地队列 + 指数退避重试,队列有上限并做批量合并。一致性保证:以「事件流 + 服务端最终聚合」为准,客户端只保证至少一次投递,重复由服务端消除。
「不依赖现有 API 实现页面停留时长上报」是在考你对浏览器事件模型的掌握。 思路是用 visibilitychange + focus/blur + 心跳组合:页面进入可见时记 startTime,隐藏或失焦时累加已停留时长并上报片段;同时每分钟发一次心跳把累计时长落库,这样即使页面被强杀也只会丢一个心跳周期。要主动说明这个方案的误差来源(后台标签页是否算、多标签页重复计数、系统休眠导致的时间漂移),以及用 performance.now()(单调时钟)而不是 Date.now() 来避免系统时间被改动导致负数。
「用户无感更新」指的是新版本发布后用户不用手动刷新。 常见做法:构建产物带 hash 与版本号,用 Service Worker 预缓存新资源并在 activate 后切换;应用内轮询或 SSE 拿到新版本通知后提示用户「有新版本」或直接静默切换(切换到新版本前要保证当前未提交的表单数据不丢,可通过本地暂存 + 恢复)。难点是新旧版本共存时的接口兼容(灰度期间后端要同时兼容两版),以及用户处于表单填写/支付流程中不能强刷,所以要给「延迟更新」的能力。校园活动网页的场景题则按「数据模型(活动、报名、名额、通知)、并发抢名额的库存扣减与幂等、通知渠道与去重、排序与状态流转」来答,注意点出报名/取消的并发与超卖处理。