React 前端中高级面试题集

针对上海缔歌科技「前端开发」岗位(16-20K·13薪,3-5年经验)整理的针对性技术面试题。覆盖 React / Next.js / TypeScript、性能优化、工程化、微前端、CI/CD、安全、监控与 A/B 实验等核心要求,每题均附参考答案与解析。

岗位:前端开发 薪资:16-20K · 13薪 经验:3-5年 文档生成日期:2026-09-19

React 核心与 Hooks

1

React 函数组件中,useEffect 的依赖数组容易出现哪些陷阱?如何正确避免闭包陈旧(stale closure)问题?

ReactHooks高频
参考答案

常见陷阱有三类:

  1. 依赖遗漏:只在 useEffect 里使用了某个状态/属性,但没写入依赖数组,导致回调中的值是旧的。
  2. 依赖过度:把对象、函数、数组直接放进依赖数组,因为每次渲染引用都变,导致 effect 频繁执行。
  3. 异步回调闭包:useEffect 里启动定时器或异步请求,内部读取的是“创建那一帧”的状态,造成 stale closure。

应对方案:

  • 使用 eslint-plugin-react-hooksexhaustive-deps 规则自动检查依赖。
  • 对会变化的函数用 useCallback,对会变化的复杂对象用 useMemo,保证引用稳定。
  • 如果只想监听某个“动作”而非状态值,可用 useRef 保存最新值,在 effect 中读取 ref.current;或者用函数式状态更新 setState(prev => ...) 避免依赖旧状态。
  • 清理副作用:异步请求要在 cleanup 中取消(AbortController / 取消标记),防止组件卸载后 setState。
解析

岗位要求“精通 React 框架及其核心理念(Hooks、Context、组件化思想、虚拟 DOM 等)”。这道题考察候选人是否能写出稳定、可维护的副作用代码,以及是否具备工程化 lint 意识,是 3-5 年经验面试的高频题。

2

useMemouseCallback 分别解决了什么问题?什么情况下不建议使用?

ReactHooks性能
参考答案

useMemo 缓存“计算结果”,避免昂贵计算在每次渲染时重复执行;useCallback 缓存“函数引用”,避免子组件因为收到新的函数 prop 而触发不必要的重渲染(配合 React.memo 使用)。

不建议使用的情况:

  • 计算成本很低:比如简单的字符串拼接、数组 map 生成 JSX,缓存的收益抵不过比较依赖的开销。
  • 依赖变化非常频繁:每次依赖都变,缓存命中率低,反而增加代码复杂度。
  • 过早优化:没有通过 React DevTools Profiler 或性能测试确认瓶颈,盲目加 memo 会让代码难以维护。
  • 函数只在事件回调中使用、不向下传递:可以直接在事件处理函数里写逻辑,不需要 useCallback。

最佳实践:先测量,再优化;把 useMemo / useCallback 当作“昂贵的优化手段”而非默认写法。

解析

岗位 JD 强调“性能优化”“复杂交互页面开发及重构经验”。通过本题可判断候选人是否理解 React 渲染模型,以及是否会为了优化而优化——后者在大型代码库中容易引入 bug。

3

React 18 引入了哪些并发特性?请说明 useTransitionuseDeferredValue 的适用场景。

React 18并发Hooks
参考答案

React 18 的核心并发特性包括:Concurrent Rendering、Automatic Batching、Suspense 增强、Transitions、useDeferredValue、useId、useSyncExternalStore 等。

  • useTransition:把“非紧急更新”标记为 transition,让高优先级交互(如输入)不被阻塞。典型场景:搜索框输入时即时反馈输入框内容,但列表过滤结果允许延迟渲染。
  • useDeferredValue:让某个值延迟更新,保持 UI 响应。典型场景:在快速输入时,用 deferred 值驱动的图表/列表慢半拍更新,而输入框本身保持即时响应。

两者都用于“可中断渲染 + 优先级调度”,但 useTransition 适合控制“状态更新”的优先级,useDeferredValue 适合控制“某个 prop/state 的滞后反映”。

解析

JD 要求“关注前沿前沿技术与生态发展”。React 18 并发是近两年前端生态的关键变化,3-5 年经验者至少应了解概念和落地场景,最好能在项目中有真实应用。

Next.js 与服务端渲染

4

Next.js App Router 与 Pages Router 在渲染模型、数据获取、路由机制上有哪些核心差异?

