惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Hacker News: Ask HN
Hacker News: Ask HN
N
News and Events Feed by Topic
Forbes - Security
Forbes - Security
The Last Watchdog
The Last Watchdog
TaoSecurity Blog
TaoSecurity Blog
Schneier on Security
Schneier on Security
SecWiki News
SecWiki News
V
Vulnerabilities – Threatpost
Project Zero
Project Zero
O
OpenAI News
W
WeLiveSecurity
Security Archives - TechRepublic
Security Archives - TechRepublic
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
H
Hacker News: Front Page
Cisco Talos Blog
Cisco Talos Blog
Spread Privacy
Spread Privacy
Help Net Security
Help Net Security
P
Privacy & Cybersecurity Law Blog
K
Kaspersky official blog
S
Security @ Cisco Blogs
Latest news
Latest news
AWS News Blog
AWS News Blog
U
Unit 42
Martin Fowler
Martin Fowler
阮一峰的网络日志
阮一峰的网络日志
S
Secure Thoughts
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Know Your Adversary
Know Your Adversary
Scott Helme
Scott Helme
博客园 - 司徒正美
B
Blog RSS Feed
C
Check Point Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
D
Docker
Google Online Security Blog
Google Online Security Blog
Jina AI
Jina AI
aimingoo的专栏
aimingoo的专栏
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Last Week in AI
Last Week in AI
月光博客
月光博客
C
CXSECURITY Database RSS Feed - CXSecurity.com
S
SegmentFault 最新的问题
NISL@THU
NISL@THU
T
The Blog of Author Tim Ferriss
C
Cisco Blogs
Attack and Defense Labs
Attack and Defense Labs
小众软件
小众软件

少数派

