Next.js 组件与骨架屏开发 (nextjs-component-dev)
专门的工作流,用于创建具有 Suspense 骨架屏、双层 TDD 测试(Jest + RTL 单元测试和 Playwright 集成/水合/视觉检查)、next-intl 字典支持、语义主题令牌以及通过 next-devtools MCP 实现的实时运行时诊断的生产就绪型 React Server Component (RSC) 和 Client Component。
[!TIP] 模块化资产与模板:
- Next.js 文档搜索与上下文:
references/nextjs-docs-lookup.md- 测试架构与验证:
references/testing-architecture-guide.md- Storybook 标准与分离:
references/storybook-reference.md- 即时导航与预取:
references/instant-navigation-and-prefetching.md- Next DevTools 调试指南:
references/next-devtools-debugging.md- 缓存与重新验证:
references/caching-and-revalidation.md- 代码模板:
resources/templates/(组件, 骨架屏, Jest 单元测试, Playwright 规范)- 参考实现:
examples/- 验证脚本:
scripts/verify-dev.ps1(Windows) /scripts/verify-dev.sh(Linux)
架构规则与标准
1. 规划上下文与路径
- 读取
docs/project.json以解析package_manager、new_component_dir、style_file_dir、component_library、dictionaries_dir(默认:"messages")和supported_languages。 - 所有内部路由必须使用来自
@/lib/routes的ROUTES。 - 所有作者/站点元数据必须使用来自
@/lib/site-config的SITE_CONFIG。 - 目标路径层次结构:
<new_component_dir>/<page_or_global>/<ComponentName>/- 类别:
global/用于共享布局框架;<page-name>/(例如home/、about/、lab/)用于页面范围的节段。
- 类别:
2. Next.js 内部文档查找 (node_modules/next/dist/docs)
- 通过 Codebase Memory MCP 搜索本地文档: 对于任何组件创建,使用
codebase-memoryMCP 工具(search_code、search_graph、get_code_snippet)主动查询并检查node_modules/next/dist/docs/下的本地 Next.js 发行版文档,以获取相关的 API 签名、指令('use cache'、'use client'、'use server')、内置组件(next/image、next/link、next/font、<Form>)、导航钩子(useRouter、usePathname)和缓存策略(cacheLife、cacheTag)。 - 消除弃用项与幻觉: 绝不依赖假设或过时的 Next.js 模式;与已安装包版本匹配的本地
node_modules/next/dist/docs是主要的事实来源。请参阅references/nextjs-docs-lookup.md。
3. 开发服务器与 Next DevTools 协议
- 开发服务器检查与调优: 在组件开发之前/期间,通过
next-devtoolsMCP 服务器(nextjs_index)检查 Next.js 开发服务器是否正在运行。 - 如果服务器正在运行: 立即调优到正在运行的服务器和端口;不要重新启动。
- 如果服务器未运行: 在后台启动开发服务器(
pnpm dev、IsDaemon: true),并通过nextjs_index验证连接。 - 运行时调试: 实现组件后,通过
next-devtools(nextjs_call)查询以立即检查错误、构建状态并诊断运行时问题。请参阅references/next-devtools-debugging.md。
4. RSC 边界与叶级 Client 下推
- 默认使用 Server Component: 保持组件为服务器渲染(
async function)。 - 将
"use client"下推: 将交互式处理程序(按钮、切换开关、表单输入)隔离到小的叶级 Client Component 中。 - RSC 组合: 将 Server Component 作为
children或 props 传递给 Client 包装器。绝不在"use client"文件内部导入 Server Component。
5. 样式、逻辑属性与主题令牌
- 语义令牌: 仅使用在
app/globals.css中定义的语义 CSS 变量(bg-background、text-foreground、border-border、text-muted-foreground)。禁止使用硬编码的十六进制颜色(#FAFAFA)或原始颜色缩放(bg-blue-500)。 - 类合并: 始终使用
cn(...)(clsx+tailwind-merge)合并类。 - 逻辑属性(双向文本): 仅使用 Tailwind 逻辑属性(
ms-、pe-、ps-、me-、start、end)。禁止使用物理方向类(ml-、mr-、pl-、pr-、left-、right-)。 - 进度链接: 对于主导航、英雄行动号召和交互式卡片,使用来自
@vercel/react-transition-progress的<Link>;对于静态实用链接,使用标准的next/link。 - 图片: 始终使用带有显式尺寸或
fill、响应式sizes以及用于首屏 LCP 资源的priority的next/image。
6. 即时导航、细粒度 Suspense 与缓存架构
- 即时组件的三个杠杆:
- 下推:将请求特定的异步操作(
await params、await searchParams、cookies()、headers()、未缓存的 DB/API 调用)提取到包裹在<Suspense>中的叶级子组件中。静态的父组件和兄弟组件直接提升到静态/App Shell 中。 - 缓存:在函数/组件级别将
'use cache'与cacheLife和cacheTag配对使用。使用 Session Bridging 模式:- 模式 A(提取并传递):从外部的
cookies()提取会话属性(例如team_id、role、tier),并将其作为参数传递给'use cache'函数,以便具有匹配属性的所有用户共享缓存数据(成本随团队/属性数量扩展,而非用户会话数量)。 - 模式 B(
"use cache: private"):对于严格特定于用户的会话查找,使用浏览器专属的会话缓存,其中stale >= 5m,随 App Shell 一起传输。
- 模式 A(提取并传递):从外部的
- 预取策略与密集网格:
- 默认 App Shell 预取(
<Link>/prefetch={null}):为每个路由预取一个共享的静态/App Shell。成本有上限($O(\text{routes})$),每个链接零服务器调用。用于密集的 feed、卡片网格(超过 50 张卡片)和批量导航。 - 每个链接预取(
<Link prefetch={true}>):在导航前解析动态 URL 数据(params、searchParams),每个可见链接需要 1 次服务器调用。谨慎用于高意图的主要行动号召、英雄操作或主从列表项目,其中必须消除骨架屏闪烁。 - 密集卡片网格:绝不在 feed 中的几十张卡片上使用 blanket
prefetch={true}。保留默认的<Link>或使用悬停/聚焦意图预取(router.prefetch())。
- 默认 App Shell 预取(
- 下推:将请求特定的异步操作(
- 细粒度加载状态(反全页闪烁):永远不要将整个组件或页面包裹在单个顶级
<Suspense>边界中,这会导致整个骨架屏闪烁。保持标题、布局框架和缓存内容立即可见;仅在动态流式传输插槽周围放置<Suspense>。 - 原生 Next.js 16 缓存指令:请参阅
references/instant-navigation-and-prefetching.md和references/caching-and-revalidation.md。
7. TanStack Query 与服务器预取
- 统一缓存契约: 使用显式的
staleTime(例如30_000毫秒)定义key、tag和queryOptions。 - 服务器预取: 触发未等待的预取(
void queryClient.prefetchQuery(...)),直接调用内部 DB 函数(在服务器上零相对 fetch)。使用<HydrationBoundary>进行水合。 - 流式组件: 在
<Suspense fallback={<[ComponentName]Skeleton />}>内部使用useSuspenseQuery。 - 乐观更新: 使用带有
onMutate缓存快照和onError回滚的useMutation;使用updateTag(cache.tag)调用 Server Action。
8. 双层测试分工(Jest vs. Playwright)
- Jest + RTL(
[ComponentName].test.tsx):- 在
jsdom中快速反馈循环。 - Props 排列、条件性 UI 元素以及空/null 状态。
- 通过
@testing-library/user-event进行用户交互(绝不使用fireEvent)。 - Next.js 路由模拟(来自
next/navigation的useRouter、usePathname、useSearchParams)。 - 在
NextIntlClientProvider内部进行next-intl字典插值和复数检查。 - 可访问的角色查询(
screen.getByRole)和自动化 a11y 检查(jest-axe)。
- 在
- Playwright(
[ComponentName].spec.ts或页面级规范):- 真实浏览器执行(Chromium/WebKit/Firefox)。
- 即时 Shell 断言(
@next/playwright): 使用instant(page, ...)辅助函数断言静态 shell 和预取的 App Shell 在动态服务器流式传输解析之前立即渲染。 - 零水合不匹配: 监听浏览器控制台事件(
page.on('console'))以检测并使测试因 React SSR 水合警告而失败。 - 视觉与双向文本回归: 使用
expect(page).toHaveScreenshot()跨主题(浅色与深色 OKLCH 变量)和文本方向(dir="ltr"与dir="rtl")进行测试。 - 网络弹性: 使用
page.route()测试缓慢的网络响应(验证 Suspense 骨架屏匹配几何形状以防止 CLS)和 500 错误边界。
- 详细的测试标准: 请参阅
references/testing-architecture-guide.md。
阶段 0:实施计划与审批关口
[!IMPORTANT] 先计划后执行: 在执���任何写入操作、修改字典或在仓库中创建组件之前,始终生成并展示一个
implementation_plan.md工件,详细说明所有计划的文件创建、修改、TypeScript 契约、翻译字典添加和 TDD 测试用例。等待用户确认/批准后再继续执行。
实施计划必须涵盖:
- 目标架构与路径:完整的目标目录(
<new_component_dir>/<page_or_global>/<ComponentName>/)和分类(RSC 与 Client 叶级组件)。 - 已咨询的 Next.js 本地文档:在
node_modules/next/dist/docs/下检查的具体文档路径(例如04-api-reference/04-components/image.md、03-directives/use-cache.md、04-api-reference/02-functions/use-router.md)。 - TypeScript 契约:带有严格英文 TSDoc 注释的 Props 接口和类型。
- 字典策略:要添加到
docs/project.json中所有supported_languages的messages/[locale].json中的显式翻译命名空间和键(零硬编码字符串或文件内模拟字典)。 - 主题令牌与样式:已识别的语义 OKLCH CSS 变量和逻辑布局类。
- 测试与诊断策略:
- Jest 单元测试(
[ComponentName].test.tsx):模拟配置(next/navigation)、props 变体、回调断言、NextIntlClientProvider集成和 a11y 角色查询。 - Playwright 集成场景(
[ComponentName].spec.ts):视觉快照目标(浅色/深色主题令牌、LTR 与 RTL 逻辑布局)、网络限速/骨架屏几何形状检查和水合验证监听器。 - Next DevTools 诊断:通过
next-devtools进行运行时错误和编译检查。
- Jest 单元测试(
- 验证关口:要运行的确切验证命令(
verify-dev.ps1、目标单元测试和 Playwright e2e 规范)。
工作流步骤
-
步骤 0:实施计划生成与审批关口
- 通过
codebase-memoryMCP(search_code、search_graph)搜索并检查node_modules/next/dist/docs,以获取计划组件所利用的任何 Next.js API、指令、钩子或组件,确保上下文是最新的。 - 综合组件需求,扫描
docs/project.json,并生成implementation_plan.md,记录已咨询的文档和契约。 - 在工件上设置
request_feedback = true和user_facing = true。 - 在编写任何代码之前等待用户审查和明确批准。
- 通过
-
步骤 1:开发服务器验证与 Next DevTools 连接
- 通过
nextjs_index查询next-devtoolsMCP 以检测正在运行的 Next.js 开发服务器实例。 - 如果开发服务器正在运行: 调优到活动端口和服务器实例;继续开发而无需重新启动。
- 如果开发服务器未运行: 在后台启动开发服务器(
pnpm dev、IsDaemon: true),并使用nextjs_index验证发现。
- 通过
-
步骤 2:字典填充与 TypeScript 契约定义
- 读取
docs/project.json以解析dictionaries_dir(默认是messages)和supported_languages。 - 定义组件的翻译命名空间和键。
- 填充所有字典文件(
messages/en.json、messages/fa.json等),在编写 JSX 之前为每种支持的语言提供真实的翻译。 - 使用严格的英文 TSDoc 注释(
@param、@defaultValue、@returns)定义 Props 接口。 - 如果支持的语言多于一种,组件必须首先获取翻译,如果失败则使用回退。
- 读取
-
步骤 3:TDD 基线单元测试(通过 Jest + RTL 的
[ComponentName].test.tsx)- 在实现组件之前编写
[ComponentName].test.tsx。 - 模拟
next/navigation钩子(useRouter、usePathname、useSearchParams)。 - 在
NextIntlClientProvider中包装渲染的组件,提供字典messages和活动的locale。 - 测试方向属性(
dir="rtl"与dir="ltr")、默认 props、交互式回调(@testing-library/user-event)、Suspense 骨架屏回退和语义 ARIA 角色。
- 在实现组件之前编写
-
步骤 4:Playwright 集成与水合/视觉规范(
[ComponentName].spec.ts)- 使用 Playwright 编写端到端规范。
- 断言即时 App Shell 渲染(使用来自
@next/playwright的instant())。 - 确认零水合不匹配(通过控制台事件监听器)。
- 跨主题(浅色/深色)和方向(LTR/RTL)捕获视觉快照。
- 测试网络降级场景(缓慢的 API、错误边界)。
-
步骤 5:Next DevTools 运行时诊断
- 在实施后查询
next-devtoolsMCP 以检查构建状态和运行时错误。 - 通过自动化工具修复任何已识别的问题。
- 在实施后查询
-
步骤 6:最终验证与批准
- 运行完整的测试套件:单元测试和 Playwright e2e 规范。
- 运行
scripts/verify-dev.ps1(Windows)或scripts/verify-dev.sh(Linux)以执行最终的一致性检查。 - 等待用户最终批准。