Next.jsSSRApp Router
参考答案
维度Pages RouterApp Router
渲染模型默认 CSR/SSR,页面级 getServerSideProps / getStaticProps / getInitialPropsServer Components 为默认,可嵌套使用;Client Components 需显式声明 'use client'
数据获取在页面 export 数据获取函数在 Server Component 中直接 await fetch() 或访问数据库;可按组件级获取数据
路由约定pages/index.tsxapp/page.tsxapp/layout.tsx
加载/错误状态自定义 pages/_app.tsx 处理基于文件约定的 loading.tsxerror.tsxnot-found.tsx
嵌套布局依赖 _app 和自定义组件原生支持 layout.tsx 嵌套,状态可保留

App Router 的优势:减少客户端 JS、提升首屏性能、组件级数据获取更灵活、更好的流式渲染(Streaming SSR)支持。

解析

JD 明确要求“熟悉 Next.js 服务端渲染框架”。候选人需要区分两代路由,尤其是 Server Components 对bundle 体积和首屏性能的影响,这直接关系到岗位里的性能优化职责。

5

请对比 SSR、SSG、ISR、CSR 四种渲染模式,并说明在 Next.js 中如何选择?

Next.js渲染模式高频
参考答案
模式构建时/请求时首屏适用场景
CSR运行时浏览器渲染慢(空壳 HTML)后台管理、强交互 SPA、对 SEO 无要求
SSG构建时生成 HTML最快,可 CDN 缓存营销页、博客、文档、商品详情(内容不常变)
SSR每次请求服务端渲染较快,动态数据个性化页面、需要实时数据的页面
ISR构建时 + 增量再生成接近 SSG,可后台更新大型电商列表、新闻站、内容频繁更新但又要求高并发

选择策略:以“内容新鲜度”和“请求量”为横纵轴。内容固定 + 流量大 → SSG;内容偶尔更新 + 流量大 → ISR;强个性化/实时 → SSR;重交互/后台 → CSR。

解析

JD 提到“SSR(服务端渲染)、静态站点生成、动态路由、懒加载等技术手段,提升页面加载速度”。本题考察候选人是否能根据业务场景做渲染策略决策,是架构设计能力的体现。

6

在 Next.js App Router 中,如何实现动态路由与静态生成?请说明 generateStaticParams 的作用。

Next.js动态路由SSG
参考答案

App Router 的动态路由使用文件夹约定,例如 app/blog/[slug]/page.tsx 对应 /blog/:slug

若要在构建时静态生成这些动态页面,需要在 page 组件中导出 generateStaticParams

// app/blog/[slug]/page.tsx
export async function generateStaticParams() {
  const posts = await fetch('https://api.example.com/posts').then(r => r.json());
  return posts.map((post) => ({ slug: post.slug }));
}

export default async function PostPage({ params }: { params: { slug: string } }) {
  const post = await fetch(`https://api.example.com/posts/${params.slug}`).then(r => r.json());
  return <article>{post.title}</article>;
}

generateStaticParams 的作用:

  • 告诉 Next.js 在构建时要生成哪些路由参数组合。
  • 未在构建时生成的参数可在运行时通过 SSR fallback 处理(默认 dynamicParams = true)。
  • 结合 ISR 可实现增量更新。
解析

岗位 JD 明确列出“动态路由”和“静态站点生成”。本题测试候选人是否掌握 App Router 下的新 API,而不是只停留在 Pages Router 的 getStaticPaths

Vue 核心与生态

1

Vue 2 与 Vue 3 的响应式原理有什么区别?为什么 Vue 3 选择 Proxy 替代 Object.defineProperty?

Vue响应式高频
参考答案

Vue 2 使用 Object.defineProperty 遍历对象属性,为每个属性设置 getter/setter 实现依赖收集与触发更新。数组变异方法(push、pop、splice 等)需要被重写才能追踪变化。

Vue 3 改用 Proxy 代理整个对象,拦截 get/set/deleteProperty/has/ownKeys 等操作。新增属性、删除属性、数组索引修改、Map/Set/WeakMap/WeakSet 都能被正常追踪。

选择 Proxy 的原因主要有三点:

  • 更完整的拦截能力:可以监听到属性新增、删除、in 操作符、Object.keys 等,defineProperty 无法做到。
  • 更好的数组性能:不需要重写数组原型方法,直接通过 Proxy 拦截索引访问和长度变化。
  • 嵌套对象懒代理:Vue 3 只在访问嵌套对象时才创建 Proxy,避免初始化时深度递归带来的性能开销。
解析

JD 要求"精通 Vue / React 等主流前端框架",响应式是 Vue 最核心的知识点。面试官希望通过对比考察候选人对框架底层实现的理解深度,而不仅是 API 使用。

2

Options API 与 Composition API 各适合什么场景?你在项目中如何选择?

VueComposition API高频
参考答案

Options API 通过 data、methods、computed、watch 等选项组织代码,逻辑分散在不同选项中。适合小型组件、快速上手、团队 Vue 2 迁移期。