派早报:Google 发布 Fitbit Air 等 - 少数派 「新人报到」確認需求,再開始 - 少数派 从 SOLO 独立开发者社区,我看到了越来越多开发者开始做自己的产品 - 少数派 我怎么管理那些"不常做,但总会忘"的生活事项 - 少数派 人形机器人量产元年,数据才是具身智能的“生死线” - 少数派 BuhoLaunchpad 高度还原 Mac 启动台:开发历程与思考 - 少数派 五年陪伴依然不舍,DIY 换壳后让罗技 MX Master 3 继续服役 - 少数派 新玩意 240|少数派的编辑们最近买了啥? - 少数派 一日一技|为什么你应该关闭 iOS 的键盘声音 - 少数派 我做了个插件和 Skills,一键提取任何网站的设计规范 Design.md - 少数派 住在三四线城市的你,该开始录播客了 - 少数派 甘南秘境,大白高国 - 少数派 AI的审美:谁让把我变成川内倫子 - 少数派 返工怎能不烦恼,打工人片单总有一部是你的「嘴替」 - 少数派 为了让「上厕所」更健康,我做了一个小工具 - 少数派 AI + Skill,能够让生成的文章去除 AI 味吗? - 少数派 新玩意|韶音OpenDots ONE 耳夹式耳机 - 少数派 《美满》| 在每一个春天的晚上相爱(362) - 少数派 新玩意|优篮子 PS01 MagSnap 磁吸支架 - 少数派 自我整合手记 | 我开始早睡了:用稳定规则,为自由托底 - 少数派 用龙虾(OpenClaw)两个多月,我最深的12个体会 - 少数派 听歌时间到,12 张你可能错过的 2025 华语乐坛好专辑 - 少数派 承诺能追吗 - 少数派 macOS 26启动台没了? 我做了个不一样的App启动器 - Keboard - 少数派 《四海为家的人》| INTJ对话INTJ(361) - 少数派 你发过的那些黑历史,是时候一次清干净了 - 少数派 新玩意:安安静静玩,越玩越专注:计客密码机 - 少数派 iPad 用户首次体验 Android 平板:vivo Pad6 Pro - 少数派 数据逻辑强 - 少数派 极北行+ | 一路向北,探访日本至北之地 | 001 - 少数派 万字剖析:千问App深度体验报告(2026) - 少数派 在2026年,如何真正防止别人抄袭你的作品 - 少数派 怎么用 50 块搭个 AI 语音助手?我踩了 3 天坑 - 少数派 YeeroAI:让 AI 对话真正成为知识管理的一部分 - 少数派 爬泰山 - 少数派 「旅图显影」 App 更新:这次,我们补上了一点「手感」 - 少数派 假期出门太折磨?我的 23 条经验帮你规划惬意旅行 - 少数派 工作流会变吗 - 少数派 Claude Opus 4.6 怎么用最省钱?我测了 5 种方案 - 少数派 GPT Image 2 让图文并茂不再稀罕 - 少数派 用户侧出发——什么是AI,我要不要学习? - 少数派 找片、转存、整理、播放一条龙!让你的付费网盘值回票价 - 少数派 欢迎试用!日课一问2.0插件 - 少数派 自己做的MDeditor,原本想购买 Typora 试了两次支付不成功,干脆自己做一个 - 少数派 vibe coding了一个 3MB 的小工具,让 ~/Downloads 彻底告别混乱 - 少数派 因为受不了 Mac 的风扇策略,我做了一个风扇控制工具 - 少数派 别只怪模型 - 少数派 Warp 终端的 AI 功能怎么用?我测了一周的体验 - 少数派 AI 写代码老是出 bug?这 5 个配置我后悔没早知道 - 少数派 「新玩意」苹果出相机可能就这样:Sigma BF + 45mm F2.8 DG Contemporary - 少数派 一个面向2030年的AI操作系统是什么样子的:浅谈cola这款有灵魂的Agent - 少数派 别只看写代码 - 少数派 每天解决10个问题,还是一口气攻坚解决400个? - 少数派 AI 交易机器人怎么搭?我用 Claude 跑了一周实盘 - 少数派 Maptoposter Online:把你爱的城市画成艺术海报 - 少数派 Function Calling 怎么用?我测了 3 个模型发现差距真大 - 少数派 Legend Talk:我做了个 AI 圆桌,让 160 位思想家围着你的问题转 - 少数派 如何找到自己的蓝方?在小县城寻找压力测试 - 少数派 语音输入与软件接口|2026年聊AI时,我们都聊些什么(上) - 少数派 混动已经卖爆,纯电又来补刀——钛7闪充版简直“不讲武德” - 少数派 本月玩什么|朋友收藏、识质存在、沙罗周期 - 少数派 为什么要每天坚持输出? - 少数派 Claude API 挂了好几个小时,你的项目有备用方案吗? - 少数派 Function Calling 没你想的复杂——我用它做了个有点用的工具 - 少数派 登录系统立即播放视频或者图片音乐的软件 - 少数派 我为什么创建 FlipHTML5 下载工具 - 少数派 残局没电?多品牌外设电量统一管理软件EasyBluetooth已支持RTSS游戏内显示以及AIDA64 - 少数派 前往通义路的路 - 少数派 太好看了,媲美Sun的个人导航页,NAS部署星云门户 - 少数派 乌黑嘴唇“一键检测”上线了 - 少数派 派早报:Claude AI 接入多个创意软件生态、FILCO 生产方接手品牌等 - 少数派 【更新】BearCLI、Claude 连接器与 MCP 服务器 - 少数派 记了上千条流水,还是看不懂财务?我做了一个让 AI 读懂账本的工作台 - 少数派 MINI R56 升级原厂 Sport 模式 - 少数派 新玩意 | 一棵柠檬树(仿真版) - 少数派 Momenta的“物理AI”野望,需迈过“含摩量”这道关 - 少数派 网页直接投屏控制手机!NAS一键部署PandaScrcpy,流畅丝滑可远程。 - 少数派 众测|邀你一同探索随身 AI 硬件入口 YoooClaw C·ONE - 少数派 2050大会:分享时间是真诚 参会记 - 少数派 iPad 赋能电影创作:国内首部宣纸手绘长片《燃比娃》的幕后故事 - 少数派 AI的审美:我用 8 个大模型给 100 张旅行照片打分 - 少数派 普通人如何破圈?去参加一个本地协会 - 少数派 把极空间的图标全换了,主题DIY全攻略打造你的专属NAS桌面 - 少数派 电子便签墙,帮你实现便签自由 - 少数派 我如何用三个 CLI 工具取代文档创建需求 - 少数派 原来真的有人可以玩一辈子 - 少数派 社区速递 139 | 派友热议三月买了啥、复古单反尼康 Df 体验 - 少数派 06 作品的赏析与评价 - 少数派 TDS REVIEW|索尼 WF-1000XM6 降噪真无线耳机体验 - 少数派 35.98万起售的第二代腾势D9,我看重的不是堆料,而是不凑合 - 少数派 鼠须管 Squirrel 皮肤配置指北 - 少数派 从watch ultra2换到redmi watch6 - 少数派 派早报:阿里巴巴发布视频生成模型 HappyHorse 1.0 等 - 少数派 别迷信1M - 少数派 家人们天塌了!网盘“大封杀”,多个渠道多条路,NAS部署PanHub - 少数派 AI与人勾心斗角!NAS一键部署AI狼人杀,假日休闲必备。 - 少数派 电商必备!Comfyui工作流批量生图插件,一次生成12张!支持Nano banana pro模型 - 少数派 Comfyui工作流配置Gpt-image-2模型教程,0.03/张 - 少数派 OpenClaw第三方APi怎么配置?可使用Gpt-image-2模型 - 少数派 会员社区话题精选 Ep. 103 - 少数派
Next.js面试题:API深度解析 - 少数派
2025-06-17 · via 少数派

