前端专业面试真题这个系列写到第二篇,正好赶上春招季的尾巴。这段时间我帮团队面了不少前端岗位的候选人,从初级到资深都有,手里的题库又沉淀下来一批非常有代表性的题目。第一篇聊的大多是基础层的东西:原型链、闭包、事件循环,属于"背了就能答"的范畴。第二篇我想换个角度,专门拆解那些"看着会、一答就废"的题——它们不直接考某一个API,而是通过一串追问、一个场景,逼着你在现场快速给出方案。这个过程最能拉开普通候选人和高潜候选人的差距。 这篇文章里挑出的五道题,综合了最近高频出现的考察方向:渲染机制、大文件上传、微前端、AI协作时代的调试思维、性能优化闭环。每一道我都会还原面试现场的追问节奏,同时把背后的考察逻辑讲清楚。不管你是准备跳槽还是单纯想查漏补缺,读完应该都能对"面试官到底想要什么"这件事有更清晰的感觉。
1. 命题趋势变了:2026年面试不再满足于"背答案"
先说一个我最近最直观的感受:面试官手里的问题库结构变了。
以前前端面试的题库是什么?闭包、作用域、事件循环、Promise、原型链,这是基础盘,几乎人人都在背。现在这些题依然会出现,但往往只作为"热身",或者干脆被塞进一个小场景里顺带考察。真正的决胜局在后面的场景题和项目深挖。尤其是AI辅助开发工具已经常态化的今天,光会写代码已经很难证明你的竞争力了,因为代码本身变得太容易生产了。
1.1 从八股文到场景题,区分度藏在追问里
高频出现的场景题有这么几类:给你一个真实业务需求,让你现场给方案,比如大文件上传、微前端拆分、SSE长期连接不稳定;或者给你一段有问题的代码,让你现场排查;又或者直接对你的项目经历连续追问:"当时为什么选这个方案?有没有对比过另一个?如果量级再大十倍怎么办?"
这类题有意思的地方在于,它没有一个绝对标准的答案,面试官想看的是你思考的路径。一个技术方案你做过就是做过,没做过当场编很容易露馅。但反过来,就算你没做过,只要你思路清晰、边界意识强、排查路径合理,照样能拿不错的分数。
1.2 面试官如今最看重三种能力
我观察下来,2026年这轮面试筛选出的候选人,普遍具备三种能力:
第一是解释"为什么"的能力。会用computed谁都会,但为什么它比watch更适合做派生数据?这个就需要对响应式原理有认识。第二是边界意识。一个方案说起来头头是道,但一问"并发量到了什么量级会崩?"、"内存会有什么压力?"就卡壳,说明施工经验不到位。第三是事后复盘的能力。这不是让你背一篇"复盘报告",而是看你叙述踩坑经历时的表述习惯,能不能从现象快速收敛到原因,再沉淀成一个可复用的判断标准。
这三个能力对应到准备阶段,意味着你不能再靠"背题"过关。更多的时间要花在把每个知识点真正做一遍、推演一遍,形成自己的理解框架。后面这五道题,基本就是按这个逻辑展开的。
2. 真题一:渲染流程的追问链,能探到哪一层
"从输入URL到页面展示,发生了什么?"
这道题大家应该都很熟了,属于前端面试里的"老牌名菜"。但这两年它的考察方式明显变了。你要是只从头到尾背完"DNS解析、TCP连接、HTTP请求、HTML解析、CSSOM、渲染树、布局、绘制",面试官基本会在你说到一半的时候开始追问,追到你说不出来为止。
2.1 从主流程答到合成层,才算触及"高分段"
我发现很多候选人对前半段(网络请求、HTML解析)讲得非常流畅,一到"渲染"这里就开始笼统了。真正的高分回答,会把渲染流程拆成两个线程维度来讲:主线程和合成线程。
主线程负责解析HTML、构建DOM树、解析CSS构建CSSOM、生成布局树、绘制记录(Paint Record)。合成线程则负责把内容分成多个图层(Layer),然后进行光栅化和合成,最终呈现到屏幕上。
为什么要分开?因为后续很多性能优化概念——transform、opacity、will-change——全部跟这个分层有关系。你如果一张嘴就是"DOM树→CSSOM→渲染树→布局→绘制",那说明你对"合成"这个环节没有概念。面试官会自然地认为你对渲染性能的理解停留在表面。
2.2 高频追问"为什么transform比left高效"的标准姿势
这是渲染题里最常见的追击问题。很多人会脱口而出:"因为transform不触发重排。"
这个回答不够准确。left改变的是布局属性,改一次就要从布局阶段重新走一遍,确实会触发重排重绘。但transform不一定完全不触发重绘——它只是通常不会触发布局和绘制阶段,而是让元素进入自己的合成层,由合成线程来处理变化。所以严谨的说法是:transform动画可以把元素的变换交给合成线程处理,绕开主线程的布局和绘制步骤,从而减少主线程的负担。
这里有个值得说的细节:并不是任何元素用transform都能享受到合成层待遇。还要满足一些条件,比如没有复杂的内容变化、层不会被频繁重绘等等。不然浏览器觉得你这个层不值得单独建,那动画可能还是在主线程跑。面试里如果能补上这一层"条件性"说明,面试官一般会觉得你是真做过动画优化的。
2.3 这道题最容易被问倒的一个点:will-change
"那will-change: transform呢?是不是加上就万事大吉?"
这个问题我在面试里问过很多次,能答好的人不多。will-change的作用是提前告诉浏览器"某个元素接下来可能会改变",让浏览器提前给它创建合成层,从而避免变化真正发生时来不及准备。但滥用它有个很现实的后果:每个合成层都要占用一定的内存和GPU资源。如果一个页面里几百个元素都加了will-change,图层的数量会爆炸,反而导致性能下降。
所以标准答案应该是:will-change要小范围、适度地用,而且用完之后在不需要的时候最好移除。尤其是动画结束后还留着,等于让浏览器白养一批图层。
注意:这道题表面在考
will-change,实际是在考你对"合成层是有成本的"这个底层概念的认知。面试官不会直接告诉你他想要这个答案,但你答到这个层面,对话质量就会立刻不一样。
3. 真题二:大文件上传,别只讲"切片+并发"
"如果要实现一个支持断点续传、秒传的大文件上传,你的方案是什么?"
这是最近两年出现频率非常高的实战题。原因也很简单,业务里真的会遇到:上传视频、上传设计稿、上传报表数据,几百MB甚至几个G的文件越来越常见。而且这道题考察面很广:文件操作、异步并发、浏览器线程、前后端配合,每个环节都能深挖。
3.1 完整方案的八个模块,缺一个都会被追问
一个能在生产环境上线的方案,至少包含八个模块:
- 分片切割:用
File.slice()把大文件切成多块,避免一次性把整个文件读入内存。 - 文件指纹:计算整个文件的唯一哈希值,作为文件在服务端的标识。
- 分片校验:每个分片有独立的序号和哈希,方便服务端校验完整性。
- 并发控制:不能一次性把所有分片全部发出去,要限制同时上传的数量。
- 断点续传:上传前先向服务端查询"已收到哪些分片",跳过已上传的。
- 秒传:服务端发现指纹相同且文件已完整存在,直接返回上传成功。
- 进度汇总:把每个分片独立的上传进度合并成全局进度。
- 失败重试:对上传失败的分片进行单独的重试,不能因为一个分片失败就全部重来。
答题的时候如果只说"切片、并发、断点续传"六个字,面试官会认为你只了解一个大概。最好能把上面这些模块串成一条完整链路讲出来:切割 → 计算指纹(Worker里做)→ 服务端问询 → 过滤已上传分片 → 并发上传 → 全部完成后通知服务端合并 → 展示进度。
我给一个非常简化的框架代码,帮你建立这个链路的感觉:
async function upload(file) { const CHUNK_SIZE = 5 * 1024 * 1024; // 5MB const chunkList = []; let cur = 0; while (cur < file.size) { chunkList.push(file.slice(cur, cur + CHUNK_SIZE)); cur += CHUNK_SIZE; } const fileHash = await calcHashInWorker(file, chunkList); // 交给Worker计算 const { uploadedList } = await queryUploaded(fileHash); // 断点续传问询 const remainList = chunkList .map((chunk, index) => ({ chunk, index })) .filter(({ index }) => !uploadedList.includes(index)); await concurrentUpload(remainList, 5); // 控制并发数 await notifyMerge({ fileHash, fileName: file.name }); }这个框架的背后逻辑,建议你自己在本地跑一遍,实践过以后,这道题就会变成你的加分题。
3.2 哈希计算的三种优化思路,worker只是入门
大文件上传最耗性能的步骤往往不在上传本身,而在于算哈希。
如果你直接在主线程对一个大文件做 MD5 或 SHA-1 的计算,页面会直接卡死。所以最基础的优化是把它放到Web Worker里:
// worker.js self.onmessage = async (e) => { const { file } = e.data; const hash = await calculateFileHash(file); // 逐块读取并累加hash self.postMessage({ hash }); };这是第一步。但"放到Worker里"并不能解决所有问题,因为大文件整体哈希依然要读完整个文件,速度还是受限于磁盘读取和哈希算法本身。于是还有两个常见的优化思路:
一是增量哈希。不直接对整个文件计算哈希,而是先对每个分片计算哈希,再把分片哈希汇总成一个总哈希。这种方式天然适合分片架构,而且失败重试时还能用分片哈希做局部校验。
二是抽样哈希。取出文件的前、中、后若干个片段参与哈希计算,用"代表性数据"来近似生成文件指纹。这个方案速度极快,但理论上存在极小概率的冲突。它更适合对准确性要求不那么苛刻的场景,比如内部系统的秒传校验。面试如果聊到这里,你要主动说出这个方案的"风险边界",这会让面试官觉得你考虑问题很全面。
3.3 生产环境里那些"面试不会考但必须知道"的坑
聊几个实际项目里踩过的坑。
第一是分片大小怎么定。常见默认值 5MB,但是否合理取决于你的服务端网关限制、并发数量和网络环境。如果内网带宽很大,可以适当调大分片;如果走公网且网络不稳定,2MB~5MB 更稳妥。面试时可以提一句:分片大小不是一个固定的值,需要根据场景测试调整。
第二是并发数到底开多少。开太多并不会一直加速,反而可能触发浏览器对同域名的连接数限制,或者把服务端的连接池打满。我自己常用的经验是 3~5 个并发,再高就要看服务端能力了。
第三是失败重试与断点续传的关系。断点续传解决的是"重新打开页面还能续上"的问题,失败重试解决的是"瞬时网络波动"的问题。两者是不同层级的容错,不能混为一谈。
注意:很多候选人在讲这个方案时,容易把"断点续传"理解成"上传过程中刷新页面,下次打开还能继续"。实际上断点续传的核心是服务端记录了已上传分片的清单,客户端通过问询接口拿到进度后跳过已上传部分。理解到这个层面,追问才不会被绕晕。
4. 真题三:微前端的公共依赖与隔离,别只背概念
"聊聊你们为什么引入微前端?如果直接用 iframe 会怎样?"
微前端这个方向,现在基本是高级岗位面试的常客。很多人对微前端的理解停留在"iframe 太重、刷新状态会丢"这个层面,然后开始背 qiankun 的 API。但真正有经验的面试官,一般会顺着往下追问三个具体问题:公共依赖怎么处理、JS 沙箱怎么选、样式隔离怎么做。
4.1 开场白细节:为什么"不用iframe"也能答出层次
其实"iframe 不行"不是一个绝对结论。iframe 的优势非常明显:天然隔离、简单可靠、不受主应用样式影响。至今仍有很多业务场景——比如第三方组件嵌入、外部系统接入、支付页面——就直接用 iframe 解决。
它的问题在于:刷新页面后 iframe 内部路由状态不好恢复;弹窗和遮罩容易被限制在 iframe 区域内部;跨 iframe 通信需要走postMessage,链路复杂以后很难维护;而且每个 iframe 都是一套独立运行环境,内存开销更大。
如果你的开场白是"iframe 也可以,但要看具体场景",然后再落到"单页应用注册中心、依赖共享、状态同步这些诉求下,iframe 处理起来更麻烦"——这个层次感,比直接说"iframe 是垃圾"要高明得多。
4.2 公共依赖三套方案对比:MF、externals、npm包
微前端拆分以后,多个子应用都会用到 React/Vue、路由库、组件库这些公共依赖。如果每个子应用打包一份 React,整体体积会非常大,而且实例不共享,内存浪费也很明显。
主流的做法大致有三种:
| 方案 | 核心思路 | 优点 | 缺陷 |
|---|---|---|---|
| Module Federation | 运行时加载共享模块,由构建工具独立打包和解析共享依赖 | 版本控制灵活,按需共享,Webpack 5 原生支持 | 构建配置复杂,概念多,排查问题难度大 |
| externals + CDN | 公共依赖不打入子应用包,通过 script 标签加载全局版本 | 简单直观,子应用包体积最小 | 版本升级需要全局控制,依赖全局对象容易产生冲突 |
| npm 包独立发布 | 把公共代码抽成独立的 npm 包,子应用各自依赖 | 使用者感知最弱,普通的依赖管理思路 | 多子应用之间容易出现不同版本同时存在的状态,升级要分批发版 |
我个人的判断是:如果团队从零开始设计,优先评估 Module Federation,因为它解决"共享依赖版本统一"这个问题更彻底,而且支持运行时加载,不用走发版链路。但如果现有架构已经很重,只是想把一两个老项目接入微前端,externals + CDN 更能控制成本。
4.3 沙箱与样式隔离:快照和Proxy选型的真实逻辑
JS 沙箱最常讨论的是两种:快照沙箱和Proxy 沙箱。
快照沙箱的思路是:子应用激活时,把window上的属性全部保存一份快照;子应用卸载时,把运行过程中被改动过的全局属性还原。它的优点是实现简单、兼容性好;缺点是不能支持多实例共存——两个子应用同时激活的时候,快照到底以谁为准?很尴尬。
Proxy 沙箱的思路则是:给子应用伪造一个代理window,子应用读写全局属性时实际读写的是这个代理对象,完全不影响真实window。这让多实例、多子应用共存变成可能。但它的成本在于要维护代理对象与真实对象之间的关系,且对旧浏览器的兼容性要注意。
在真实项目里,如果你的主应用是"一个时间只激活一个子应用",快照沙箱完全够用;如果你有多个子应用同时可见的需求,就要用 Proxy 沙箱。不要盲目追新,方案取舍要基于实际场景。
样式隔离这块也容易踩坑。CSS Modules 只能解决子应用内部的类名问题;如果子应用一进来要把一些全局样式(比如body背景色)改了,那就得靠约定和规范来约束,再加上动态style标签的插入与卸载管理。Shadow DOM 能提供更严格的隔离,但很多组件库的弹窗是通过document.body挂载的,一进 Shadow DOM 就找不到外层上下文,所以它反而更容易引入新问题。
5. 真题四:AI都能写代码了,面试官为什么死磕调试思路
这两年我面试人的时候,越来越喜欢问一个问题:
"如果你用 AI 辅助写了一个模块,上线后线上反馈有问题,你的排查思路是什么?"
这个问题听起来简单,但考察的维度非常多。AI 工具(不管叫什么名字)提高了代码产出效率,但它不代表你能免掉代码审查、调试和验证的环节。面试官真正想确认的是:工具生产了大量代码,你怎么保证代码质量?出了问题,你能不能从一团乱麻里快速定位?
5.1 一个现场复盘:SSE推送线上断连的完整排查链路
我常用一个很具体的线上场景来考察候选人:服务端用了 SSE(Server-Sent Events)往页面推送实时数据,本地联调一切正常,部署到线上之后过一段时间连接就会自动断开。你会怎么排查?
这个场景能同时考察:HTTP 连接模型、SSE 协议特性、代理层和网关的配置习惯、以及问题分级排查的思路。
一个合理的排查链路应该是这样的:
- 先观察现象:断开的时间点是否有规律?是固定几分钟就断,还是长则不规律?这决定了你可能要去查哪个方向。
- 看客户端状态:浏览器的 Network 面板里 EventStream 请求是什么样的?服务端最后一次发送数据的时间和断开时间差多少?
- 怀疑代理层:线上环境一般都有 Nginx 或云厂商的负载均衡。有些代理组件默认会缓存响应,SSE 这种需要实时推送的长连接,一旦被缓存,客户端接收到的数据就可能是“卡住”的;有些代理组件有
proxy_read_timeout之类的超时设置。SSE 本身设计上有心跳机制,但如果你在服务端没有实现周期性发送注释心跳,代理层会因为一段时间内“没有数据流动”而主动断开连接。 - 验证假设:本地用 curl 模拟连接,观察连接是否在同样时间断掉;或者查代理日志,看断开时是不是代理返回了超时。
- 修复与验证:在服务端加上定时心跳,调整代理缓冲配置,然后回归验证连接持续时长。
- 复盘沉淀:把"SSE 必须有心跳"、"代理层可能改动连接行为"这两个判断写进团队的排错手册。
这个链路里,"先观察规律 → 再怀疑代理 → 验证修复"是一个朴素的排查骨架,重点不是每个环节都踩过,而是你能有条理地推进。很多人只答一句"可能被断开了,加个重连机制",这就没有展示出排查能力。
5.2 这道题背后真正考察的工程素养
这道题真正考察的是三个点。
第一,你懂不懂协议本身。SSE 是单向长连接,它有自动重连机制,但触发重连的条件和心跳间隔强相关。如果你连EventSource的自动重连行为都不清楚,解决这个问题大概率会靠"堆代码"来补救。
第二,你知不知道问题可能在链路的哪个位置。很多初级工程师一上来就改前端代码,加各种重试逻辑。但如果根因是代理层超时,你改完前端只是表面上解决了,后端连接其实还是断的。有经验的人会先做分层定位——客户端、服务端、代理层、网络层——每层找证据。
第三,你怎么看待 AI 生成的代码。AI 工具能帮你快速写出一个 SSE 客户端,但它不会告诉你线上还挂了个代理层。能不能识别出"AI 交付的代码里,哪些部分是可靠的原语,哪些部分依赖外部环境假设",这本质上是工程判断力的问题。
注意:如果你面试时遇到类似场景题,哪怕实际没做过,也可以先从"我会先确认哪些信息、再看哪些指标、接着验证什么假设"这个角度组织回答。这种回答方式,比直接说"我不会"要加分得多。
6. 真题五:性能优化,从"清单体"进化到"数据驱动"
"聊聊你做过的一次性能优化。"这是老牌问题。但这两年面试官开始反感那种"清单体"回答——图片懒加载、路由懒加载、资源压缩、CDN 加速,列完一排四五个,感觉像在背优化手册。真正有区分度的回答,必须有一个完整的"量化-定位-优化-验证"闭环。
6.1 指标先行:LCP、INP、CLS这些数字代表什么
性能优化第一步不是优化,而是定指标。没有指标,你连"优化成功"都说不清楚。
现在比较常用的核心指标包括:
| 指标 | 全称/含义 | 它反映的问题 |
|---|---|---|
| LCP | Largest Contentful Paint,最大内容绘制 | 用户能看到主要内容要等多久 |
| INP | Interaction to Next Paint,交互到下一帧绘制 | 用户点击/输入后页面响应的延迟 |
| CLS | Cumulative Layout Shift,累积布局偏移 | 页面加载过程中内容是否跳来跳去 |
| TTFB | Time To First Byte,首个字节到达时间 | 网络链路和服务端的响应速度 |
| FCP | First Contentful Paint,首次内容绘制 | 白屏时间的近似体现 |
如果候选人说到性能优化时第一个提到的还是 "图片懒加载" 而不是 "LCP、INP 这些指标先量化",我基本能判断他之前做优化大概率是"感觉有效"而不是"验证有效"。
6.2 一个报表页面的优化全程:从2.8s到1.2s
举个例子,我之前优化过一个报表页面,线上 LCP 长期在 2.8s 左右。整个过程可以分成四步:
第一步是量化。用 Lighthouse 和 Performance API 分别采集实验室数据和真实用户数据,确认 LCP 的瓶颈在哪里。通过 Performance Timeline 发现,TTFB 占了 1.1s,图片加载占 0.8s,脚本执行占 0.5s,其余是样式计算和渲染。
第二步是定位根因。TTFB 高是因为报表接口是串行调用的,必须先查用户权限,再查数据源,最后聚合返回。虽然接口逻辑是服务端的锅,但前端可以通过并行请求和接口聚合减少一部分等待时间。图片加载慢是因为一个大背景图没有任何优先级标记,浏览器默认对齐低优先级;脚本执行长是因为首屏路由懒加载没有真正生效,主包把整个图表库都打进去了。
第三步是针对性优化。前端这边主要做了四件事:请求并行化、给背景图加上fetchpriority="high"、彻底验证并修复路由级代码分割、把图表库改成按需引入。这个过程中要让测试同学配合回归,尤其是懒加载改完之后,不能出现点击某个路由才发现的"白屏"问题。
第四步是验证与回归。优化后再用同一套工具采集数据,LCP 降到了 1.2s,并且浏览 Performance entries 确认主要耗时分布已经变化。再观察一段时间的线上 RUM 数据,确认没有回升。
这套流程里面有非常多细节,但面试时讲"四步走"已经足够了。关键要让面试官感受到:你不是凭感觉做优化,而是有一套测量、定位、验证的方法论。
注意:"首屏性能优化"和"接口变快了"是两个层面的东西。很多候选人把优化结果全归功于服务端接口提速,前端优化一笔带过。这种回答听上去像在炫耀别人的功劳。优化动作要和结果强相关,越能展示"这个改动直接对应那个指标的改善",越有说服力。
7. 收尾环节:反问和项目复盘才是真正的"加分题"
很多候选人前面技术题答得不错,一到面试末尾就开始松懈。其实最后五分钟的反问环节,以及面试过程中随时可能被问到的项目复盘,往往决定了你在面试官心里的最终印象分。
7.1 反问环节的三种"取分"姿势
反问环节最怕的是问出"咱们加班多吗""公积金怎么交"这类问题。不是说这些问题不能问,而是在技术面阶段问这些,会冲淡前面好不容易建立的专业形象。
比较好的反问方向包括:
- 团队的工程化建设处于什么阶段,比如 CI/CD、监控告警、代码生成工具的使用程度。
- 前端团队在需求评审中的话语权如何,设计稿是纯交付还是能参与交互方案的讨论。
- 团队对线上质量的定义,有没有核心指标的看板,会不会定期做性能评审。
这三种问法背后,都在暗示你是一个关注工程质量、有长期发展意识的开发者,而不是一个只关心"给多少钱、加不加班"的螺丝钉。
7.2 项目复盘怎么讲才不像在念流水账
项目复盘题看似随意,其实很有讲究。常见的失败版本是:"我们这个项目做了 X、Y、Z,我用到了 A、B、C 技术,遇到了一个 bug,最后解决了。" 这种讲法信息密度太低。
更好的复盘框架是:
- 背景:项目为什么存在,核心解决什么问题,这个业务的约束条件是什么。
- 方案选型:你面对的关键决策点是什么,当时有哪些候选方案,你为什么选这个,对比的维度是什么。
- 落地过程中的问题:不是流水账式罗列,而是挑一两个最有代表性的问题,讲清楚排查和解决的完整思路。
- 效果验证:你怎么知道做成功了,用哪些指标证明。
- 反思:如果再来一次,哪里可以做得不一样。
比如你做了个组件库性能优化,只讲"我用了虚拟列表"就很单薄。如果按上面的框架讲,就变成:某个长列表页面从数据量和渲染成本两个维度评估后,认定虚拟列表是性价比最高的方案;对比了react-window和自研方案的差异;实现过程中发现列表项高度不稳定导致滚动跳动,于是用占位测量+动态缓存解决;优化后白屏时间或滚动帧率有了具体数据;最后反思如果当时直接用了某项浏览器内置能力,可能开发量更小。
这样的复盘,才是一个有经验的工程师应该有的叙事方式。
最后分享一个我个人的习惯:每次面试结束后,我会随手记下候选人身上一个让我印象深刻的点——不管是技术上的亮点,还是表达方式上的问题。时间长了以后我发现,能留下印象的人往往不是那种"每个题都答得完美"的人,而是那种遇到没做过的题,也能坦诚地说"这个我没实际做过,但我的排查思路是……"的人。面试官也是人,没见过的东西太多了,坦诚加上清晰的思路,比硬撑一个明显编造的方案要值钱得多。如果你正在准备下一轮面试,多练一练这种"面对未知问题时组织思路"的能力,它才是面试场上真正通用的硬通货。