Composition API 通过 setup()<script setup> 按逻辑关注点组织代码,配合 ref / reactive / computed / watch / lifecycle hooks 等函数复用逻辑。适合复杂组件、逻辑复用、TypeScript 类型推断、大型项目。

选择建议:

  • 简单展示型组件:Options API 更直观。
  • 复杂业务组件、表单、表格、多步骤流程:Composition API,逻辑内聚,便于抽离 composables。
  • 需要跨组件复用逻辑:封装 composable(如 useUser、useTable、useAsync)。
解析

JD 强调"Vue 组合式 API 实战",这是明确考点。回答时要避免捧一踩一,重点说明 Composition API 在逻辑组织和复用上的优势,并能结合项目举例。

3

Vue 组件通信有哪些方式?请按使用场景分类说明。

Vue组件通信高频
参考答案
场景方式说明
父子组件props / emit父传子 props,子传父 emit,单向数据流。
父级直接访问子级ref / $parent(不推荐)ref 获取组件实例,适合调用子组件暴露的方法。
跨层级 / 全局Provide / Inject祖先提供数据,后代注入,适合主题、配置等。
全局状态Pinia / Vuex正式项目首选 Pinia,轻量、类型友好、Devtools 支持好。
事件总线mitt / EventBus适合轻量跨组件事件,Vue 3 已移除 $on/$off。
URL 状态共享Vue Router query/params页面级状态,刷新不丢失。
解析

岗位 JD 提到"组件化开发"和"状态管理",通信方式是基础但高频的考点。回答时强调 Vue 3 推荐方案(props/emit、Pinia、Provide/Inject、mitt),避免提及已废弃的 Vue 2 选项。

4

Vue Router 4 有哪些核心变化?如何设计一个带权限的路由守卫?

VueVue Router路由守卫
参考答案

Vue Router 4 核心变化:

  • 创建方式改为 createRouter + createWebHistory / createWebHashHistory
  • 路由匹配改为基于 path-to-regexp 的自定义实现,通配符 * 需要显式参数。
  • 导航守卫逻辑调整,beforeEnter 支持数组;next() 不再推荐传递参数。
  • 新增 scrollBehaviorrouter.addRoute / removeRoute 动态路由能力。

权限路由守卫示例:

router.beforeEach(async (to, from, next) => {
  const userStore = useUserStore();
  if (!userStore.token && to.path !== '/login') {
    return next('/login');
  }
  if (to.meta.roles && !to.meta.roles.includes(userStore.role)) {
    return next('/403');
  }
  next();
});
解析

JD 要求"前端路由"和"权限控制"经验。考察候选人是否熟悉 Vue Router 4 的 API 变化,以及能否将路由守卫与真实权限模型(token、角色、动态菜单)结合。

5

Vue 3 中 refreactive 有什么区别?什么情况下会用到 toRef / toRefs

VueComposition API高频
参考答案

ref 接收任意类型值,返回一个响应式对象 { value: ... }。模板中会自动解包,JS 中需要 .value 访问。适合原始值(string、number、boolean)或需要替换整个对象的场景。

reactive 只能接收对象类型,返回 Proxy 代理对象。访问属性无需 .value,但不能直接替换整个对象(会丢失响应式)。

toRef / toRefs 用于从 reactive 对象中解构出响应式引用:

  • toRef(state, 'count'):创建一个与 state.count 保持同步的 ref。
  • toRefs(state):将 reactive 对象所有属性转为 ref,常用于从 composable 中解构返回。
const state = reactive({ count: 0, name: 'Vue' });
const { count, name } = toRefs(state); // 解构后仍保持响应式
解析

这是 Composition API 的基础考点,也是最容易写错的地方。面试官希望看到候选人对响应式引用、解构丢失响应式问题以及解决方案有清晰认识。

6

你在 Vue 项目中做过哪些性能优化?请至少说出 5 条并说明适用场景。

Vue性能优化高频
参考答案
  1. v-once / v-memo:静态内容或极少变化的数据使用 v-once;列表中部分子树依赖不变时用 v-memo
  2. 懒加载组件defineAsyncComponent + 路由懒加载,减少首屏 bundle 体积。
  3. 合理使用 computed:避免在模板中写复杂表达式,缓存计算结果。
  4. 列表渲染优化v-for 必加 :key;大数据列表使用虚拟滚动(vue-virtual-scroller)。
  5. 避免不必要响应式:大量静态数据用 Object.freezeshallowRef / shallowReactive 跳过深层响应式。
  6. Tree-shaking 与按需引入:组件库(Element Plus、Ant Design Vue)按需引入,避免全量打包。
  7. keep-alive 缓存:多标签页、表单步骤等场景缓存组件状态,减少重复渲染。