Next.js面试题:API深度解析

Next.js 通过 App Router 的引入彻底改变了 Web 开发范式。在这个新时代,深入理解 Next.js 的 API 函数不再只是锦上添花,而是技术面试中的关键区分点。这些函数构成了构建高性能、可扩展、现代化 Web 应用的基石。

本文将系统地解析 Next.js 的各类函数,不仅阐述它们的基本功能,更深入探讨实际应用场景、细微差别以及面试中可能出现的问题。我们将着重于理解每个函数背后的实现原理与设计思路。

缓存是 Next.js 性能策略的核心。面试中,候选人需要清晰阐述不同缓存层级和控制机制。

扩展的 fetch API

Next.js 对原生 fetch API 进行了扩展,为数据获取提供了精细的服务器端缓存控制。

在实际开发中,我们可以通过几个关键配置选项来控制缓存行为:

JavaScript

// 默认行为,开发环境每次请求获取,生产环境静态路由只获取一次const data = await fetch('https://api.example.com/data');

// 始终从服务器获取最新数据,不使用缓存const freshData = await fetch('https://api.example.com/data', { cache: 'no-store' });

// 优先使用缓存,设置60秒的重新验证时间const cachedData = await fetch('https://api.example.com/data', {
  next: { revalidate: 60 }
});

// 使用缓存标签,便于精确失效const taggedData = await fetch('https://api.example.com/products', {
  next: { tags: ['products'] }
});

这些缓存控制选项让开发者能够根据数据的性质和更新频率来优化应用性能。

缓存失效机制

Next.js 提供了两种主要的缓存失效方法:

按路径失效revalidatePath 允许我们清除特定路径的缓存数据。

JavaScript

// 在Server Action中使用async function updateProduct(formData) {
  await saveProduct(formData);
  // 失效产品列表页面的缓存
  revalidatePath('/products');
  // 注意:目前在Server Action中使用会使客户端路由缓存中的所有路由失效
}

按标签失效revalidateTag 让我们能够更精确地失效与特定标签关联的缓存数据。

JavaScript

// 在Server Action中使用async function updateProduct(formData) {
  await saveProduct(formData);
  // 只失效带有'products'标签的缓存数据
  revalidateTag('products');
}

面试中,理解这些缓存机制的工作原理以及何时使用哪种方法是展示你对 Next.js 深入理解的好机会。

Next.js 中的 HTTP 请求处理

Next.js 在标准 Web API 之上提供了强大的抽象,用于处理 cookies、headers 和构建响应。

cookies 函数

cookies() 函数是一个异步函数,用于在 Server Components 中读取请求 cookies,以及在 Server Actions 或 Route Handlers 中读取/写入 cookies。

JavaScript

// 在Server Component中读取cookieimport { cookies } from 'next/headers';

