Communitygithub.com

React 前端规则

为 React/TypeScript 前端开发提供全面的规则与参考,涵盖架构、组件、状态管理、路由、测试、可访问性和安全性。

React 前端规则 是什么?

该规则集旨在为 React/TypeScript 前端项目提供一套完整、强制的开发规范。它明确了技术栈(如 Vite SPA 或 React Router 框架模式、TanStack Query、Zustand、Zod 等),并强制采用 Feature-Sliced Design 作为项目结构。规则中包含了从组件编写、数据获取、表单处理到可访问性、测试、安全性和容器化部署等各个方面的“始终适用”原则,如“派生状态而非副作用”、“服务器数据仅存于 TanStack Query”、“可访问性内建,从不事后添加”和“浏览器存储中不留令牌”。此技能适用于使用 Cursor、Claude Code 或 Codex 等工具的开发者,作为开发任何 React 前端时的权威指南,确保代码库的一致性和高质量。

兼容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/mehmetmuejde/agent-skills/tree/HEAD/skills/react-frontend

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

React 前端

适用于每个 React 前端的规则。此文件包含了始终适用的原则;在开始相关主题的工作前,请先阅读匹配的参考资料。

任务阅读
文件夹、层、切片、公共API、导入、桶文件(barrel files)references/structure.md
FSD 深入:决策树、交叉导入、实体、资产、认证/API 放置、框架连接、迁移references/fsd/(索引在 structure.md 末尾)
命名、文件大小、属性、设计系统、布局、常量references/code-style.md
组件、Hook、副作用、记忆化、过渡、长列表、水合references/hooks-and-rendering.md
瀑布请求、包体积、代码分割、预加载、重渲染成本references/performance.md
服务器数据、查询、变更、加载器、搜索参数、Zustandreferences/data-and-state.md
表单、验证、表单错误references/forms.md
语义、键盘、焦点、对比度、活动区域、无障碍测试references/accessibility.md(React 实现)+ frontend-accessibility 技能(完整规则、审计)
单元测试、组件测试和端到端测试、覆盖率、API 模拟references/testing.md
故事、Storybook 无障碍检查、视觉回归references/storybook.md
XSS、渲染 HTML/Markdown/LLM 输出、认证、CSRF、CSP、环境变量、登出references/security.md
Node 版本、包管理器、pre-commit + gitleaks、依赖审计references/tooling.md
翻译、语言切换、<html lang>references/i18n.md
新建项目设置references/setup.md
前端的容器镜像references/docker.md + docker-kubernetes 技能

技术栈

  • React 19(≥ 19.2 以获得 useEffectEvent 和 <Activity>)· TypeScript strict
  • 渲染:Vite SPA 或 React Router 框架模式(SSR + 水合)。标记为 React Router 框架专属 的规则仅适用于此模式。无 Next.js、无 React Server Components、无 SWR。
  • 路由:TanStack Router 或 React Router — 每个项目固定,从代码中检测,切勿混用。
  • 服务器状态:TanStack Query · 客户端状态:Zustand
  • 表单:React Hook Form + Zod 或 TanStack Form + Zod — 每个项目固定
  • 验证:每个边界处使用 Zod(API 响应、表单、搜索参数、环境变量、存储、postMessage)
  • 工具链:Biome(lint + format)、Steiger(FSD 规则)、Vitest + Testing Library、Playwright、Storybook
  • 无 React Compiler → 记忆化手动进行,但仅限测量之后。

结构 — Feature-Sliced Design

层级 app → pages → widgets → features → entities → shared;仅向下导入;禁止同层切片之间的导入;每个切片仅通过其 index.ts 文件导入,且显式命名导出(无 export *)。shared/ui 和 shared/lib 每个组件/库对应一个索引文件。从 app、pages、shared 开始;不要创建空的层级文件夹。代码保留在页面中,直到满足提取规则 — 即当前在多个地方使用、有独立于任何消费者的变更理由、以及有集中的职责;三者都满足时方可提取,在此之前允许重复。不鼓励使用 widgets:仅当某组合块在多个页面中复用且不能放在页面中时才使用(现有 widget 继续有效)。详情:references/structure.md,上游规则手册 references/fsd/rules.md。

  • 一个文件一个组件,一个文件一个 Hook,每个组件约 150 行;组件以其切片名称作为前缀(references/code-style.md)。
  • 优先使用设计系统:使用来自 shared/ui/ 的自有组件;切勿在 shared/ui/ 外部导入 shared/ui/primitives/(UI 库 CLI 输出,切勿编辑)。在检查设计系统组件、属性和标记能实现什么之前,不要新增 CSS。

