关于 inertia-rails-architecture
面向使用 Rails、Inertia.js 和 React 的开发者,提供服务端驱动架构的实施指南。它强调由 Rails 管理路由、数据与认证,React 专注于渲染,并给出选择数据和状态处理模式的规则。
主要功能
- 01服务端与客户端职责划分
- 02页面数据和状态决策规则
- 03表单、导航与数据刷新的模式
- 04延迟属性及无限滚动建议
- 05常见工作流的相关技能指引
适用场景
- 01规划 Rails 与 Inertia.js 页面架构
- 02判断状态应由服务器还是 React 管理
- 03选择表单提交或页面导航方式
- 04决定慢查询及滚动数据的处理方式
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ inertia-rails/ skills --skill inertia-rails-architecture安装后在 Claude Code 中输入/inertia-rails-architecture确认已加载。
附带文件references/AGENTS.mdreferences/decision-trees.md
详细介绍
Inertia Rails 架构
使用 Rails + Inertia.js + React 构建页面、 表单、导航或数据刷新时的服务端驱动架构。Inertia 并不是传统的 SPA—— 路由、数据和身份验证由服务端负责。React 仅负责渲染。
核心思维模型
服务端是真实数据源。React 接收数据作为 props 并渲染 UI。 没有客户端路由器、全局状态存储或 API 层。
构建任何功能之前,请先问:
- 数据从哪里来? → 如果来自服务端:使用控制器 prop。如果来自用户交互:使用
useState。 - 谁拥有这个状态? → 如果它在 URL 或数据库中:由服务端拥有(使用 props)。如果它是临时 UI 状态:由 React 拥有。
- 我是不是要用 React/SPA 模式? → 先查看下面的决策矩阵——Inertia 很可能有对应的服务端驱动方案。
决策矩阵
| 需求 | 解决方案 | 不要使用 |
|---|---|---|
| 来自服务端的页面数据 | 控制器 props | useEffect + fetch |
| 全局数据(身份验证、配置) | inertia_share + usePage() | React Context / Redux |
| 闪现消息 / Toast | Rails flash + usePage().flash | inertia_share / React 状态 |
| 表单提交 | <Form> 组件 | fetch/axios + useState |
| 页面间导航 | <Link> / router.visit | react-router / window.location |
| 刷新特定数据 | router.reload({ only: [...] }) | React Query / SWR |
| 开销较大的服务端数据 | InertiaRails.defer | useEffect + 加载状态 |
| 无限滚动 | InertiaRails.scroll + <InfiniteScroll> | 客户端分页 |
| 稳定的参考数据 | InertiaRails.once | 缓存在 React 状态中 |
| 实时更新(核心场景) | ActionCable + router.reload | 使用 setInterval 轮询 |
| 简单轮询(MVP/原型开发) | usePoll(在后台标签页中自动降低频率) | setInterval + router.reload |
| 由 URL 驱动的 UI 状态(对话框、标签页) | 控制器读取 params → prop,通过 router.get 更新 | useEffect + window.location |
| 临时 UI 状态 | useState / useReducer | 服务端 props |
| 外部 API 调用 | 专用 API 端点 | 与 Inertia props 混用 |
规则(按影响程度排序)
| # | 影响 | 规则 | 原因 |
|---|---|---|---|
| 1 | CRITICAL | 页面数据绝不使用 useEffect+fetch | Inertia 在导航时会重新渲染整个组件;useEffect fetch 会创建第二套数据生命周期,与 props 脱节并导致界面显示过时内容 |
| 2 | CRITICAL | 绝不在客户端检查身份验证 | React 中的身份验证状态可以伪造;只有服务端检查才是真正的访问门槛。客户端“守卫”会带来虚假的安全感 |
| 3 | CRITICAL | 使用 <Form>,而不是 fetch/axios | <Form> 会处理 CSRF、跟随重定向、映射错误、检测文件和历史记录状态;使用 fetch 会重复处理这些工作或破坏相关功能 |
| 4 | HIGH | 使用 <Link> 和 router,而不是 <a> 或 window.location | <a> 会触发整页重新加载,导致所有 React 状态和布局持久化状态丢失 |
| 5 | HIGH | 使用部分重新加载,而不是 React Query/SWR | React Query 会增加第二层缓存,与 Inertia 基于页面的缓存和版本控制冲突 |
| 5b | HIGH | 仅在 MVP 中使用 usePoll;生产环境实时功能优先使用 ActionCable | usePoll 虽然方便,但会浪费带宽——即使没有任何变化,每个间隔仍会请求服务器。ActionCable 只会在实际发生变化时推送 |
| 6 | HIGH | 全局数据使用 inertia_share,而不是 React Context | Context 每次变化都会重新渲染消费者;共享 props 按请求提供,并与部分重新加载集成 |
| 7 | HIGH | 通知使用 Rails flash,而不是共享 props | Flash 会在一次响应后自动清除;共享 props 会一直保留,直到显式修改,因此可能导致提示信息过时 |
| 8 | MEDIUM | 对开销较大的查询使用延迟/可选 props | 否则会阻塞初始渲染——慢查询完成前,用户看到的页面会是空白 |
| 9 | MEDIUM | 使用持久化布局来保留状态 | 没有持久化布局时,每次导航都会重新挂载布局——滚动位置、音频播放和组件状态都会丢失 |
| 10 | MEDIUM | React 组件应负责渲染,而不是获取数据 | 在组件中混合数据获取逻辑会使其难以测试,并破坏 Inertia 的服务端驱动模式 |
技能图谱
常见工作流涉及多项技能——请加载下表所列的全部技能,确保覆盖完整:
| 工作流 | 加载这些技能 |
|---|---|
| 使用 props 创建新页面 | inertia-rails-controllers + inertia-rails-pages + inertia-rails-typescript |
| 带验证的表单 | inertia-rails-forms + inertia-rails-controllers |
| shadcn 表单输入 | inertia-rails-forms + shadcn-inertia |
| Flash 提示 | inertia-rails-controllers + inertia-rails-pages + shadcn-inertia |
| 延迟/惰性数据 | inertia-rails-controllers + inertia-rails-pages |
| URL 驱动的对话框/标签页 | inertia-rails-controllers + inertia-rails-pages |
| Alba 序列化 | alba-inertia + inertia-rails-typescript |
| 测试控制器 | inertia-rails-testing + inertia-rails-controllers |
参考资料
必须——在构建新的 Inertia 页面或功能之前,阅读整个文件:
references/AGENTS.md(约 430 行)——包含上方决策矩阵中各模式的全栈示例。
必须——不确定应使用哪种 Inertia 模式时,阅读整个文件:
references/decision-trees.md(约 70 行)——用于选择 props 类型、导航方法和数据策略的流程图。
请勿加载关于上方决策矩阵已涵盖的单一模式的简单问题所对应的参考资料。
确实需要单独 API 的情况
并非所有内容都适合放在 Inertia 的请求周期中。遇到以下情况时,请使用传统的 API 端点:
| 信号 | 原因 | 示例 |
|---|---|---|
| 非浏览器使用者 | Inertia 的 JSON 封装(组件、属性、URL、版本)是为前端适配器设计的,其他使用者无法使用 | 移动端 API、CLI 工具、支付 Webhook |
| 大型数据集搜索 | 数据集太大,无法作为属性加载;每次输入都需要服务器按键过滤。搜索时使用原始 fetch,让 Inertia 通过属性处理选择后的副作用。 | 城市/地址自动补全、邮政编码查询 |
| 二进制/流式响应 | Inertia 只能传递 JSON 属性。请使用单独的路由,并返回标准下载响应。 | PDF/CSV 导出、文件下载 |
评论
支持 Markdown