解析

JD 明确要求"前端性能优化",且薪资档位属于中高级。回答时要结合 Vue 特性(v-memo、defineAsyncComponent、keep-alive、shallowRef),并给出具体场景,避免泛泛而谈。

TypeScript 类型设计

7

如何为一个复杂的 React 组件设计类型安全的 Props?请用示例说明泛型、条件类型、联合类型的应用。

TypeScript类型设计高频
参考答案

以“按钮组件支持多种变体且不同变体拥有不同专属属性”为例:

type BaseButtonProps = {
  children: React.ReactNode;
  disabled?: boolean;
  onClick?: () => void;
};

type PrimaryButtonProps = BaseButtonProps & {
  variant: 'primary';
  themeColor?: string;
};

type LinkButtonProps = BaseButtonProps & {
  variant: 'link';
  href: string;
  external?: boolean;
};

type ButtonProps = PrimaryButtonProps | LinkButtonProps;

function Button(props: ButtonProps) {
  if (props.variant === 'link') {
    return <a href={props.href} target={props.external ? '_blank' : undefined}>{props.children}</a>;
  }
  return <button style={{ color: props.themeColor }}>{props.children}</button>;
}

// 类型校验:link 变体必须传 href
<Button variant="link" href="/home">首页</Button>

要点:

  • 联合类型 表达互斥变体。
  • 类型收窄(discriminated union)在运行时分支中自动获得精确类型。
  • 泛型 处理可复用的高阶组件或 render props,例如 Table<T>
  • Pick/Omit/Partial 从已有类型派生子类型,减少重复定义。
解析

JD 要求“熟练掌握 TypeScript,具备良好的类型设计与工程化规范意识”。本题考察实际编码中如何写出既安全又可扩展的类型,而不是死记硬背概念。

8

interfacetype 有什么区别?在大型项目中如何抉择?

TypeScript基础
参考答案
特性interfacetype
合并声明支持声明合并(declaration merging)不支持同名重复声明
扩展方式extends& 交叉类型
适用类型仅对象类型对象、联合、元组、基本类型别名等
错误提示通常更清晰,指出缺少的属性交叉类型冲突时提示较复杂

大型项目建议:

  • 对象类型、组件 Props、类类型优先用 interface,便于扩展和声明合并。
  • 联合类型、工具类型、复杂类型别名用 type
  • 团队统一 lint 规则(如 @typescript-eslint/consistent-type-definitions),避免混用导致风格不一致。
解析

这是 TypeScript 基础但高频的问题。JD 强调“工程化规范意识”,考察候选人是否有团队规范意识,以及是否能解释清楚技术差异。

状态管理与数据流

9

React 项目中 Redux、Zustand、Jotai、Context 各适合什么场景?你会如何选型?

状态管理React高频
参考答案
方案特点适用场景
ContextReact 内置,简单,但任意值变化会导致所有消费组件重渲染主题、语言、用户身份等低频变化的全局状态
Zustand轻量、无样板代码、支持 selector、中间件生态丰富中小型项目或希望快速替代 Redux 的场景
Jotai / Recoil原子化状态,细粒度订阅,适合派生状态状态之间依赖复杂、需要大量派生计算的 UI
Redux Toolkit成熟、可预测、DevTools 强大、中间件生态完善大型团队、复杂业务流、需要严格数据流审计的项目

选型思路:先看状态规模与变化频率,再看团队熟悉度和调试需求。简单共享状态用 Context;中等规模优先 Zustand 降低样板;超大型或需要强约束的用 Redux Toolkit。

解析

JD 提到“组件化思想、虚拟 DOM、数据流设计”。状态管理选型是前端架构设计的核心,通过本题判断候选人是否能根据项目规模做合理技术决策。

10

全局状态中的异步副作用(如 API 请求)应该如何处理?请说明 Redux Toolkit + createAsyncThunk 或 Zustand 中的常见做法。

状态管理异步数据流
参考答案

核心原则:异步逻辑不应直接放在 UI 组件里,应下沉到状态管理层或独立的服务层。

  • Redux Toolkit:使用 createAsyncThunk 定义异步 action,自动派发 pending/fulfilled/rejected,配合 extraReducers 更新 loading/error/data 状态。
  • Zustand:在 store 中直接写 async action,手动 set 状态;或者结合 immer 中间件简化不可变更新。
  • 通用做法:定义统一的 API 层(如 services/),状态管理只负责调用和保存结果;错误处理统一封装,UI 只消费状态。
// Zustand 示例
import { create } from 'zustand';