async function UserProfile() {
  const cookieStore = cookies();
  const theme = cookieStore.get('theme');

  return <div>Current theme: {theme?.value || 'default'}</div>;
}

// 在Server Action中设置cookieasync function setTheme(theme) {
  'use server';

  cookies().set('theme', theme, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    maxAge: 60 * 60 * 24 * 7, // 一周path: '/'
  });

  // 重定向或返回数据
}

值得注意的是,从 Next.js 15 开始,cookies() 函数变为异步,这是一个重要变化。使用此函数会使路由动态渲染,因为它依赖于运行时请求信息。

headers 与请求处理

headers() 函数让我们能够在 Server Component 中访问传入请求的头部信息:

JavaScript

import { headers } from 'next/headers';

async function UserAgentComponent() {
  const headersList = headers();
  const userAgent = headersList.get('user-agent');

  return <div>Your browser: {userAgent}</div>;
}

在 Middleware 和 Route Handlers 中,Next.js 提供了增强的 NextRequestNextResponse 对象,它们扩展了标准 Web API:

JavaScript

// 在Middleware中使用import { NextRequest, NextResponse } from 'next/server';

export function middleware(request: NextRequest) {
  // 检查用户代理const userAgent = request.headers.get('user-agent');

  // 基于移动设备重定向if (userAgent && userAgent.includes('Mobile')) {
    return NextResponse.redirect(new URL('/mobile', request.url));
  }

  // 添加自定义头部并继续const response = NextResponse.next();
  response.headers.set('x-custom-header', 'my-value');
  return response;
}

面试中,理解这些 API 的异步特性以及它们如何影响渲染策略是关键点。例如,你可以解释如何在需要保持页面大部分静态的同时访问 cookies 或 headers 信息。

Next.js 路由导航与控制

Next.js 提供了一套完整的路由系统,相关钩子和函数让开发者能够精确控制导航和访问路由信息。

客户端导航钩子

useRouter 是最常用的客户端导航钩子,提供了编程式路由控制:

JavaScript

'use client'import { useRouter } from 'next/navigation'export default function NavigationButtons() {
  const router = useRouter()

  return (
    <div><button onClick={() => router.push('/dashboard')}>Go to Dashboard</button><button onClick={() => router.back()}>Go Back</button><button onClick={() => router.refresh()}>Refresh Current Page</button></div>
  )
}

useRouter.refresh() 特别值得注意,它会重新获取数据并重新渲染 Server Components,但保留客户端状态,这与完整页面刷新有很大不同。

其他有用的导航钩子包括:

usePathname(): 获取当前URL路径

useParams(): 访问动态路由参数

useSearchParams(): 读取URL查询字符串

useSelectedLayoutSegment(s): 了解活动路由段

JavaScript

'use client'import { usePathname, useParams, useSearchParams } from 'next/navigation'export function RouteInfo() {
  const pathname = usePathname();
  const params = useParams();
  const searchParams = useSearchParams();

  return (
    <div><p>Current path: {pathname}</p><p>Route params: {JSON.stringify(params)}</p><p>Search query: {searchParams.get('q')}</p></div>
  );
}

重定向与错误处理

Next.js 提供了几个用于控制导航流程的函数:

JavaScript

import { redirect, permanentRedirect, notFound } from 'next/navigation';

// 临时重定向
redirect('/login');

// 永久重定向(对SEO更友好)
permanentRedirect('/new-page');

// 显示404页面
notFound();

这些函数在不同上下文中的行为略有不同。例如,redirect 在 Server Actions 中使用 303 状态码,而在其他情况下使用 307 状态码。了解这些细微差别对于处理表单提交和保留请求方法非常重要。

元数据优化与SEO

Next.js 提供了强大的工具来管理元数据,这对SEO和社交媒体分享至关重要。

动态元数据生成

generateMetadata 函数允许我们基于路由参数或外部数据动态生成页面元数据:

TypeScript

// app/products/[id]/page.tsxexport async function generateMetadata({ params }) {
  const product = await getProduct(params.id);

  return {
    title: product.name,
    description: product.description,
    openGraph: {
      images: [{ url: product.imageUrl }]
    }
  };
}