组件和 Hook — 始终如此

  • 切勿在另一个组件内部定义组件 — 这样会导致每次渲染时重新挂载。
  • 派生,而非同步:可从 props/state 计算得出的值在渲染期间计算。不要使用 useEffect 将 props 或 state 复制到 state 中。使用 key 重置。
  • 用户操作在事件处理函数中执行,而非在由状态标志触发的 effect 中。
  • Effect 仅用于与外部系统同步,具有狭窄的基本类型依赖,每个 effect 只关注一件事,并提供清理函数。切勿禁用 exhaustive-deps 规则。
  • 当新值依赖于旧值时,使用 setState(prev => …);对于昂贵的初始值,使用 useState(() => expensive())。
  • 切勿修改 props 或 state:使用 toSorted()、toReversed()、toSpliced()、with()、展开运算符。
  • 使用 {count > 0 ? <X /> : null} — 切勿在左侧为数字时使用 &&。
  • 不要在 useEffect 中使用 fetch;服务器数据来自 TanStack Query 或路由加载器。
  • memo/useMemo/useCallback 仅在性能分析之后或需要引用稳定性时使用。
  • 错误绝不能静默处理:无空的 catch,无 .catch(() => {})。每个路由都有一个错误边界;每个查询都有加载、错误和空 UI 状态。

数据和状态 — 始终如此

  • 请求函数 → Hook → 组件。 HTTP 仅通过 shared/api/ 中的客户端进行;不要在 Hook 或组件中导入 HTTP 客户端。
  • 服务器数据仅存在于 TanStack Query 中,通过包含 queryOptions 的查询键工厂管理;在请求函数中使用 Zod 解析响应。
  • 普通资源访问、CRUD 和查询键工厂位于 shared/api(或单独使用它们的页面/特性中);entities/<x>/api 仅用于包含领域规则或该实体映射的请求。
  • 变更会失效(或更新)所有受影响的查询。
  • URL 状态(过滤器、排序、分页、标签)位于经过类型化和 Zod 验证的搜索参数中 — 切勿手动从 window.location 解析。
  • Zustand 仅用于共享的客户端状态;始终使用选择器;持久化存储使用 version、migrate 和 partialize,且不持有敏感数据。
  • 在路由加载器中并行加载路由数据(queryClient.query({ ...options, staleTime: 'static' }),原 ensureQueryData),而非在嵌套组件中依次加载。

可访问性 — 内建,从不事后添加

目标:WCAG 2.2 AA。它是每个组件和页面验收标准的一部分。frontend-accessibility 技能包含完整的规则和审计流程 — 每次 UI 变更时都应加载它。

  • 优先使用语义 HTML:使用 <button> 表示操作、<a>/<Link> 表示导航、每个字段使用 <label>、地标元素、一个 <h1> 以及有序的标题层级。仅在没有原生元素匹配时才使用 ARIA。
  • 键盘:所有内容均可通过键盘到达和操作;无正值的 tabIndex;无键盘陷阱。
  • 可见焦点:每个交互元素上可见(:focus-visible,对比度 ≥ 3:1)。
  • 焦点管理:路由变化时设置页面标题并将焦点移至 <h1> 或 <main>;对话框应锁定焦点,按 Escape 关闭并将焦点返回到触发元素。
  • 名称:图标按钮具有 aria-label;图片具有 alt(装饰性图片设为 alt="")。
  • 对比度:文本 4.5:1,UI 组件 3:1;颜色不应是唯一的信息传达方式。
  • 尊重减少动画;活动区域(role="status"/role="alert")用于异步结果和错误。
  • 测试通过角色和可访问名称进行查询;故事通过可访问性插件;关键页面在 Playwright 中通过 axe 检查。

测试 — 与功能同时编写,而非之后

  • Vitest + Testing Library 为每个功能编写单元测试和组件测试,并在同一更改中完成。通过 UI 测试行为(角色、标签、user-event),而非实现细节。
  • 覆盖率 ≥ 80% 行覆盖率且 ≥ 80% 分支覆盖率,由 CI 中的 Vitest 阈值强制执行。
  • Playwright E2E 覆盖每个关键用户流程(登录、核心业务流、支付/结账、权限):基于角色的定位器,无固定等待,重用认证状态,关键页面上使用 axe 扫描。
  • 每个共享/可复用的 UI 组件都有 Storybook 故事,涵盖所有状态(默认、加载、空、错误、禁用、长内容)。默认使用桌面视口;仅当项目需要响应式布局时才添加移动视口。
  • 通过 Storybook + Playwright 截图进行视觉回归;快照测试仅在有针对性的情况下谨慎使用。