const useUserStore = create((set) => ({
  user: null,
  loading: false,
  error: null,
  fetchUser: async (id) => {
    set({ loading: true, error: null });
    try {
      const res = await fetch(`/api/users/${id}`);
      if (!res.ok) throw new Error('fetch failed');
      set({ user: await res.json(), loading: false });
    } catch (e: any) {
      set({ error: e.message, loading: false });
    }
  },
}));
解析

JD 强调“数据流设计及性能优化思路”。异步状态管理是实际项目中最容易出问题的环节,考察候选人是否有清晰的分层意识和错误处理经验。

前端性能优化

11

请列举至少 5 个优化首屏加载(FCP/LCP)的具体手段,并说明它们在 Next.js 或 React 项目中的落地方式。

性能优化首屏高频
参考答案
  1. 代码分割 / 路由懒加载:React 用 React.lazy + Suspense,Next.js 路由天然代码分割。
  2. 图片优化:使用 Next.js Image 组件自动提供 WebP/AVIF、响应式尺寸、懒加载;React 项目可用 loading="lazy"srcset
  3. 字体优化:使用 font-display: swap,预加载关键字体,避免 FOIT。
  4. 关键 CSS 内联:把首屏关键 CSS 直接内联到 HTML,减少渲染阻塞。
  5. 服务端渲染 / 静态生成:减少客户端 JS 执行时间,让 LCP 资源更快呈现。
  6. Tree Shaking 与第三方库瘦身:按需引入组件(如 lodash-es 替代 lodash),使用 next/bundle-analyzer 分析包体积。
  7. 资源预加载/预连接:对关键域名使用 <link rel="preconnect">,对 LCP 图片使用 <link rel="preload">
解析

JD 明确写到“具备前端性能优化能力,对首屏加载、资源压缩、代码分割、懒加载、缓存等策略有深入理解”。本题是岗位核心能力点,需要候选人能落地而非空谈。

12

代码分割(Code Splitting)、懒加载(Lazy Loading)与预加载(Prefetch/Preload)有什么区别?如何组合使用?

性能优化加载策略
参考答案
技术目的触发时机典型用法
Code Splitting减小初始 bundle构建时按路由/组件拆包Webpack/Vite 动态 import,Next.js 自动路由分割
Lazy Loading延迟加载非关键资源运行时(进入视口/路由/交互时)React.lazy + Suspense,图片 loading="lazy"
Preload提前加载当前页面关键资源当前页面加载早期<link rel="preload"> 关键字体/图片/脚本
Prefetch预测性加载未来可能用到的资源浏览器空闲时Next.js <Link prefetch>,路由预取

组合策略:首屏只加载必要资源(code splitting + lazy loading),对首屏关键资源使用 preload,对可能下一步访问的页面/数据使用 prefetch。

解析

JD 把“懒加载”“代码分割”“预加载”列为关键技术手段。本题考察候选人对加载策略体系化的理解,避免混淆概念。

13

Core Web Vitals 包含哪些核心指标?请分别说明 LCP、CLS、INP 的优化思路。

性能优化Core Web Vitals高频
参考答案
指标含义优化方向
LCP(Largest Contentful Paint)最大内容元素渲染时间优化图片/视频大小、使用 CDN、预加载 LCP 资源、SSR/SSG、减少 TTFB
CLS(Cumulative Layout Shift)累积布局偏移为图片/视频/广告预留尺寸、避免在已有内容后插入内容、字体加载策略优化
INP(Interaction to Next Paint)交互到下一次绘制延迟减少长任务、事件处理函数非阻塞、使用 useTransition/useDeferredValue、优化 DOM 操作
FCP / TTFB首次内容绘制 / 首字节时间CDN、边缘缓存、服务端优化、减少重定向

测量工具:Lighthouse、Chrome DevTools Performance、Web Vitals 扩展、web-vitals JS 库。

解析

JD 明确写“能针对 Lighthouse/Core Web Vitals 等指标进行调优优先”。这是中高级前端必备技能,考察候选人是否有实际调优经验。

前端工程化

14

Webpack 与 Vite 的核心差异是什么?为什么 Vite 冷启动更快?

工程化构建工具高频
参考答案

核心差异:

  • Webpack:基于 bundler,开发时也会打包所有模块;启动时间和项目规模正相关;生态成熟,配置灵活。
  • Vite:基于原生 ESM 的 dev server,开发时按需编译浏览器请求的模块;生产环境用 Rollup 打包。

Vite 冷启动更快的原因:

  1. 不需要预先打包所有依赖,启动时只处理入口 HTML 和少量预构建(optimize deps)。
  2. 利用浏览器原生 ESM 解析依赖图,按需加载。
  3. 编译器使用 esbuild(C++ 编写),比 Webpack 的 JavaScript 解析器快 10-100 倍。
  4. HMR 按模块边界更新,不需要重新打包整个 bundle。
