Next.js 面试题
Next.js 面试题
React、Next.js、Node.js 各分入门 / 中等 / 高难,每档 20 题,共 180 题,★ 是高频。06 用来快速入门,本篇用来系统复习。通用方案不代表项目已有实现。
Next.js 入门(20 题)
1. ★ Next.js 与 React 什么关系?
React 是 UI 库,Next 是基于它的应用框架,提供路由、服务端渲染、构建与服务端能力。使用 Next 不等于所有页面都 SSR,也不表示业务后端必须迁进 Next。
2. App Router 的 page 和 layout 是什么?
page 是路由页面,layout 提供嵌套共享结构,切换子路由时可保留其状态。路由由目录组织;别把需要每次重置的表单状态不加考虑地放在长期保留的 layout 中。
3. ★ Server Component 和 Client Component 怎么分?
服务端组件适合读服务端数据并减少浏览器 JS;客户端组件用于 state、Effect、事件和浏览器 API。客户端边界通过 'use client' 声明,向客户端传递的数据必须符合 React 支持的序列化协议。
4. 'use client' 是否表示完全不在服务端执行?
不是。客户端组件初次加载仍可能参与服务端 HTML 预渲染,再在浏览器水合。不能在渲染时无条件访问 window/localStorage;浏览器专属行为放合适生命周期或明确禁用该组件 SSR。
5. ★ SSR、SSG、CSR 有什么区别?
SSR 按请求生成 HTML,SSG 在构建或再生成阶段产出,CSR 主要在浏览器获取数据渲染。实际页面可混用;选择取决于个性化、更新频率、首屏与部署限制,不只看 SEO。
6. 水合是什么?
浏览器把交互能力接到服务端生成的 HTML 上。服务端和客户端首次渲染应一致;随机数、本地时间、浏览器状态和不同数据版本都可能引起 mismatch。
7. ★ Link 和普通 a 有什么区别?
Link 支持框架的客户端导航与预取等行为,普通 a 导航通常刷新整个文档。外部下载/跨站链接按需求使用;预取会带来资源成本,敏感操作不能通过访问一个预取链接就触发。
8. 动态路由怎么组织?
用 [id] 表示动态段,[...slug] 表示多段捕获,可选捕获有对应语法。params 在较新版本按异步请求 API 使用;仍要校验格式、权限和资源是否存在,路径名不是身份凭证。
9. loading.tsx 的作用?
给路由段提供加载边界,等待内容时展示占位。它改善等待体验,不会减少慢查询本身耗时;合理拆边界,别让一个全页 loading 遮住已经可交互的静态结构。
10. ★ error.tsx 与 not-found 有什么区别?
error 处理路由段的运行失败并提供恢复 UI;not-found 表示资源或路由不存在。它们对应不同产品语义;权限隐藏资源时按后端约定展示不存在,不把所有接口错误都当 404。
11. Route Handler 是什么?
在 route.ts 等文件中定义 HTTP 方法处理,可做 BFF、回调或轻量服务。它是服务端入口,需要校验身份、输入和请求体大小;不能因为和页面同仓库就省略接口安全控制。
12. ★ rewrite 和 redirect 区别?
rewrite 在服务端内部改请求目标,浏览器地址通常保持原样;redirect 让客户端跳转到新 URL。rewrite 适合接口代理,redirect 适合页面迁移;代理后仍需正确传递 cookie 和状态码。
13. 项目怎样代理后端?(项目)
frontend 的 next.config.ts 配置多条 API rewrite;console/gateway 只有设置各自代理目标变量时才启用。部署可能由同域网关转发,不能说浏览器的每个 /api 请求必经 Next。
14. 环境变量哪些能放客户端?
只有明确允许公开的配置才能暴露;NEXT_PUBLIC_ 常在构建时替换进浏览器包,不能放密钥。非公开变量应留服务端,但服务端读取后再返回给客户端照样会泄露。
15. ★ cookies 和 headers 怎么读取?
使用框架提供的请求 API;Next 15 引入异步形式,迁移应使用 await 等正确方式,16 移除多项同步兼容。读取用户信息后要考虑路由动态行为及缓存,避免复用其他用户的数据。
16. Next 的 fetch 默认都缓存吗?
不能这样说,默认行为随版本变化。Next 15 已改变 fetch、GET Route Handler 等默认缓存策略;需要缓存时显式表达并检查路由配置,复习时不要背旧版「一律 force-cache」。
17. 图片组件解决什么问题?
提供图片尺寸、懒加载和优化相关能力,帮助减少布局位移与传输成本。远端图片来源要限制,宽高/布局要合理;动态鉴权图片和静态导出有额外部署约束。
18. ★ metadata 是做什么的?
管理页面标题、描述与分享信息,可静态声明或按路由生成。服务端生成时避免把私有文档摘要放进公开 metadata;SEO 信息也需要遵循资源权限。
19. standalone 输出有什么用?(项目)
追踪所需运行文件,生成更易打包部署的服务目录;console/gateway 使用它。静态资源、public 与运行环境仍要正确打包配置,standalone 不等于单个无依赖可执行文件。
20. Next 15 和 Next 16 为什么要分开回答?(项目)
三个前端并非同一个大版本。升级涉及缓存、请求 API、工具链和命名变化,Next 16 也移除了 next lint。以各仓库 package.json 与升级说明为准,不能复制一份命令就保证全部可用。
Next.js 中等(20 题)
1. ★ 哪些组件应该放客户端边界?
把交互小岛尽量放在需要 state/事件的最小子树,静态结构和敏感数据读取保留服务端。'use client' 会影响导入链,不能为解决一个 window 报错就把整棵应用改成客户端。
2. 服务端组件能把服务端组件传给客户端吗?
可由服务端父组件把已经构建的服务端内容作为 children 等传给客户端组件组合。客户端模块直接导入含服务端依赖的模块是另一回事;按边界组合,别把数据库代码带进浏览器导入链。
3. ★ RSC 和 SSR 为什么不等价?
SSR 产生 HTML,RSC 描述服务端组件树并参与客户端导航更新;客户端组件也能被 SSR。两者可合作,分析性能时分别看 HTML、RSC payload 和 JS,而不是把 RSC 简称成一种模板引擎。
4. 请求内去重和持久缓存有什么区别?
请求内去重减少一次渲染内重复读取;持久缓存会跨请求复用并需失效规则。范围、适用 API 和运行环境可能不同,不能认为 fetch 调两次没访问网络就证明它被跨用户缓存。
5. ★ Next 缓存有哪些层次?
可从请求内去重、数据缓存、路由输出与客户端路由缓存理解,但具体默认和 API 随版本/配置变化。分别写清谁缓存、缓存键、有效期和失效条件,避免把所有问题都归因于浏览器缓存。
6. revalidatePath 和 revalidateTag 怎么选?
前者按路径更新关联内容,后者按数据标签管理相关缓存。何时立即失效、何时延迟再验证要看版本和调用上下文;权限敏感数据不能靠长缓存加偶尔失效保障即时撤权。
7. ★ 动态数据怎么避免跨用户缓存?
从可信请求获取身份,明确禁用不合适的共享缓存,或把授权范围与数据版本纳入缓存键。读取后最小化传给客户端的字段;不能把全局变量当请求上下文。
8. Server Action 是普通内部函数吗?
不是,它会形成可从客户端触发的服务端入口。每次执行仍需鉴权、校验参数、检查资源权限和幂等;函数在服务端定义不表示调用者参数可信,错误输出也不能暴露密钥。
9. ★ 为什么 Server Component 不应该绕 HTTP 请求自己的 Route Handler?
同一服务端可以直接调用共享数据层,少一次网络并避免构建期服务尚未监听的问题。对外协议或独立服务仍可走 HTTP;共享层保留授权,别因「内部调用」省掉权限验证。
10. 怎么避免数据请求瀑布?
无依赖的请求尽早并行,需要前置结果的再串行;按边界流式展示慢内容。先辨认真实依赖,不能盲目 Promise.all 导致未授权的数据请求也发出;失败策略按独立模块设计。
11. loading、Suspense 和流式 SSR 如何协作?
Suspense 划分可渐进交付的区域,loading 是路由层的方便约定。服务器可以先发送外壳再补内容;代理缓冲、压缩和客户端水合仍会影响首屏实际时间,需从浏览器观察。
12. ★ BFF 层做什么,不做什么?
聚合接口、转换前端所需字段、管理安全的会话访问,减少浏览器复杂度。避免把核心规则复制成另一份后端真相;如果项目主要用 rewrite,就不要把它包装成已经实现复杂聚合 BFF。
13. cookie 经过 rewrite 有什么坑?
域、路径、SameSite、Secure、代理协议与 Set-Cookie 传递都可能影响登录。逐跳查看请求/响应头,校验主机与路径;同域代理减少跨域问题,但不会自动修复 CSRF 与错误 cookie 配置。
14. 如何集成第三方客户端组件?
为需要浏览器 API 的库设置恰当客户端边界,必要时按框架能力动态加载。避免服务端导入阶段就访问 window;同时考虑首屏占位、样式插入和包体积,别直接禁掉整页 SSR。
15. ★ antd 的服务端样式要注意什么?
按其与当前 Next/React 版本的集成方式收集并插入样式,防止首屏闪烁和重复样式。项目依赖中有 nextjs registry 与 React 19 兼容补丁;实际接入仍需看 Provider,不凭包名就说全部配置正确。
16. 路由组、平行路由、拦截路由分别用在哪?
路由组组织目录而不改变 URL;平行路由展示多个插槽;拦截路由可在当前上下文中呈现目标页面。复杂路由要覆盖直达、刷新和回退,别只验证从某个按钮点开时正常。
17. ★ 静态导出能代理后端吗?
纯静态文件没有 Next 服务进程,不能执行运行时 rewrite、服务端函数等。API 代理应由实际部署网关承担,或选择保留服务端运行方式;不能把 standalone 与静态导出混为一谈。
18. 怎么减少客户端 bundle?
分析依赖体积,缩小 use client 边界,按需加载重编辑器/图表,避免大 barrel 牵进无关依赖。看实际构建结果与首屏交互,而不只计算源码行数。
19. middleware / proxy 能承担全部鉴权吗?
可做快速路由判断,但受运行环境和匹配规则约束,真正的数据入口仍需授权。Next 16 的 proxy 命名迁移需按版本处理;不能把页面重定向当作 API 已安全。
20. ★ 怎么测试 Next 页面?
纯逻辑与交互用单测,路由、cookie、SSR/水合、代理和重连用本机集成/E2E。项目默认开发命令可能指向共享后端,应选择明确的本地入口,不能为验证前端文档触发共享数据写入。
Next.js 高难(20 题)
1. ★ 水合只在部分用户机器报错?
比较服务端与客户端首屏数据、时区、语言、随机值、浏览器扩展和无效 HTML 嵌套。构建可复现样本定位差异;suppressHydrationWarning 只适合少数已知差异,不能用来掩盖整页错配。
2. 页面显示了上一个用户的数据怎么查?
立即检查共享缓存、模块级状态、CDN cache key 与登录切换后的客户端缓存。以身份和资源版本重建边界,敏感接口服务端复核;只在登出时清空 Redux 无法修复服务端缓存泄露。
3. ★ rewrite 后 SSE 总是攒一大段才输出?
逐跳测试直接后端、Next 代理、外层代理到浏览器的事件间隔。检查缓冲、压缩和超时,确认代码未先 await response.text()。保留最小流式样本,不能只根据普通 API 延迟判断。
4. Next 服务端内存持续增长怎么定位?
分请求峰值、全局缓存、未关闭流、图片优化及第三方库泄漏。用固定负载观察 GC 后基线与堆保留路径,限制无界缓存;单纯增加 Node heap 会推迟 OOM,不等于修复。
5. ★ 多副本缓存不一致怎么处理?
先明确哪些缓存进程内、哪些共享,统一版本和失效事件;必要时使用部署支持的共享缓存机制。私有内容仍要即时授权,不能靠让请求固定在同一副本解决权限变化。
6. 发版后浏览器加载旧 chunk 导致白屏?(项目)
核对 HTML/JS 版本组合、CDN 与 Service Worker。项目使用 Serwist,旧 SW 可能缓存旧资源;采用兼容的发布/资源保留与更新提示,在本机清理 SW 验证,不把永久禁用缓存当最终方案。
7. Server Action 重复执行会怎样?
网络重试和用户重复提交都可能触发,因此业务幂等仍必需。操作 ID 与唯一约束防重复,提交状态与重试分开;对支付、审批等不能只依赖 pending 按钮状态。
8. ★ 缓存失效触发大量回源怎么办?
把缓存条目分散过期,合并相同请求,给回源限并发,按允许程度使用陈旧数据再验证。权限变化类不能随意 stale;缓存恢复期间也要保护数据库,防止重试叠加。
9. 读取用户 cookie 后整页变慢怎么优化?
确认动态数据实际影响哪些组件,分开公共缓存内容与私有读取,避免根 layout 无差别阻塞全页。按部署支持选择边界缓存与流式策略;不能为了缓存绕过身份读取。
10. ★ Next 15 升 16 最容易漏什么?
检查异步请求 API 的同步兼容移除、工具链/配置变化、next lint 移除、middleware/proxy 迁移及缓存行为。先按官方清单逐项校验,再本机验证代理、样式、水合与构建产物,不只升级 package.json。
11. 本地能登录,部署后 cookie 丢了?
对照实际 HTTPS、代理头、cookie Domain/Path/Secure/SameSite 和多层转发。确认服务认为的外部协议是否正确;不要用取消 Secure 或把所有域都放开来绕过根因。
12. SSR 访问内部地址为什么有风险?
若目标 URL 受用户控制,服务器可被用来访问内网或云元数据,形成 SSRF。使用目标白名单、协议限制、解析后地址校验与跳转约束;rewrite 也不能开放成任意代理。
13. ★ 页面快了但服务器成本翻倍?
检查预取、服务端重复请求、缓存未命中、长连接驻留和渲染 CPU。按实际导航率估预取收益,合并重复读取并测每请求成本;不能只优化浏览器首屏而忽略后端负载。
14. 并行 Route 请求产生不一致快照?
相互独立的数据可并行,必须一致的业务读取需服务端聚合事务或版本水位。客户端把两次不同时刻结果拼起来,不自动获得一致快照;返回版本帮助识别过时内容。
15. 冷启动影响首字怎么办?
拆依赖初始化、连接建立和实际模型时间,避免所有角色加载重库。给就绪探测留合理启动期,按需/预热选择有成本依据;项目已有 APP_SCOPE,不能让 console 入口引入整套 AI 依赖。
16. ★ 怎样避免错误页面泄露内部信息?
客户端展示可行动的错误和关联 ID,服务端记录受控详情,过滤异常里的 SQL、URL 凭证与 prompt。错误边界只负责展示,不等于已完成日志脱敏;失败重试仍要验证授权。
17. 构建期变量与运行变量不一致怎么查?
查哪些值进入编译产物、哪些在服务进程启动后读,尤其 NEXT_PUBLIC_ 与 next.config 生成的规则。修改运行环境后重新 inspect 行为;不能假定同一镜像到处改 ENV 就改了浏览器包。
18. 边缘运行时能用所有 Node 库吗?
不能,运行时 API、原生扩展、文件系统和 TCP 能力受部署平台影响。按实际 target 验证依赖与连接方式;需要完整 Node 能力时明确选择,别因「更近用户」就把重后端逻辑迁过去。
19. ★ 多前端如何避免接口地址到处写?(项目)
frontend 按既定 constants/services 层管理地址与请求,console/gateway 用各自明确的代理目标配置。版本、scope 与 cookie 规则需统一约定;不要把配置分散复制到每个组件。
20. 面试如何说明你用 Next 的程度?(项目)
可以讲三个前端的版本、App Router、客户端状态、接口代理和 standalone。某页面实际主要 CSR 就如实讲,不能因为用了 Next 就声称深度实践了所有 RSC、Server Action 或复杂缓存能力。
项目事实与版本
2026-10-21 核对各仓库 package.json、next.config.ts 和实际源码:
| 项目 | 能确认的内容 |
|---|---|
../xknow-frontend/ | Next 15.3.6、React 19.1.0、antd 5.26.0、Redux Toolkit 2.6.0、SCSS;页面/组件→store/services→utils 分层,见 AGENTS.md、docs/ARCHITECTURE.md |
../xknow-console/ | Next 16.2.9、React 19.2.7、Tailwind 4,output=standalone |
../xknow-gateway/ | Next 16.2.9、React 19.2.7、Tailwind 4,output=standalone |
| 三个前端的 rewrite | frontend 有 /api/web、/api/ai、/api/ai_task 等规则;console 与 gateway 仅在分别配置 CONSOLE_API_PROXY_TARGET / GATEWAY_API_PROXY_TARGET 时启用对应规则,不能概括成所有部署都由 Next 转发全部 /api |
../xknow-payment/ | Node + Express 扫码收款服务;src/server.js 先挂载 notify 的 raw body 路由,再挂全局 express.json;src/wechatpay.js 含签名验证和外部请求超时 |
官方核对入口:React Effect、React use、Next 15 升级说明、Next 16 升级说明、Server / Client Components、Node 事件循环、Node Stream。Next 缓存和异步请求 API 有版本差异,回答时先报项目版本。
第一部分:React
三、Next.js
1. Next.js 是什么?为什么用它而不是纯 React(Vite)?
React 的全栈框架:文件即路由、服务端渲染、API 路由、图片 / 字体优化、构建优化开箱即用。我们三个前端都用它,而且都用它的 rewrite 把 /api/* 转发到后端,前端和后端同域,省掉跨域问题。
2. 渲染方式:CSR、SSR、SSG、ISR?
| 在哪生成 HTML | 适合 | |
|---|---|---|
| CSR 客户端渲染 | 浏览器里 JS 执行后生成 | 登录后的后台、强交互页面(我们的后台基本是这种) |
| SSR 服务端渲染 | 每次请求时在服务器生成 | 需要 SEO、首屏快、数据实时 |
| SSG 静态生成 | 构建时生成 | 文档、官网 |
| ISR 增量静态再生 | 静态页面定期在后台重新生成 | 内容偶尔更新的页面 |
3. App Router 的 Server Component 和 Client Component?
- App Router(
app/目录)里组件默认是 Server Component:在服务器运行,可以直接读数据库 / 调接口,不打包进浏览器 JS,不能用 useState / useEffect / 浏览器 API。 - 文件顶部写
'use client'就是 Client Component:可以用 Hooks 和交互。 - 原则:交互的部分做成 Client Component,尽量往组件树的叶子推。
4. 路由约定?
app/models/page.tsx → /models;app/models/[id]/page.tsx → /models/123(动态路由);layout.tsx 是共享布局;loading.tsx 加载态;error.tsx 错误边界;(app) 这种带括号的是路由分组,不影响 URL(AI 配置中心的 /(app) 就是这么组织的)。
5. Route Handler 和 Middleware?
app/api/xxx/route.ts里导出GET/POST函数,就是一个后端接口。middleware.ts:请求到达页面前执行,常用来做登录校验和重定向。
6. 环境变量?
NEXT_PUBLIC_ 开头的变量会在构建时编译进前端代码(浏览器能看到);其他的只在服务端可用。所以改了 NEXT_PUBLIC_* 必须重新构建镜像 —— 这是我们部署时的一条约定。密钥绝不能用 NEXT_PUBLIC_ 前缀。
7. Tailwind CSS 是什么?优缺点?
原子化 CSS:直接在 className 里写 flex items-center gap-2 px-4 text-sm。优点:不用起类名、样式就在组件旁边、最终 CSS 很小(只打包用到的);缺点:className 很长、需要记类名。对比产品前端用的 SCSS Modules(每个组件一个样式文件,类名自动加哈希防冲突)。