export default function ProductPage({ params }) {
  // 页面组件
}

Next.js 会自动记忆化 generateMetadata 中的数据获取,并在构建时(对静态路由)或请求时(对动态路由)生成元数据。

动态图像生成

对于社交媒体分享图像,ImageResponse 提供了使用JSX和CSS动态生成图像的能力:

TypeScript

// app/products/[id]/opengraph-image.tsximport { ImageResponse } from 'next/og';

export const runtime = 'edge';

export async function GET(request, { params }) {
  const product = await getProduct(params.id);

  return new ImageResponse(
    (
      <divstyle={{display: 'flex',
          fontSize: 48,
          background: 'white',
          width: '100%',
          height: '100%',
          padding: 32,
          alignItems: 'center',
          justifyContent: 'center'
        }}
      ><img src={product.imageUrl} width="200" height="200" /><h1>{product.name}</h1></div>
    ),
    {
      width: 1200,
      height: 630
    }
  );
}

这种方法比静态图像更灵活,可以为每个产品或文章生成独特的社交媒体预览图像。

服务器端逻辑与构建优化

Next.js 使用特定函数来指导其构建过程,特别是在静态生成和处理服务器端任务方面。

静态路由生成

generateStaticParams 函数是静态站点生成的核心,它允许我们在构建时预渲染动态路由:

TypeScript

// app/blog/[slug]/page.tsxexport async function generateStaticParams() {
  const posts = await getPosts();

  return posts.map((post) => ({
    slug: post.slug
  }));
}

export default function BlogPost({ params }) {
  // 页面组件
}

这个函数在构建时运行,为每个返回的参数集生成一个静态路由。它可以与 dynamicParams 配置结合使用,控制未预生成路径的处理方式:

JavaScript

// 允许按需生成未预渲染的路径(默认行为)
export const dynamicParams = true;

// 仅允许访问预生成的路径,其他返回
404export const dynamicParams = false;

响应后任务

after 函数允许我们调度在响应完成后执行的任务,这对于不应阻塞初始响应的操作(如日志记录、分析)非常有用:

JavaScript

import { after } from 'next/server';

export async function GET() {
  // 主要响应逻辑const data = await fetchData();

  // 调度响应后任务
  after(() => {
    // 这不会阻塞响应
    logAccess();
    updateAnalytics();
  });

  return Response.json(data);
}

after 不会使路由动态化,即使对于静态页面,回调也会在构建时或重新验证时执行。这使得它成为处理副作用的理想选择,同时保持性能优势。

内容预览模式

draftMode 函数为内容创建者提供了查看未发布内容的能力,这对于与无头CMS集成特别有用:

TypeScript

// app/api/enable-draft/route.tsimport { draftMode } from 'next/headers';

export async function GET(request) {
  const { searchParams } = new URL(request.url);
  const secret = searchParams.get('secret');

  // 验证预览请求if (secret !== process.env.PREVIEW_SECRET) {
    return new Response('Invalid token', { status: 401 });
  }

  // 启用草稿模式
  draftMode().enable();

  return new Response('Draft mode enabled');
}

在页面组件中,我们可以检查草稿模式状态并相应地获取内容:

TypeScript

// app/page.tsximport { draftMode } from 'next/headers';

export default async function Page() {
  const { isEnabled } = await draftMode();

  // 根据草稿模式状态获取内容const content = await getContent({ draft: isEnabled });

  return (
    <div>
      {isEnabled && <div className="draft-banner">Draft Mode</div>}
      <h1>{content.title}</h1><div>{content.body}</div></div>
  );
}

授权与错误状态管理

Next.js 提供了几个实验性函数来处理常见的授权和错误状态,使开发者能够创建一致的用户体验。

授权状态处理

forbiddenunauthorized 函数(实验性)提供了一种声明式方法来处理授权失败:

TypeScript

// app/admin/page.tsximport { forbidden, unauthorized } from 'next/server';
import { getCurrentUser } from '@/lib/auth';

export default async function AdminPage() {
  const user = await getCurrentUser();

  if (!user) {
    // 用户未登录,显示401页面
    unauthorized();
  }

  if (!user.isAdmin) {
    // 用户无权访问,显示403页面
    forbidden();
  }

  return <AdminDashboard user={user} />;
}