安全 — 始终如此

  • 不使用 dangerouslySetInnerHTML,除非配合 DOMPurify;在 React 外部使用 textContent,绝不使用 innerHTML。模型输出和 Markdown 绝不渲染为原始 HTML。
  • 不在 localStorage/sessionStorage/IndexedDB 中存储令牌或敏感数据。 认证使用后端设置的 HttpOnly 会话 cookie;对于 OIDC,优先使用后端为前端(BFF)模式。
  • 状态更改请求发送 CSRF 标头;credentials: 'include' 仅在请求自己的 API 时使用。
  • VITE_* 变量是公开的 — 绝不在其中放置任何密钥。
  • ?redirect= 目标只能是同源相对路径(防止开放重定向)。
  • 登出会清除服务器会话、TanStack Query 缓存以及所有持久化存储。
  • CSP 作为 HTTP 标头,包含 object-src 'none'、base-uri 'none'、frame-ancestors。
  • postMessage 处理程序检查 event.origin;绝不合并不可信对象(防止原型污染)。
  • 前端绝不执行授权 — 由后端负责 [ASVS 8.3.1]。

TypeScript 和 Biome

  • strict 开启(自 TypeScript 7 起为默认值 — 请保持显式设置);同时包括 noUncheckedIndexedAccess、verbatimModuleSyntax、moduleResolution: "bundler"、lib 使用 ES2023 + DOM。TypeScript 7 默认 types 为 [] — 请显式列出 "vite/client";baseUrl 已移除,请使用 paths("@/*": ["./src/*"])。
  • 无 any(使用 unknown 并进行类型收窄)、无非空断言来抑制错误、无 @ts-ignore(如果无法避免,使用带理由的 @ts-expect-error)。无魔法数字或字符串 — 使用位于 shared/config/ 或对应切片的 config/model 中的命名常量。
  • 外部数据的类型来自 Zod 模式(z.infer/z.output),而非可能漂移的手写接口。
  • Biome:推荐规则外加 noNestedComponentDefinitions、noReExportAll 和 noConsole(不在推荐集中);noBarrelFile 对于切片的 index.ts 文件保持关闭(references/structure.md)。
  • 确保 biome ci、tsc --noEmit、steiger ./src 和 knip 在本地和 CI 中通过。不要内联禁用规则,除非附带注释解释原因。
  • 注释使用英文;TODO 使用项目的 TODO 标记。

仓库卫生 — 始终如此

  • Node 版本锁定:.nvmrc(LTS)、package.json 中的 engines 配合 engine-strict、packageManager 指定确切的 npm/pnpm 版本;锁定文件提交。
  • pre-commit 为提交和推送安装:对暂存更改和所有未推送的提交运行 gitleaks、Biome;推送时运行 tsc、相关的 Vitest 测试和依赖审计。切勿使用 --no-verify 绕过。
  • CI 中每次 MR 和定时任务都进行依赖审计。

详情:references/tooling.md。

Docker 和部署

容器镜像、.dockerignore、Compose 和 Kubernetes 由 docker-kubernetes 技能覆盖;前端工作流和检查清单在 references/docker.md 中。每个镜像都有一个 .dockerignore。以下是与前端相关的注意事项:

  • VITE_* 值在构建时被打入包中。一个镜像用于多个环境需要运行时配置:提供一个 config.json(或 config.js),该文件在容器启动时由环境变量写入,并在应用启动时获取/验证 — 仍然是公开的,仍然没有密钥。
  • Vite SPA 是静态文件:将其从 Web 服务器上提供,并为客户端路由配置对 index.html 的回退、对哈希资源长时间缓存、对 index.html 设置 no-cache,以及来自 references/security.md 的安全标头。
  • React Router 框架模式(SSR)需要运行时Node 服务器(react-router-serve 或自定义服务器)— 它不是静态部署。

编写之后

如需对结果进行安全审查,建议使用 appsec-review 技能。

来源

综合自 Vercel Engineering 的 React 最佳实践(github.com/vercel-labs/agent-skills, react-best-practices,MIT 许可)— 已从 Next.js 适配为 Vite/React Router 加 TanStack Query;规则 ID 保留以供追溯 — 以及 OWASP Secure Agent Playbook(CC BY 4.0;OWASP ASVS 5.0)。结构遵循 Feature-Sliced Design(feature-sliced.design, fsd.how);references/fsd/ 改编自官方 FSD agent 技能(github.com/feature-sliced/skills,MIT 许可)。可访问性目标为 WCAG 2.2。

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

相关技能