解析

JD 要求“熟悉前端工程化工具链(如 Vite、Webpack、ESLint、Prettier、Babel 等)”。本题是工具链基础但高频,考察候选人是否理解构建原理。

15

如何设计一套前端代码规范与提交规范?请说明 ESLint、Prettier、Husky、lint-staged 的分工。

工程化代码规范高频
参考答案
工具职责
ESLint代码质量与潜在错误检查(unused vars、复杂逻辑、React Hooks 规则、import 顺序等)
Prettier代码格式化(换行、引号、缩进等),保证风格一致
HuskyGit hooks 管理工具,在 pre-commit 等阶段触发脚本
lint-staged只对暂存区文件运行 lint/format,避免全量检查拖慢提交

完整流程:

  1. 项目初始化 ESLint + Prettier,用 @eslint/jstypescript-eslinteslint-plugin-react-hooks 等规则集。
  2. 配置 .prettierrc 与 ESLint 不冲突(关闭 ESLint 中 Prettier 已覆盖的格式规则)。
  3. Husky 配置 pre-commit hook,调用 lint-staged
  4. lint-staged 配置对暂存文件执行 eslint --fixprettier --write
  5. 可选:使用 commitlint + commitizen 规范提交信息(如 Conventional Commits)。
解析

JD 强调“代码规范意识与文档编写能力”“具备良好的类型设计与工程化规范意识”。工程化规范是团队协作的基石,3-5 年经验者应该能独立搭建规范体系。

前后端协作与 API

16

RESTful API 与 GraphQL 各有什么优缺点?前端在选型时应考虑哪些因素?

APIRESTfulGraphQL
参考答案
维度RESTfulGraphQL
数据获取多个端点,可能 over-fetch/under-fetch单个端点,客户端指定所需字段
缓存HTTP 缓存成熟(CDN、浏览器)需要自定义缓存策略(如 Apollo Cache、DataLoader)
学习成本低,符合 HTTP 语义需要学习 Schema、Resolver、Query/Mutation
版本管理常见 v1/v2 版本通过 Schema 演进,避免版本号
调试工具Postman、SwaggerGraphiQL、Playground

选型因素:团队后端技术栈、数据聚合复杂度、多端需求(移动端需要精简字段)、缓存要求、团队学习成本。BFF(Backend for Frontend)场景 GraphQL 优势明显。

解析

JD 要求“熟悉 RESTful / GraphQL API 调用与集成”。本题考察候选人对两种主流 API 范式的理解及选型能力。

17

如何设计错误码与统一错误处理机制?请结合 React/Next.js 项目说明。

API错误处理工程化
参考答案

错误码设计建议:

  • 分层:业务错误码(4 位或 6 位) + HTTP 状态码。例如 4001001 表示“参数缺失”,4010001 表示“登录过期”。
  • 约定统一响应结构:{ code, message, data, requestId }
  • 错误类型分类:客户端错误、鉴权错误、服务端错误、第三方服务错误。

统一错误处理:

  1. 封装请求库(如基于 axios/fetch 的 request.ts),在响应拦截器中统一解析 code。
  2. 对需要登录态的接口统一处理 401,跳转登录或刷新 token。
  3. 对业务错误统一 toast/notification 提示;对 5xx 错误统一展示友好页面。
  4. Next.js 中可在 error.tsx 中捕获路由段错误;React 中可用 Error Boundary 捕获渲染错误。
  5. 记录 requestId,便于后端排查。
解析

JD 提到“参与接口规范、错误码定义、数据结构等工作”。统一错误处理是前后端协作的关键环节,考察候选人是否具备工程化思维和落地能力。

前端安全

18

请分别说明 XSS、CSRF、CORS 的原理及前端防御措施。

安全XSSCSRFCORS高频
参考答案
攻击原理前端防御
XSS攻击者注入恶意脚本,浏览器执行输入过滤、输出转义;React/Vue 默认转义 JSX;使用 DOMPurify 处理富文本;CSP 限制脚本来源
CSRF诱导已登录用户访问恶意链接,携带 cookie 发起请求SameSite Cookie、CSRF Token、校验 Referer/Origin、敏感操作二次验证
CORS浏览器同源策略限制跨域请求前端不处理,由服务端配置 Access-Control-Allow-Origin;开发环境可用代理

注意:CORS 不是攻击,而是浏览器的安全机制;真正的防御在服务端配置。

解析

JD 明确写“了解常见的安全机制(XSS、CSRF、CORS 等)”。安全是中高级前端必须掌握的基础,尤其是电商/SaaS/支付类业务。

19