这些函数会抛出错误,触发渲染相应的错误页面(unauthorized.jsforbidden.js),可以在这些页面中提供自定义UI,如登录表单。

错误传播控制

unstable_rethrow 函数解决了一个微妙但重要的问题:确保 Next.js 内部错误(如从 notFound()redirect() 抛出的错误)不会被用户的 try/catch 块意外捕获:

JavaScript

import { unstable_rethrow } from 'next/dist/client/components/error-boundary';

async function fetchAndDisplayProduct(id) {
  try {
    const product = await fetchProduct(id);

    if (!product) {
      notFound();
    }

    return <ProductDetails product={product} />;
  } catch (error) {
    // 清理资源
    closeConnections();

    // 确保 Next.js 错误继续传播
    unstable_rethrow(error);

    // 这里的代码永远不会执行
  }
}

这确保了 Next.js 的控制流机制能够正常工作,同时仍然允许开发者在错误处理中执行必要的清理。

性能监控与Web Vitals

监控核心 Web 指标对于了解真实用户体验和识别性能问题至关重要。

Web Vitals 报告

useReportWebVitals 钩子使我们能够收集和报告关键性能指标:

JavaScript

'use client'import { useReportWebVitals } from 'next/web-vitals';

export function WebVitalsReporter() {
  useReportWebVitals((metric) => {
    // 根据指标类型进行处理switch (metric.name) {
      case 'FCP':
        // 首次内容绘制console.log('FCP:', metric.value);
        break;
      case 'LCP':
        // 最大内容绘制console.log('LCP:', metric.value);
        break;
      case 'CLS':
        // 累积布局偏移console.log('CLS:', metric.value);
        break;
      case 'FID':
        // 首次输入延迟console.log('FID:', metric.value);
        break;
      case 'TTFB':
        // 首字节时间console.log('TTFB:', metric.value);
        break;
      case 'INP':
        // 交互到下一次绘制console.log('INP:', metric.value);
        break;
    }

    // 发送到分析服务
    sendToAnalytics({
      id: metric.id,
      name: metric.name,
      value: metric.value,
      rating: metric.rating // 'good', 'needs-improvement', 'poor'
    });
  });

  return null; // 这个组件不渲染任何UI
}

通常,我们会在根布局中包含这个组件,以跟踪整个应用程序的性能:

TypeScript

// app/layout.tsximport { WebVitalsReporter } from '@/components/web-vitals';

export default function RootLayout({ children }) {
  return (
    <html lang="en"><body><WebVitalsReporter />
        {children}
      </body></html>
  );
}

通过收集这些指标,我们可以识别性能瓶颈,衡量优化的影响,并确保为用户提供流畅的体验。

总结:掌握 Next.js API 函数的关键

深入理解 Next.js 的 API 函数不仅是应对面试的关键,更是构建高性能、可维护应用的基础。这些函数反映了 Next.js 的核心设计理念:

性能优先:通过精细的缓存控制、静态生成和响应后任务等机制,Next.js 优化了应用性能。

开发体验:函数 API 提供了直观的接口,使复杂任务变得简单,如动态元数据生成和路由控制。

渐进增强:从基本功能到高级特性,Next.js 提供了一系列可组合的 API,让开发者能够根据需要逐步采用。

标准对齐:许多 API 都基于 Web 标准,如 fetchHeadersResponse,使学习曲线更平缓。

在面试中,不仅要展示对这些函数的了解,更要展示对它们背后原理的理解,以及如何在实际项目中应用它们来解决具体问题。考虑各种权衡,如静态生成与动态渲染、客户端与服务器状态管理等,将使你的回答更加全面和深入。

随着 Next.js 的不断发展,保持对新特性和最佳实践的了解也很重要。实验性 API(如 forbiddenunauthorized)表明了框架未来的发展方向,了解这些可以让你在面试中展示前瞻性思维。

最后,精通这些函数可以显著增强应聘者在面试中的信心和表现。通过深入理解 Next.js 的核心概念和 API,你将能够自信地应对各种技术挑战,并展示自己作为现代 Web 开发者的专业素养。