Web 应用架构
先阅读 web-craft。只加载任务所需的参考文献;仅加载所选工具包和框架对应的适配器。
映射
| 主题 | 参考文献 |
|---|---|
| 服务器与客户端组件、BFF、环境变量与密钥边界 | references/server-client.md |
| API 层、错误模型、状态所有权、表单、乐观更新、URL 状态 | references/data-forms.md |
| 加载、错误和未找到边界、重试、离线、骨架屏计时 | references/states.md |
| i18n:注册表、解析、URL、目录、格式化、后端请求头 | references/i18n.md |
| RTL、逻辑属性、方向性图标、Portal | references/rtl.md |
| 认证、授权、XSS、CSRF、Cookie、缓存隔离、个人数据 | references/auth-security.md |
| 主题:用户偏好与应用主题、系统变化、无闪烁 | references/theming.md |
| 公开页面的 SEO | references/seo.md |
| GEO:在 AI 搜索和助手中的可见性 | references/geo.md |
| Next.js App Router 适配器 | references/fw-next.md |
| React + Vite 适配器 | references/fw-vite.md |
| shadcn/ui 适配器 | references/kit-shadcn.md |
| Ant Design 适配器 | references/kit-antd.md |
| Material UI 适配器 | references/kit-mui.md |
| 与 node-craft(或任何 OpenAPI)后端配合 | references/node-craft-contract.md |
| 官方来源与审查日期 | references/sources.md |
全局适用的规则
- 按需划分边界。 组件成为客户端组件是因为它需要交互性、浏览器 API 或客户端状态,而不是默认如此。保持交互式孤岛尽可能小。切勿将仅服务器代码、ORM 客户端或密钥导入客户端代码;公共环境变量不是密钥。
- 单一 API 层。 一个 fetch 客户端,一个以稳定代码和状态为键的类型化错误模型,一种认证行为。功能模块不得自行构建 fetch 和重试逻辑。服务端数据存在于查询/缓存层,全局客户端状态存在于小型存储或上下文中,表单状态存在于表单工具中,本地 UI 状态存在于组件中。模拟源通过配置在开发和测试时切换,绝不通过修改功能代码实现;不可信的响应在运行时解析。
- 表单。 使用 react-hook-form + Zod,除非项目采用了其他工具。配置
mode: 'onTouched'、reValidateMode: 'onChange',聚焦并滚动到第一个错误,通过setError处理服务端字段错误,错误后保留值,阻止重复提交。服务端是验证的权威。 - 状态有边界。 路由级别的加载和错误边界,以及在数据流处添加本地 Suspense;一个有问题的部件不会导致整个页面空白。
- i18n 是架构。 使用真实的引擎,区域注册表(BCP 47 标签、方向、目录、显示名称),默认英文回退(除非另有选择),服务端请求作用域的区域,服务端和客户端使用相同的初始区域,按区域和命名空间加载目录,从应用区域映射工具包和日期区域。
- 安全在服务端。 后端负责授权。对任何渲染的 HTML 进行清理。基于 Cookie 的会话需要 CSRF 保护。个人响应绝不能放入共享缓存;区域和用户相关的响应需要变化缓存键。
- 公开页面应可被找到。 在服务端渲染区域正确的元数据,每个语言有唯一的 canonical URL,仅对真实替代页面添加 hreflang 交替链接,站点地图,与可见内容匹配的结构化数据。GEO 以此为起点:可索引、可引用的内容和明确的 AI 爬虫策略。不提供排名或引用保证。
- 工具包是适配的,而非包裹的。 主题和令牌来自产品的设计决策。仅当需要重复的产品行为或固定 API 时,才包裹工具包组件。不要在工具包自身的过渡效果上叠加第二个动画系统。
完成标准
应用 web-craft → 完成,此外:没有客户端代码包包含密钥或仅服务器模块;两个并发的不同区域或不同用户的请求不会混用数据;首次渲染使用正确的语言和主题;每个声称支持的工具包/框架组合都已实际检查过。