前端如何安全地存储 Token?Access Token 与 Refresh Token 的存储策略有何不同?

安全鉴权Token
参考答案

安全存储原则:

  • 不推荐 localStorage:易受 XSS 攻击,一旦页面被注入脚本,Token 会被直接读取。
  • 推荐 HttpOnly Cookie:由服务端设置 HttpOnly; Secure; SameSite=Strict,JS 无法读取,可防御 XSS 窃取。
  • 内存存储:把 Token 保存在内存(如 React Context/Zustand)中,页面刷新后丢失,配合 cookie 中的 Refresh Token 重新获取。

Access Token vs Refresh Token:

  • Access Token:有效期短(分钟级),用于接口鉴权,建议内存存储或 HttpOnly Cookie。
  • Refresh Token:有效期长(天/周级),用于换取新的 Access Token,必须 HttpOnly Cookie,且建议绑定设备指纹或 rotating refresh token。
解析

JD 提到 SaaS 平台、支付系统、交易类前端经验优先。Token 安全是这些业务的核心,考察候选人是否了解 XSS 风险及现代鉴权最佳实践。

微前端架构

20

微前端架构解决了什么问题?常见的实现方案有哪些,各有什么特点?

微前端架构高频
参考答案

微前端解决的问题:

  • 巨石应用难以维护、构建慢、发布耦合。
  • 多团队并行开发同一产品时技术栈冲突、发布冲突。
  • 希望渐进式重构老系统,而非一次性重写。

常见方案:

方案特点适用
iframe隔离性最强,但体验差(弹窗遮罩、路由同步难)临时集成、异构系统
qiankun基于 single-spa,JS 沙箱、样式隔离、prefetch,生态成熟国内企业主流方案
Module FederationWebpack 5 原生,运行时共享依赖,体验接近单体技术栈统一、需要模块共享
Web Components标准方案,跨框架,但工程化成本高组件级微前端、跨技术栈
解析

JD 明确写“了解微前端架构……现代化前端工程实践者优先”。本题考察候选人对微前端适用场景和主流方案的理解。

21

在使用 qiankun 或 Module Federation 时,如何处理子应用之间的样式隔离和公共依赖共享?

微前端qiankunModule Federation
参考答案

样式隔离:

  • qiankun:开启 strictStyleIsolation: true 使用 Shadow DOM,或 experimentalStyleIsolation: true 给子应用样式加前缀。
  • 工程化:CSS Modules、BEM 命名规范、CSS-in-JS(styled-components/emotion)。
  • 子应用卸载时清理动态插入的 style 标签。

公共依赖共享:

  • qiankun:主应用通过 import-map / externals 注入 React/Vue/Router 等,子应用打包时排除(external)。
  • Module Federation:在 ModuleFederationPlugin 中配置 shared,自动去重并共享依赖版本,支持 eager consumption。

注意:公共依赖共享需要统一版本策略,否则容易出现多版本 React 导致的 Hooks 错误。

解析

微前端落地时样式冲突和依赖共享是最常见的问题。本题测试候选人是否有真实踩坑经验,而不仅是概念。

CI/CD 与容器化

22

一个成熟的前端 CI/CD 流程通常包含哪些阶段?请结合 GitHub Actions / GitLab CI 说明。

CI/CDDevOps高频
参考答案
  1. Install:安装依赖,缓存 node_modules(如 actions/setup-node + cache)。
  2. Lint & Format Check:运行 ESLint、Prettier、TypeScript 类型检查,确保代码规范。
  3. Unit Test:运行 Jest/Vitest 单元测试,生成覆盖率报告。
  4. Build:构建生产包,检查构建产物大小。
  5. E2E Test(可选):Playwright/Cypress 端到端测试。
  6. Deploy:上传到 CDN / 对象存储 / Kubernetes / Vercel / 自有服务器。
  7. Notification:失败时通知飞书/钉钉/Slack。

关键原则:前置检查(lint/type/test)优先,避免把问题带到线上;构建产物版本化;回滚策略。

解析

JD 要求“了解 CI/CD 自动化流程”。3-5 年经验者应能描述完整流水线,体现工程化成熟度。

23

如何为 Next.js / React 项目构建一个轻量的 Docker 镜像?请给出关键优化点。

Docker容器化部署
参考答案

关键优化点:

  1. 多阶段构建(Multi-stage):第一阶段用 node 镜像构建,第二阶段用精简镜像(如 node:alpine 或 distroless)运行。
  2. 依赖分层缓存:先复制 package.json / lockfile 安装依赖,再复制源码,利用 Docker layer cache。
  3. 使用 .dockerignore:排除 node_modules、.git、.next 等,减少 build context。
  4. Next.js standalone 输出:配置 output: 'standalone',只打包运行所需的最小文件。
  5. 非 root 用户运行:创建专用用户提升安全性。
