ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Shopee前端面经:一年半经验从投递到Offer的全流程复盘

Shopee前端面经:一年半经验从投递到Offer的全流程复盘 去年秋招的时候我面了 Shopee 的前端岗位整个过程从投简历到拿 Offer 差不多持续了一个月。当时我的工作经验刚好一年半说长不长说短不短既有一定的项目积累又还没到能独当一面的资历正好处在一个比较尴尬的节点。面完之后复盘了一下感觉整个过程还挺有代表性的所以把这段面经整理出来给同样在准备前端面试、或者正在观望机会的朋友做个参考尤其是那些工作经验一年到三年之间的同学应该能从中找到一些共鸣。这一年半里我主要做的是 PC 端管理系统和部分 H5 页面技术栈以 React 为主也用过 Vue算是比较典型的中后台前端开发。Shopee 这边整体技术栈也是 React 居多所以面起来还算匹配。下面我会从投递前的准备、面试流程、高频题目复盘、系统设计题的打法以及新人容易踩的坑这几个维度来聊尽量把细节写清楚方便你对照着准备。1. 面试前的一个月我是怎么复习的1.1 先把简历上的每个项目都“过一遍”说实话很多同学挂在一面不是因为技术不行而是被问到自己项目的时候讲不清楚。面试官问到的第一个问题几乎永远是“你介绍一下你最近做的项目”这里绝对不能只描述业务模块比如“我做了一个订单管理系统里面包含 XX 模块”这种回答没有任何信息量。我在准备阶段把简历里三个项目分别写了一份“项目说明书”结构是项目背景、我的职责、技术方案选型、核心难点、最终成果、可优化的点。每一条我都会按照“因为什么原因 - 所以做了什么选择 - 带来了什么结果”的逻辑去写。比如我在做后台管理系统时当初选择用纯 React Umi 而不是 Next.js是因为这个系统不涉及 SEO而且团队对 Umi 的约定式路由比较熟开发效率更高。这种决策层面的思考面试官非常喜欢听。一个很重要的经验面试官问项目通常不是为了考核你用了什么框架而是想通过项目了解你的技术判断力和边界感。所以不要只把技术列表背出来一定要讲出“我为什么没有选另一个方案”。1.2 算法突击刷题要有空窗期的自觉一年半经验的前端去面试算法一般不会太难但也不能完全裸考。Shopee 和国内大厂不太一样对算法的要求属于“不能太差就行”的水平不过面试官会通过算法题看你的代码风格和边界处理能力。我当时花了两周时间刷了大概 60 道题集中在数组、字符串、链表、二叉树和简单动态规划上。我没有按题号刷而是按考点去刷每个类型找 10 道左右总结出通用的解题模式比如数组类题目先想双指针能不能解决字符串类题目优先考虑哈希表记录频率二叉树题目基本绕不开递归、层序遍历动态规划不会就直接跳面试很少考很难的 DP准备期间我每天保持 3 道题的节奏并且每道题都用“先讲思路再写代码最后优化”的顺序来练习。这个习惯等到面试时帮了我大忙因为写代码的时候如果你能同步说出思路面试官会明显更认可你。1.3 八股文要背但不能死背网上流传的前端八股文合集我还是认真过了一遍的但我的建议是不要逐字逐句背答案而是要把核心概念用自己的话说出来。比如“React 的 setState 是同步还是异步”这道题背答案是“在合成事件中是异步的在原生事件中是同步的”但这个答案其实并不完整。我更推荐用一个场景来理解当你在事件回调中连续调用三次 setState 并传对象时React 会进行一次合并更新如果传的是函数React 会按顺序执行三次只是最终渲染一次。用这种代码示例结合结论的方式去记忆面试时即使扩展追问也不慌。所以我在复习八股文的时候基本上每个知识点都会自己写一个最小化代码示例验证一下结论是否准确。这个过程既加深了记忆也避免了面试时“知其然而不知其所以然”的尴尬。2. 面试流程全记录从投递到 Offer2.1 整体时间线Shopee 的流程分为简历筛选、在线笔试、两到三轮技术面、一轮 HR 面整个周期我在一个月内全部走完。第一轮是初筛电话面主要了解基本情况笔试是在线完成接下来是两轮技术视频面最后是 HR 沟通。这里提醒一下不同团队可能面试轮数略有不同有些人会有交叉面有些人没有。我当时是两轮技术面加一轮 HR可能是因为一年半经验的定位不需要走太复杂的流程比较节省时间。2.2 笔试环节四道题三个小时在线笔试用的是一个常见的外企笔试平台限时 3 小时共四道题。难度上比国内互联网的校招笔试要温和不少但依然需要认真对待。我记得题目类型大概是这样的一道数组相关的题给一个数组和一个目标值要求找出和为目标值的连续子数组这道题可以用前缀和加哈希表优化如果直接暴力双层循环过不过就看测试用例的力度了一道是二叉树层序遍历常规题LeetCode 上面一模一样的题一道是字符串处理的题比如判断括号是否合法还有一道偏场景的题目让你模拟一个任务队列按优先级执行异步任务并支持取消操作。笔试的代码环境本身不带自动补全所以写代码时要特别注意大小写和变量名。我是提前在本地 IDE 里把常用模板比如二叉树节点的定义、快慢指针、DFS 模板练熟然后复制到在线平台上。笔试过程中如果某些测试用例没过先不要急着改把已有的通过用例跑完再确定是边界问题还是算法问题。2.3 技术一面的考察重点技术一面是一个前端工程师面的时长一个半小时。开头五到十分钟是对上过简历的项目进行简单了解然后进入技术问题环节最后是一道代码题。一面比较侧重于基础知识的广度和工程实践能力。我被问到了浏览器从输入 URL 到页面展示的全过程事件循环、宏任务和微任务的区别React 的调和、Fiber、合成事件性能优化相关如何定位首屏和白屏时间怎么去做优化这里我记得很清楚的是面试官特别爱追问“为什么”。比如我说到在浏览器输入 URL 后会先进行 DNS 解析面试官会追问“DNS 解析的流程是什么浏览器会缓存吗缓存了多久如果 DNS 解析失败有哪些可能原因”这种连续追问是最容易出局的环节好在我提前把每一层都剥开准备了。代码题是一道“防抖节流”的变体要求实现一个带有最大等待时间的节流函数也就是不仅要在高频触发时限制执行频率还必须保证最后一次触发最终一定会执行。这道题日常开发中很常见但真的要现场写对还是需要先把防抖和节流的原理搞清楚然后再去处理“保证最后一次执行”的逻辑。2.4 技术二面的深度和系统设计技术二面是更资深的工程师来面时长同样在一个半小时左右和一面不同二面更看重你在设计和架构维度的思考。一面考你会不会用二面考你会不会选、会不会权衡。二面一开始先聊项目的深度问题我挑了一个权限管理的模块来展开从后端返回的权限树怎么在前端处理到按钮级别的权限控制怎么实现再到权限变更后的及时更新怎么做。面试官顺着聊又问到了如果团队里多个前端项目需要复用同一套权限逻辑你会怎么设计。这个问题其实就是想考察你对微前端和组件库设计的理解。后面还有几道场景题如果现在需要设计一套支持多层级表头的 Excel 导入组件你会怎么设计它的数据结构和算法复杂表单页的校验逻辑如何抽离校验规则可以动态配置页面数据量大导致卡顿你如何定位原因并制定优化方案这些题目并不要求你现场写完整代码但要能提出合理的方案并且思考到边界情况。在这里“会讲故事”变得格外重要你需要在规定时间内组织好语言的逻辑并能让面试官觉得你有全局意识。2.5 HR 面聊薪资和职场预期HR 面相对轻松但也不是纯粹聊天。会问到当前薪资情况、期望薪资、为什么想要换工作、对加班的态度、未来三到五年的规划等。这里我的建议是提前想好一个“离职原因版本”不要踩前公司的缺点尽量从个人成长角度出发比如“当前项目技术栈比较传统我希望在更有挑战的技术环境中成长”。如果 HR 问期望薪资可以给一个合理范围而不是固定数值并且能在范围内说明依据。我当时是参考了市场上一年半经验前端的普遍薪资结合自己的项目积累给的期望整体比较顺利。3. 高频题目复盘这些题我记了很久3.1 React 核心问答别再背答案了React 几乎是我面试中占比最大的一块这里把几个高频题和我的回答思路展开说一下。第一个是“React 的 key 有什么用”。这个问题看似简单但展开讲可以很深入。如果列表重新排序没有 key 时 React 会把同层节点依次比对一旦条数不对就会发生大量复用的错乱导致状态错位。正确回答是需要覆盖三个层面一是声明式列表更新的重要标识二是优化 diff 过程让 React 可以复用原节点而不是重建节点三是如何正确选择 key避免使用数组下标。面试官如果追问“为什么不能用数组下标”就解释当列表发生插入、删除、排序时index 会变从而导致同一个 key 对应的实例和之前不是同一个容易引发状态错乱。第二个是“React 的渲染流程”。我习惯从更新触发开始讲setState 触发后进入调度阶段React 会计算出哪些组件需要更新然后进入 render 阶段生成新的 React Element tree接着进入 commit 阶段把变更应用到真实 DOM。顺便提一下 Concurrent 模式下的优先级调度让高优先级任务可以先中断低优先级任务这样解释可以体现出你对现代 React 的理解。第三个是“Fiber 是什么”。重点是 Fiber 是一个普通的 JavaScript 对象但链表式的结构让 React 可以保留每个节点的引用从而可以中断和恢复渲染工作。简单类比就是以前只能一口气干完现在可以干到一半先出去接个电话再回来接着干这个能力就是增量渲染的基础。3.2 手写题专题基础能力一测便知一年半经验的前端手写题大概率不会太难但很吃基本功。我遇到过的以及面试圈里高频的题目主要有这几个手写一个 Promise.all。这个我强烈建议任何准备面试的人都练一下因为它考的不只 Promise还有对异步并发处理的理解。我当时的实现思路是接收一个可迭代对象返回一个新的 Promise遍历所有元素用 Promise.resolve 包一层确保所有项都是 Promise记录已完成的数量和结果数组当所有项都完成时 resolve 结果数组只要有一项 reject就立即 reject。简单版本可以这样写Promise.myAll function (promises) { return new Promise((resolve, reject) { const results []; let count 0; const len promises.length; if (len 0) { resolve(results); return; } promises.forEach((item, index) { Promise.resolve(item).then((value) { results[index] value; count; if (count len) resolve(results); }, reject); }); }); };注意这里结果数组的下标一定要用原 index 来存不能 push因为异步任务完成的顺序是随机的如果用 push 会导致结果顺序错乱。手写深拷贝。这个题要求的是“在面试环境的限制下写出一个尽量完整的实现”。核心是处理循环引用否则对象中有循环引用时会直接爆栈。一般用 WeakMap 来存储已拷贝过的对象遇到就返回已有拷贝避免死循环。还可以处理 Date、RegExp、Map、Set 这类特殊类型并且 Symbol 和函数一般直接引用原值即可。不推荐面试时直接把 lodash 源码的 cloneDeep 背出来太长而且面试官更想看你自己如何建立边界意识。手写防抖和节流。这两个几乎人手一份八股但面试官会变着法考比如“防抖有立即执行版本吗这个版本的参数和 this 怎么处理”我当时写的一个带立即执行的防抖function debounce(fn, wait, immediate false) { let timer null; let isInvoked false; return function (...args) { const context this; if (timer) clearTimeout(timer); if (immediate) { if (!isInvoked) { fn.apply(context, args); isInvoked true; } timer setTimeout(() { isInvoked false; }, wait); } else { timer setTimeout(() { fn.apply(context, args); }, wait); } }; }反正核心就是搞清楚防抖是把多次触发合并成一次且只保留最后一次节流是保证一段时间内至少执行一次。能讲清楚它们的场景比如搜索输入用防抖、滚动监听用节流这个题就不慌。3.3 浏览器原理和前端性能优化浏览器相关的题目非常容易变成连环问我在面试中就被这样追过“浏览器输入 URL 到页面展示发生了什么”这个问题我一般回答时会把它拆成网络链路、渲染链路和主线程链路三个阶段。网络链路里要清楚 DNS 解析、TCP 连接、TLS 握手、HTTP 请求和响应渲染链路里要讲 HTML 解析成 DOM 树、CSS 解析成 CSSOM 树、合并成渲染树、布局、绘制、合成主线程链路里要提到脚本阻塞、事件循环、异步加载方式。讲到 HTTP 的时候面试官顺口问了 HTTP/1.1 和 HTTP/2 的区别这里又是一个容易展开的小专题。重点可以提到多路复用、头部压缩、二进制分帧、服务端推送以及 HTTP/2 仍然存在的队头阻塞问题TCP 层面的。性能优化方面我被问到过“首屏优化怎么做”。常见的回答方向有资源体积优化JS/CSS 压缩、Tree Shaking、Code Splitting、网络优化CDN、HTTP 缓存、预加载预连接、渲染优化骨架屏、SSR 或预渲染、加载策略路由级懒加载、图片懒加载、按需加载等。如果能再补充一个你实际项目中用到的优化方案和优化前后的数据对比这道题就能答出亮点。4. 系统设计题和场景题怎么展开4.1 组件库设计级联选择器的数据结构怎么定系统设计题一般不会让你从零设计一个完整微前端框架更多是贴近业务的下沉组件或模块设计。我印象最深的一道题是“如果让你设计一个支持搜索、多选和级联关系的城市选择组件你会怎么做”。这道题面试官想考察的核心是数据设计和组件接口设计而不是 UI 细节。我的思路是先定义输入数据格式一张大概长这样的树形结构const cityData [ { code: 110000, name: 北京市, children: [ { code: 110101, name: 东城区 } ] } ];再定义 props考虑 value 的格式是 string[] 还是 object[]是否支持清空、是否支持搜索、搜索时是对全路径匹配还是只匹配当前节点、级联面板的展开策略是什么。整体我用“可控组件”的思路来设计value 和 onChange 由外部传入内部状态只负责面板的展开和搜索关键词这样组件就保持“受控”的稳定性。这道题得分的关键是你要能够主动设计整个组件的 API 和交互边界而不是等面试官一个问题一个问题的逼问。主动交代“如果数据量很大我会用懒加载而非一次性拉全量”这种思路会明显加分。4.2 微前端改造老项目迁移怎么规划微前端在今年的前端面试里高频出现几乎必问。我准备的思路是这样首先介绍微前端的核心理念也就是“技术栈无关、独立开发、独立部署、增量迁移”。然后讲常见的方案qiankun 基于 single-spa 的 JS 沙箱和 HTML EntryModule Federation 是 Webpack 5 的模块共享方案还有 iframe 方案能简单实现隔离但体验较差。面试官一般会追问“老项目要迁移到微前端你的切割边界怎么定”。我当时的回答是按业务域切割比如订单域、用户域、商品域各成一个微应用公共依赖React、UI 组件库、工具函数可以提取成共享依赖或者 federation 的 shared 模块主应用只保留布局结构、导航和路由注册功能。还要提前制定好样式隔离方案和公共状态管理方案比如用 qiankun 时建议各子应用之间尽量不共享状态需要跨应用通信时通过全局事件或主应用下发 props 来做。关于“为什么要上微前端”我个人的看法是如果你是跟随技术潮流那没必要但如果你确实有大量老项目需要共存、多个团队需要独立交付那么微前端是一个相对成熟的方案。这里要表达清楚“方案选型服务于工程现状而不是为了炫技”面试官很看重这个。4.3 场景题大文件上传和状态管理选型场景题里我一个印象深刻的是“如果一个大文件需要上传前端如何保证稳定性和可断点续传”。这个问题在真实业务中非常常见也容易考察出候选人的工程能力。我的回答思路是先明确大文件的痛点是单个请求大小限制、网络不稳定导致失败重传整个文件、进度展示不准确。然后讲分片上传的流程前端通过 File 对象的 slice 方法把文件切成大小固定的 chunk比如每个 chunk 5MB为每个 chunk 计算 hash可以用 spark-md5通过 requestIdleCallback 分批计算避免阻塞主线程后端接口支持分片上传前端逐个上传 chunk全部完成后调用 merge 接口后端合并分片并校验 hash。再补充断点续传上传前先调用接口查询哪些 chunk 已经上传成功只上传缺失的 chunk上传中可以显示分片进度网络中断后下次重新上传时直接复用已完成的 chunk。要注意如果是超大文件比如几个 GB前端还需要考虑并发数控制不要一次性几十个请求同时发起一般建议控制在 3-5 个并发避免打爆后端和用户带宽。这个细节很容易被忽略但讲了就会显得你很懂工程化。关于状态管理的选型题面试官问过我“你的项目状态管理方案是什么为什么选它”。我当时用的是 Redux Toolkit理由是我需要跨页面共享用户信息和权限信息并且需要在请求拦截器中读取 token同时页面的数据流比较复杂模块之间有较多联动。如果把这种共享状态完全写在组件内后期调试和维护成本会很高。面试官又问“会不会考虑用 zustand”我也聊了一下说如果是轻量项目或者共享状态不多zustand 更轻、写起来更少样板代码但团队如果已经熟悉 Redux 生态稳定性和调试工具会更好。这里不要只说一个正确答案要能对比不同方案说明在什么场景下选什么更合适。5. 一年半经验最容易踩的坑5.1 项目深度不够怎么用“侧面信息”补一年半经验很容易被大厂面试官挑出来的问题就是项目深度不够。比如你的项目就是切图写页面没有复杂的渲染性能问题没有高难度的组件封装也没有权限设计。如果简历上确实没有特别复杂的东西我的经验是不要硬编造但可以把“看似平淡”的点挖深一层。怎么挖比如你做过一个表格页你可以在项目描述里写“实现了基于虚拟滚动的十万条数据表格渲染方案”即使你当时只是用了 antd Table 的 virtual 属性你也要在准备面试时彻底搞懂虚拟滚动的原理是只渲染可视区条目还是保留一部分缓冲区滚动时是否会出现空白怎么根据 scrollTop 计算起点索引和终点索引。只要你能把这个点讲透面试官就不会觉得你只是“用过 API”而是真正理解了原理。还有一种方式是补充你遇到的“工程化问题”。比如项目分支混乱导致上线时合并了大量冲突你是否提过优化方案比如构建速度慢你是否分析过慢的原因并优化了构建配置。这类“软实力”同样能增加项目的丰满度而且是普通八股文覆盖不到的。5.2 手撕代码一定要养成“先讲思路再动手”的习惯面试中写代码时我最大的体会是面试官对代码的考察不只是“对不对”更是“你的思考过程”。如果你拿到题之后马上埋头写写完发现有 bug 再改虽然结果正确但面试官的印象会打折扣。正确的姿势是先花一两分钟想清楚然后把思路讲给面试官听确认方向正确后再动手。举个例子他给我出了一道“找两个有序数组的中位数”的题其实这题直接归并排序或者双指针也可以解但是时间复杂度不是最优。我第一时间想到的是这道题需要理解“二分查找两个数组的分割线”这个思路但鉴于面试场景和一年半经验面试官可能并不期望你能在十分钟内写对 O(log(mn)) 的写法他更看重的是你能不能用双指针的方式实现一个 O(mn) 的解法并且讲清楚为什么要找中位数。所以我当场就没去硬套最优解而是先告诉面试官“这道题最直观的思路是合并后找中位数但不需要真正合并可以用双指针遍历两个数组到中位数位置。如果要求跨过 O(mn) 的最优解可以用二分法来确定分割线。”面试官听完满意地点头让我写双指针版本。这种“对问题有判断力”的展示本身就是非常加分的能力。万一遇到你完全不会的题也不要直接说不会试着从暴力解法开始把最朴素的想法讲出来面试官一般会引导你优化。5.3 BQ 问题同样需要准备不能掉以轻心很多技术候选人容易忽略 BQ 问题觉得只要技术答得妙就行。其实对于一年半经验的候选来说HR 面和部分技术面里的 BQ 问题直接影响能不能拿 Offer。我遇到的一些 BQ 问题包括“你在项目中和后端或者产品意见不一致时怎么处理的”“如果需求上线时间很紧但测试发现了严重 bug你怎么决策”“你有没有推进过技术优化类的事情最终效果如何其他人怎么看”回答 BQ 问题我有个心得要讲具体事例按 STAR 法则来组织也就是情境、任务、行动、结果。不要泛泛地说“我会和团队沟通”而是要给出一个具体的项目背景你做了什么结果怎么样你从中学到了什么。比如我曾遇到产品要求在三天内上线一个营销活动页但按当前排期至少要五天我当时的做法是先评估核心功能与非核心功能把用户信息收集和表单提交作为 MVP 必须上把分享卡、UI 动效这些后置到一个版本然后和产品明确告知风险并约定好灰度范围和回滚方案。最后活动准时上线数据达标这次经历在面试中讲出来比说一百句“我有责任心”都管用。在 HR 面聊薪资缺口和离职原因时同样也要提前想清楚。我被问到“为什么想离开当前公司”时我的回答是“希望在更大体量的产品和技术团队中工作学习更体系化的前端工程化方案”。这样说既不会得罪前公司也表达了自己对成长的诉求。5.4 心态和节奏管理面试前一周做什么面试前一星期我建议不要再做新题也不要再看新的技术文章。当时我就踩过这种坑面试前三天看到一篇讲 ResizeObserver 的文章觉得写得很不错于是花了一晚上去研究结果导致当天的复习节奏全乱了还错过了把 React 调和过程完整串一遍的时间。后来我总结考前一周的核心任务是“保温”而非“冲刺”。把已经吃透的题目再在白纸上默写一遍尤其是手写 Promise、防抖节流、深拷贝把每个项目的项目说明书重新读一遍确保每条写出来的话都能自圆其说把高频八股文过一遍遇到不熟的先标记出来不要当场死磕按照实际面试的时间节奏模拟一次完整面试让自己的答题状态提前进入“面试模式”面试过程中如果遇到不会的内容也不要慌坦诚说“这部分我了解不深入目前我的理解是……”然后把自己的思路讲出来再补充一句“如果面试官能指点一下那就太好了”。面试官不会因为一道题没答上来就否定你他更在意你是不是有学习能力和自省意识。最后再分享一个小技巧我在面试过程中会随身带一个本子记录每一轮被问到的问题和当时回答的要点。面试结束后立刻复盘把答得不好的问题整理成文档重新查资料补充。这轮面试没答上来的问题往往就是下一轮面试的题目。比如我一轮面试中“DNS 缓存问题”回答得不太完整回去之后好好研究了一遍结果二面就又被问到了那次回答明显顺畅了很多。面试不仅仅是为了一个 Offer它也是一次非常高密度的自我扫描。把自己薄弱的地方暴露出来再针对性地修好这个成长速度比平时做三个月业务都快。希望这篇面经能帮到正在准备跳槽的朋友也祝你们都能拿到心仪的 Offer。
返回列表