Remix — 拥抱 Web 标准的 React 全栈框架
是什么
Remix 是 Ryan Florence 和 Michael Jackson(React Router 的作者)做的 React 全栈框架。它的理念一句话:“不打架 Web 平台,强化它”。
日常类比:next-js 是给 React 加了一座宫殿,里面什么都自己造一套;Remix 是把现有的胡同改造成顺畅的步行街——少加少减,让浏览器原生能力(fetch、form、URL)更好用。
你写一个 Remix 路由长这样:
export async function loader() { return json(await db.posts.findMany())}
export default function Posts() { const posts = useLoaderData<typeof loader>() return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>}数据从服务端 loader 来,组件直接 useLoaderData() 拿——不用 useEffect、不用 fetch、不用 loading state。
为什么重要
理解 Remix 的设计哲学,能解释这些事:
- 为什么 React 全栈这么难做:客户端状态管理、数据获取、错误处理、表单提交——每个问题都有一堆库。Remix 用 Web 标准(fetch + form)把它们一次解决
- 为什么 React Router v7 突然变得像 Next.js:2024 年 Shopify 收购 Remix 后,团队把 Remix 的能力全量并入 React Router——v7 = 新版 React Router + Remix
- 为什么”渐进增强”重要:Remix 默认 JS 不加载也能用(form 走原生提交),符合 Web 平台几十年的可访问性传统
- 为什么 Nested Routes 是个大事:路由嵌套对应 UI 嵌套,这是 React Router 的发明,被 next-js App Router 抄过去
核心要点
Remix 的心智模型可以拆成 三件套:
-
loader(服务端获取数据):每个路由可以导出一个
loader函数,在服务端跑,返回的数据通过useLoaderData()给组件用。类比:每个页面有自己的”数据厨房”,组件只是端盘子的服务员 -
action(处理表单提交):每个路由可以导出一个
action函数,处理 POST/PUT/DELETE 请求。配合<Form>组件,不用 onSubmit、不用 fetch——浏览器原生表单提交直接走到 action -
component(渲染):默认导出的 React 组件。它只关心怎么渲染,不关心数据从哪来、提交到哪去——这两件事 loader / action 已经做了
加上 嵌套路由:URL /products/123 对应 routes/products.tsx(layout)+ routes/products.$id.tsx(详情页)。layout 包详情页,两个 loader 并行跑,不像传统 SPA 串行等待。
实践案例
案例 1:loader + 组件三件套
// app/routes/posts.$slug.tsximport { json, type LoaderFunctionArgs } from "@remix-run/node"import { useLoaderData } from "@remix-run/react"
export async function loader({ params }: LoaderFunctionArgs) { const post = await db.post.findUnique({ where: { slug: params.slug } }) if (!post) throw new Response("Not Found", { status: 404 }) return json({ post })}
export default function Post() { const { post } = useLoaderData<typeof loader>() return <article><h1>{post.title}</h1><p>{post.body}</p></article>}注意:throw new Response 直接走错误边界,不用 try/catch。
案例 2:Form + action 不写一行 fetch
import { Form, redirect, type ActionFunctionArgs } from "@remix-run/react"
export async function action({ request }: ActionFunctionArgs) { const formData = await request.formData() await sendEmail({ name: formData.get("name") as string, message: formData.get("message") as string, }) return redirect("/thanks")}
export default function Contact() { return ( <Form method="post"> <input name="name" required /> <textarea name="message" required /> <button type="submit">发送</button> </Form> )}JS 不加载也能用:浏览器原生 form 提交→ 服务端 action 处理 → redirect 到 thanks。JS 加载后,Remix 把它升级成 fetch 提交,无刷新。
案例 3:Nested Routes
app/routes/├── products.tsx (layout: 顶部分类筛选)├── products._index.tsx (列表页)└── products.$id.tsx (详情页)访问 /products/42:
products.tsx的 layout 渲染(包含<Outlet />)products.$id.tsx的详情在 Outlet 里渲染- 两个 loader 并行:layout 的分类数据 + 详情数据同时拿,不串行
踩过的坑
-
学习曲线对 React-only 的人陡:习惯了
useState + useEffect + fetch的人会困惑——“为什么不用 onSubmit?“答案是:Web 表单标准比 React 早 30 年,Remix 让你用回它。但要扭转心智 -
client-only 状态反而麻烦:复杂的客户端全局 store(Zustand / Redux)没有官方位置——Remix 假设你 90% 状态是”服务端的数据”。剩下 10% 你得自己接
-
Remix v2 与 v1 路由约定有调整:v1 用文件夹(
routes/posts/$slug.tsx),v2 用扁平命名(routes/posts.$slug.tsx)。老教程经常错位 -
2024 年 Remix → React Router v7 合并:术语切换让老文档失准——现在新项目应该用
react-router@7(带 framework mode),而不是@remix-run/*。Remix v2 仍维护,但 v3 不会有了 -
部署需要 Node 服务端:Remix 默认 SSR,不像 next-js 那样可以纯静态导出。要放 CDN 得用 Cloudflare Workers / Deno Deploy 等边缘运行时
适用 vs 不适用场景
适用:
- 内容驱动的网站(博客、文档、电商)—— loader 拿数据 + form 提交,全套丝滑
- 强调可访问性、SEO、首屏速度的项目 —— 服务端渲染 + 渐进增强
- 团队熟悉 Web 平台标准(fetch、Response、FormData)—— Remix 的 API 几乎就是 Web API
- 想从 Next.js Pages Router 迁移但又不想接受 App Router 的 RSC 复杂度
不适用:
- 纯客户端 SPA(管理后台、画板工具)—— Remix 的卖点用不上,反而被 SSR 拖累
- 需要完全静态导出(GitHub Pages 这种)—— 默认要 Node 运行时
- 团队已经深度绑定 next-js 生态(next-image / next-auth / vercel) —— 切换成本不值
- 2025+ 新项目:直接用 React Router v7 framework mode,别再用
@remix-run/*包
学到什么
- Web 标准不是包袱,是资产:fetch / Form / URL / Response 这些 30 年沉淀的东西,比任何框架抽象都稳定。Remix 让你用回它们
- 数据流从”哪里取”开始定,不从”怎么存”开始:loader 决定数据源 → 组件直接用,跳过了”全局 store + selector + action”的传统三件套
- Nested Routes 不是路由的事,是 UI 的事:URL 嵌套 = layout 嵌套 = loader 并行——三件事用一个机制解决
- 框架可以”少而对”:Remix 核心 API 只有几十个,但每个都是 Web 标准的薄包装。比起 next-js 的”全功能”,是另一种产品哲学
延伸阅读
- 官方文档:remix.run/docs(信息架构很清晰,从 Quickstart 到 Discussion 分层)
- React Router v7 文档:reactrouter.com(Remix 的延续,新项目用这个)
- 视频:Ryan Florence — When To Fetch(讲清楚 loader 为什么比 useEffect 好)
- 文章:Kent C. Dodds — Why I Love Remix(社区视角的设计哲学解读)
关联
- next-js —— Remix 的最大对手;两者哲学相反,Remix 拥抱 Web 标准,Next 自建一套
- react-router —— Remix 的”娘家”;2024 年合并后 React Router v7 = Remix
- astro —— 同样追求”Web 标准 + SSR”,但做内容站,不做交互应用
- shadcn-ui —— 常和 Remix 配合用的 UI 方案
反向链接
- ape-framework —— Ape Framework — Python 智能合约开发一条龙
- astro —— Astro — 内容站点优先的 Web 框架
- conform —— Conform — 让浏览器原生 form 也能 type-safe 校验
- next-js —— Next.js — React 全栈框架
- shadcn-ui —— shadcn/ui — 把 React 组件从 npm 包变成”源码 + CLI 协议”
- sveltekit —— SvelteKit — Svelte 全栈框架
- tanstack-router —— TanStack Router — 把 URL 当类型,编译器替你守路由