# 示例:Next.js standalone Dockerfile
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM node:20-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]
解析

JD 写“Docker/容器化部署等现代化前端工程实践者优先”。本题考察候选人是否具备前端部署与镜像优化的实战经验。

监控与 A/B 实验

24

前端监控体系应采集哪些指标?如何设计一套简单的 A/B 实验方案?

监控A/B 实验数据分析
参考答案

前端监控指标分类:

  • 性能:FCP、LCP、CLS、INP、TTFB、资源加载耗时、API 响应时间。
  • 错误:JS 报错、Promise 未捕获异常、资源加载失败、接口错误码。
  • 业务:PV/UV、页面停留时长、转化率、按钮点击率。
  • 用户行为:点击热图、路由跳转、报错回放(Session Replay)。

A/B 实验设计:

  1. 分流:基于用户唯一标识(userId/deviceId)做哈希分桶,保证同一用户稳定命中同一版本。
  2. 埋点:在实验组和对照组分别上报曝光、点击、转化事件,携带 experiment_id + bucket。
  3. 指标:预先定义核心指标(如转化率)和护栏指标(如错误率、加载时长)。
  4. 统计:收集足够样本量后做假设检验,判断实验是否显著。
  5. 灰度:先小流量开启,观察无异常后再全量。
解析

JD 提到“前端监控与 A/B 实验体系”。这属于中高级前端向工程化/数据化延伸的能力,考察候选人是否有数据驱动意识。

加分项专题

25

Ant Design、Tailwind CSS、shadcn/ui 各有怎样的设计哲学和适用场景?

UI 框架设计审美加分项
参考答案
框架设计哲学适用场景
Ant Design企业级设计语言,组件丰富,生态成熟后台管理系统、SaaS、中后台
Tailwind CSSUtility-first,原子类直接组合,高度可定制需要快速迭代、强品牌定制的项目
shadcn/ui可复制的组件代码,基于 Radix + Tailwind,不依赖 npm 包追求可维护、可定制、现代化体验的项目

选型建议:中后台求稳选 Ant Design;追求定制与开发效率选 Tailwind;希望组件代码完全可控、避免黑盒选 shadcn/ui。

解析

JD 加分项写“熟悉 UI 框架并具备良好的设计审美”。本题帮助识别候选人对现代 UI 方案的理解,以及是否能根据项目气质选型。

26

在 Next.js 项目中如何实现国际化(i18n)?请比较 next-intl 与原生 next-i18next 的差异。

国际化i18nNext.js加分项
参考答案

Next.js 国际化常见做法:

  • App Router 推荐 next-intl,通过 middleware 根据 locale 路由,Server Components 直接获取翻译。
  • Pages Router 常用 next-i18next,基于 react-i18next,在 getServerSideProps/getStaticProps 中加载翻译。
维度next-intlnext-i18next
路由App Router + middlewarePages Router
Server Components原生支持不支持,需 Client Components
API 风格简洁,useTranslations / getTranslationsuseTranslation / serverSideTranslations
复数/插值内置 ICU MessageFormat基于 i18next 插件

实现要点:locale 路由(如 /en/products)、语言切换器、fallback locale、翻译文件按页面/模块拆分。

解析

JD 加分项明确写“国际化项目开发经验(如 i18n、next-intl)”。本题测试候选人是否有真实落地经验,尤其是 App Router 下的 next-intl。

27

Node.js 中间层在大型前端项目中能起到什么作用?你如何看待“全栈思维”在前端架构中的价值?

Node.js全栈架构加分项
参考答案

Node.js 中间层(BFF)作用:

  • 数据聚合:合并多个后端接口,为前端提供统一视图,减少请求次数。
  • 协议转换:把 RPC/GraphQL/第三方接口转成前端友好的 REST。
  • 渲染层:Next.js / Nuxt 的 SSR 服务,承担首屏渲染和 SEO。
  • 鉴权与代理:统一处理登录态、权限校验、敏感信息脱敏。
  • 性能优化:缓存、接口合并、SSR 流式输出。

全栈思维价值:

  • 前端能更合理地设计接口契约、错误码、数据结构和缓存策略。
  • 减少前后端往返沟通成本,提升交付效率。
  • 在架构层面做端到端优化,而不是只局限在浏览器端。

边界:全栈不等于一个人做所有事,而是在理解后端、运维、产品的基础上做出更优的前端技术决策。

解析

JD 加分项写“了解 Node.js 或 Golang 等后端开发,具备一定的全栈思维”。本题考察候选人是否有跨端视角,是否能把前端架构放到整个技术栈中思考。