React Router RSC 双模式实践:从 unstable_reactRouterRSC 插件到 matchRSCServerRequest 底层实现
React Router 的 React Server Components(RSC)支持目前处于不稳定(unstable)阶段,分为 RSC Framework Mode 与 RSC Data Mode 两种变体。本文围绕这两个模式展开:如何识别项目中已启用的 RSC 变体、RSC 路由模块与普通路由模块的差异(ServerComponent、ServerErrorBoundary 等导出)、客户端/服务端边界划分,以及 Data Mode 下三个入口(RSC Server / SSR Server / Browser)的完整接线方式,并对照开源仓库中的默认入口实现与 matchRSCServerRequest 源码,讲清每个 API 在请求链路中的真实作用。
RSC 支持的两种变体
React Router 的 RSC 支持是实验性的,API 可能在 minor/patch 版本中发生破坏性变更。官方文档在 react-server-components.md 中明确标注了 unstable: true,并提示使用者需密切关注发布说明。RSC 指 React 19 起提供的一类在打包前、独立于客户端与 SSR 服务端的环境中预渲染的组件,其核心概念是 Server Components 与 Server Functions("use client" / "use server" 指令)。
在本仓库中,RSC 支持存在两个层次:
- RSC Framework Mode:Framework Mode 加上不稳定的 RSC Vite 插件(
unstable_reactRouterRSC),并搭配实验性的@vitejs/plugin-rsc。 - RSC Data Mode:更底层的 RSC 运行时 API 与手动打包器/服务器集成,由 RSC Framework Mode 的 API 构建在其之上。
阅读顺序建议(也是仓库技能参考文档 .agents/skills/react-router/references/rsc.md 给出的路径):先读 react-server-components.md,再读对应基础模式的文档 Framework Mode 或 Data Mode。RSC 文档描述的是与非 RSC 模式的差异,而非重复全部 Framework/Data 概念,因此两层知识都要放在脑子里。
识别 RSC Framework Mode
在接触一个已有项目时,先判断它是否使用了 RSC Framework Mode。识别信号:
- 从
@react-router/dev/vite导入unstable_reactRouterRSC; - 依赖中出现
@vitejs/plugin-rsc; vite.config.ts中形如plugins: [reactRouterRSC(), rsc()];- Framework 路由模块中出现 RSC 路由导出(
ServerComponent等); - 存在 RSC 入口文件,如
app/entry.rsc.ts。
从源码结构看,该插件在 vite.ts 中仅有一行导出:
export { reactRouterRSCVitePlugin as unstable_reactRouterRSC } from "./vite/rsc/plugin";
即 unstable_reactRouterRSC 是一个独立的 Vite 插件实现,而非普通 reactRouter() 插件的选项分支。RSC Framework Mode 使用的是不同的 Vite 插件,不能把它替换成普通的 reactRouter() 插件。
标准配置如下(@vitejs/plugin-rsc 必须放在 React Router RSC 插件之后):
import { defineConfig } from "vite";
import { unstable_reactRouterRSC as reactRouterRSC } from "@react-router/dev/vite";
import rsc from "@vitejs/plugin-rsc";
export default defineConfig({
plugins: [reactRouterRSC(), rsc()],
});
RSC Framework Mode 详解
构建产物
RSC Framework Mode 的服务端构建文件(build/server/index.js)导出一个 default 请求处理函数((request: Request) => Promise<Response>),同时处理文档请求与数据请求。如需把它挂到标准 Node.js http.createServer 或 Express 上,可用 @remix-run/node-fetch-server 的 createRequestListener:
import express from "express";
import requestHandler from "./build/server/index.js";
import { createRequestListener } from "@remix-run/node-fetch-server";
const app = express();
app.use(
"/assets",
express.static("build/client/assets", {
immutable: true,
maxAge: "1y",
}),
);
app.use(express.static("build/client"));
app.use(createRequestListener(requestHandler));
app.listen(3000);
Loaders/Actions 返回 React 元素
在 RSC Framework Mode 中,loaders 和 actions 除了普通数据外还可以返回 React 元素,这些元素只在服务端渲染:
import type { Route } from "./+types/route";
export async function loader() {
return {
message: "Message from the server!",
element: <p>Element from the server!</p>,
};
}
export default function Route({
loaderData,
}: Route.ComponentProps) {
return (
<>
<h1>{loaderData.message}</h1>
{loaderData.element}
</>
);
}
如果返回的元素中需要用到客户端特性(Hooks、事件处理器),必须把这部分提取到 "use client" 客户端模块:
"use client";
import { useState } from "react";
export function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
import type { Route } from "./+types/route";
import { Counter } from "./counter";
export async function loader() {
return {
message: "Message from the server!",
element: (
<>
<p>Element from the server!</p>
<Counter />
</>
),
};
}
export default function Route({
loaderData,
}: Route.ComponentProps) {
return (
<>
<h1>{loaderData.message}</h1>
{loaderData.element}
</>
);
}
路由 Server Components
当路由导出 ServerComponent 而不是通常的 default 组件时,该路由在服务端渲染而不是客户端。同一角色下,路由模块不能同时导出 default 和 ServerComponent。客户端专属的注解(如 clientLoader、clientAction)可以与 ServerComponent 并存;其余组件导出遵循同一套客户端/服务端划分:ErrorBoundary、Layout、HydrateFallback 是客户端组件,而 ServerErrorBoundary、ServerLayout、ServerHydrateFallback 在服务端渲染。
互斥的成对导出如下:
| Server Component 导出 | 客户端组件导出 |
|---|---|
ServerComponent |
default |
ServerErrorBoundary |
ErrorBoundary |
ServerLayout |
Layout |
ServerHydrateFallback |
HydrateFallback |
import type { Route } from "./+types/route";
import { Outlet } from "react-router";
import { getMessage } from "./message";
export async function loader() {
return {
message: await getMessage(),
};
}
export function ServerComponent({
loaderData,
}: Route.ServerComponentProps) {
return (
<>
<h1>Server Component Route</h1>
<p>Message from the server: {loaderData.message}</p>
<Outlet />
</>
);
}
服务端优先路由中如需客户端能力,同样把带 Hooks 的部分提取为 "use client" 模块(如上一节的 Counter),再在 ServerComponent 中引入。
.server/.client 模块不再内置
为避免与 RSC 的 "use server"、"use client" 指令混淆,使用 RSC Framework Mode 时,.server 模块与 .client 模块的文件命名约定不再内置支持。推荐改用 @vitejs/plugin-rsc 提供的 "server-only" 与 "client-only" 边界导入,在模块内以副作用方式导入以保证构建期校验(无需安装官方 npm 包 server-only/client-only,@vitejs/plugin-rsc 会在内部处理这些导入,用构建期校验替代运行时报错):
import "server-only";
// Rest of the module...
如果存量代码依赖 .server/.client 命名约定,推荐直接使用 vite-env-only 插件做快速迁移,例如确保 .server 模块不会误入客户端构建:
import { defineConfig } from "vite";
import { denyImports } from "vite-env-only";
import { unstable_reactRouterRSC as reactRouterRSC } from "@react-router/dev/vite";
import rsc from "@vitejs/plugin-rsc";
export default defineConfig({
plugins: [
denyImports({
client: { files: ["**/.server/*", "**/*.server.*"] },
}),
reactRouterRSC(),
rsc(),
],
});
MDX 路由支持
使用 @mdx-js/rollup v3.1.1+ 时,RSC Framework Mode 支持 MDX 路由。注意 MDX 路由中导出的任何组件都必须是 RSC 环境合法的(不能使用 Hooks 等客户端特性),需要这些特性的组件应提取到 "use client" 模块。
自定义入口文件
RSC Framework Mode 支持自定义入口,可分别定制 RSC 服务器、SSR 服务器与客户端入口。插件会自动在 app 目录探测以下文件,找不到则使用框架默认入口:
app/entry.rsc.ts(或.tsx)—— 自定义 RSC 服务器入口;app/entry.ssr.ts(或.tsx)—— 自定义 SSR 服务器入口;app/entry.client.tsx—— 自定义客户端入口。
想查看框架生成的默认入口,可以用 react-router reveal entry.client、react-router reveal entry.rsc、react-router reveal entry.ssr。默认入口的源码就在本仓库的 default-rsc-entries 目录 中,构建后可在 node_modules/@react-router/dev/dist/config/default-rsc-entries/ 直接查看:
基本覆盖模式:自定义入口可以包装或扩展现有默认行为。例如为 RSC 入口增加日志:
import defaultEntry from "@react-router/dev/config/default-rsc-entries/entry.rsc";
import { RouterContextProvider } from "react-router";
export default {
fetch(request: Request): Promise<Response> {
console.log(
"Custom RSC entry handling request:",
request.url,
);
const requestContext = new RouterContextProvider();
return defaultEntry.fetch(request, requestContext);
},
};
if (import.meta.hot) {
import.meta.hot.accept();
}
SSR 入口同理:
import { generateHTML as defaultGenerateHTML } from "@react-router/dev/config/default-rsc-entries/entry.ssr";
export function generateHTML(
request: Request,
serverResponse: Response,
): Promise<Response> {
console.log(
"Custom SSR entry generating HTML for:",
request.url,
);
return defaultGenerateHTML(request, serverResponse);
}
客户端入口则可以直接引用默认实现:
import "@react-router/dev/config/default-rsc-entries/entry.client";
复制默认入口做深度定制:在 IDE 中对默认入口的导入使用"跳转到定义",把默认入口代码复制到自己的文件里再修改即可。复制时必须保留必需的导出约定:
entry.rsc.ts必须导出带fetch方法的默认对象;entry.ssr.ts必须导出generateHTML函数;entry.client.tsx负责处理客户端 hydration。
对照仓库中的默认实现可以看到这条链路:entry.rsc.tsx 的默认导出是 async fetch(request, requestContext?),内部通过 import.meta.viteRsc.loadModule 动态加载 SSR 模块并调用 ssr.generateHTML(request, await fetchServer(request, requestContext));fetchServer 则调用 matchRSCServerRequest 并传入 virtual:react-router/unstable_rsc/routes 等由插件生成的虚拟模块(路由、route discovery、basename、clientVersion)。而 entry.ssr.tsx 的 generateHTML 调用 routeRSCServerRequest,在其 renderHTML 回调中用 renderToReadableStream 把 <RSCStaticRouter getPayload={getPayload} /> 渲染为 HTML 流。这印证了文档中"一个请求先经 RSC 服务器生成 payload、再由 SSR 入口转成 HTML"的两段式结构。
不支持的配置项
以下 react-router.config.ts 选项目前不支持 RSC Framework Mode:
buildEndpresetsserverBundlessplitRouteModules
RSC Data Mode
RSC Framework Mode 的 API 构建在更底层的 Data Mode API 之上。Data Mode 缺少 routes.ts 配置与文件系统路由、HMR 与 Hot Data Revalidation 等特性,但更灵活,允许接入自己的打包器与服务器抽象。Data Mode 比 Framework Mode 更手动:在改动路由或入口之前,先摸清应用现有的打包器与服务器抽象。识别信号包括:unstable_RSCRouteConfig、传给底层 RSC API 的路由配置、unstable_matchRSCServerRequest / unstable_routeRSCServerRequest / unstable_RSCHydratedRouter / unstable_RSCStaticRouter 等 API、围绕 RSC 的自定义打包器/服务器设置。
配置路由
路由以参数形式传给 matchRSCServerRequest。最小需求是 path 与 component:
function Root() {
return <h1>Hello world</h1>;
}
matchRSCServerRequest({
// ...other options
routes: [{ path: "/", Component: Root }],
});
虽然可以内联定义组件,但出于启动性能与代码组织考虑,官方推荐使用 lazy() 选项并遵循 Route Module 约定。RSC 路由配置中的 lazy 字段期望与 Route Module API 相同的导出,从而保持路由模块形状在 Framework Mode 与 RSC Data Mode 之间一致——包括 loader、action、meta、links、headers、ErrorBoundary、HydrateFallback 以及各类客户端注解。
类型定义 RSCRouteConfig 在 server.rsc.ts 中:每条 RSCRouteConfigEntry 含 id(必填)、可选 path,lazy 返回的模块中 default 与 Component 二选一(类型上用 never 互斥),且 index: true 与 children 互斥:
import type { unstable_RSCRouteConfig as RSCRouteConfig } from "react-router";
export function routes() {
return [
{
id: "root",
path: "",
lazy: () => import("./root/route"),
children: [
{
id: "home",
index: true,
lazy: () => import("./home/route"),
},
{
id: "about",
path: "about",
lazy: () => import("./about/route"),
},
],
},
] satisfies RSCRouteConfig;
}
Server Component 路由
Data Mode 下,每条路由的 default 导出默认渲染为 Server Component:
export default function Home() {
return (
<main>
<article>
<h1>Welcome to React Router RSC</h1>
<p>
You won't find me running any JavaScript in the
browser!
</p>
</article>
</main>
);
}
Server Components 的一个特性是可以把组件写成异步函数从而直接在服务端取数:
export default async function Home() {
let user = await getUserData();
return (
<main>
<article>
<h1>Welcome to React Router RSC</h1>
<p>
You won't find me running any JavaScript in the
browser!
</p>
<p>
Hello, {user ? user.name : "anonymous person"}!
</p>
</article>
</main>
);
}
官方文档同时提示:Server Components 也可以从 loaders/actions 中返回;在全面使用 RSC 构建应用时,loader 主要用于设置 status 码或返回 redirect,而在 loader 中使用 Server Components 对渐进式引入 RSC 很友好。
Server Functions
Server Functions 是 React 提供的服务端异步函数特性,以 "use server" 指令定义:
"use server";
export async function updateFavorite(formData: FormData) {
let movieId = formData.get("id");
let intent = formData.get("intent");
if (intent === "add") {
await addFavorite(Number(movieId));
} else {
await removeFavorite(Number(movieId));
}
}
import { updateFavorite } from "./action.ts";
export async function AddToFavoritesForm({
movieId,
}: {
movieId: number;
}) {
let isFav = await isFavorite(movieId);
return (
<form action={updateFavorite}>
<input type="hidden" name="id" value={movieId} />
<input
type="hidden"
name="intent"
value={isFav ? "remove" : "add"}
/>
<AddToFavoritesButton isFav={isFav} />
</form>
);
}
Server Functions 被调用后,React Router 会自动重新验证(revalidate)路由并用新的服务端内容更新 UI,无需手动处理缓存失效。这一行为在源码中对应 processServerAction:当请求带 rsc-action-id 头时走增强型 server action 路径(decodeReply + loadServerAction);当是带 $ACTION_ 前缀字段的表单请求时走 decodeAction 路径,两者最终都产出一个 revalidation request。
Client Properties
路由在运行时于服务端定义,但借助 client references 与 "use client" 仍可提供 clientLoader、clientAction 和 shouldRevalidate:
"use client";
export function clientAction() {}
export function clientLoader() {}
export function shouldRevalidate() {}
export default function ClientRoot() {
return <p>Client route</p>;
}
然后在懒加载的路由模块中重新导出:
export {
clientAction,
clientLoader,
shouldRevalidate,
} from "./client";
export default function Root() {
// ...
}
这也把整条路由变成 Client Component 的方式(此时路由的 default 导出需要保留一个 Server Component 来承载客户端组件,这也是使用 CSS 副作用导入时打包器的硬性要求):
import { default as ClientRoot } from "./route.client";
export {
clientAction,
clientLoader,
shouldRevalidate,
} from "./client";
export default function Root() {
// Adding a Server Component at the root is required by bundlers
// if you're using css side-effects imports.
return <ClientRoot />;
}
打包器接线:三个入口
React Router 提供的 API 让你容易把 Data Mode 接入 RSC 兼容的打包器(例如构建自己的 custom framework)。以"SSR + SPA 导航 hydration"的典型接线为例,需要配置三样东西:
- 处理入站请求、获取 RSC payload 并转成 HTML 的服务器;
- 生成 RSC payload 的 React 服务器;
- 客户端浏览器处理器:hydrate 生成的 HTML,并设置
callServer以支持 hydration 之后的 server actions。
命名约定仅为熟悉起见,可以自行命名与配置。"React Server"与请求处理服务器不必是两个独立进程——可以是同一服务器内的两个独立模块图,这很重要,因为 React 在生成 RSC payload 与生成客户端 HTML 时行为不同。
| 入口 | 职责 | 相关 API |
|---|---|---|
entry.ssr.tsx(Server) |
处理请求、调用 RSC 服务器、把 payload 转为 HTML | routeRSCServerRequest、RSCStaticRouter |
entry.rsc.tsx(RSC Server) |
把请求匹配到路由并生成 RSC payload | matchRSCServerRequest |
entry.browser.tsx(Browser) |
hydrate HTML,设置 callServer |
createCallServer、getRSCStream、RSCHydratedRouter |
提示:SSR 并非必须。可以用 RSC 预渲染 HTML 用于 SSG 或 ISR。
以下示例使用 Express 与 @remix-run/node-fetch-server。Vite 侧除了 react、react-dom、react-router,还需要:
npm i -D vite @vitejs/plugin-react @vitejs/plugin-rsc
vite.config.ts
import rsc from "@vitejs/plugin-rsc/plugin";
import react from "@vitejs/plugin-react";
import { defineConfig } from "vite";
export default defineConfig({
plugins: [
react(),
rsc({
entries: {
client: "src/entry.browser.tsx",
rsc: "src/entry.rsc.tsx",
ssr: "src/entry.ssr.tsx",
},
}),
],
});
src/entry.ssr.tsx
import { createFromReadableStream } from "@vitejs/plugin-rsc/ssr";
import { renderToReadableStream as renderHTMLToReadableStream } from "react-dom/server.edge";
import {
unstable_routeRSCServerRequest as routeRSCServerRequest,
unstable_RSCStaticRouter as RSCStaticRouter,
} from "react-router";
export async function generateHTML(
request: Request,
serverResponse: Response,
): Promise<Response> {
return await routeRSCServerRequest({
// The incoming request.
request,
// The React Server response
serverResponse,
// Provide the React Server touchpoints.
createFromReadableStream,
// Render the router to HTML.
async renderHTML(getPayload, options) {
const payload = await getPayload();
const formState =
payload.type === "render"
? await payload.formState
: undefined;
const bootstrapScriptContent =
await import.meta.viteRsc.loadBootstrapScriptContent(
"index",
);
return await renderHTMLToReadableStream(
<RSCStaticRouter getPayload={getPayload} />,
{
...options,
bootstrapScriptContent,
formState,
signal: request.signal,
},
);
},
});
}
src/entry.rsc.tsx
import {
createTemporaryReferenceSet,
decodeAction,
decodeFormState,
decodeReply,
loadServerAction,
renderToReadableStream,
} from "@vitejs/plugin-rsc/rsc";
import { unstable_matchRSCServerRequest as matchRSCServerRequest } from "react-router";
import { routes } from "./routes/config";
function fetchServer(request: Request) {
return matchRSCServerRequest({
// Provide the React Server touchpoints.
createTemporaryReferenceSet,
decodeAction,
decodeFormState,
decodeReply,
loadServerAction,
// The incoming request.
request,
// The app routes.
routes: routes(),
// Encode the match with the React Server implementation.
generateResponse(match, options) {
return new Response(
renderToReadableStream(match.payload, options),
{
status: match.statusCode,
headers: match.headers,
},
);
},
});
}
export default async function handler(request: Request) {
// Import the generateHTML function from the client environment
const ssr = await import.meta.viteRsc.loadModule<
typeof import("./entry.ssr")
>("ssr", "index");
return ssr.generateHTML(
request,
await fetchServer(request),
);
}
src/entry.browser.tsx
import {
createFromReadableStream,
createTemporaryReferenceSet,
encodeReply,
setServerCallback,
} from "@vitejs/plugin-rsc/browser";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
import {
unstable_createCallServer as createCallServer,
unstable_getRSCStream as getRSCStream,
unstable_RSCHydratedRouter as RSCHydratedRouter,
type unstable_RSCPayload as RSCPayload,
} from "react-router/dom";
// Create and set the callServer function to support post-hydration server actions.
setServerCallback(
createCallServer({
createFromReadableStream,
createTemporaryReferenceSet,
encodeReply,
}),
);
// Get and decode the initial server payload.
createFromReadableStream<RSCPayload>(getRSCStream()).then(
(payload) => {
startTransition(async () => {
const formState =
payload.type === "render"
? await payload.formState
: undefined;
hydrateRoot(
document,
<StrictMode>
<RSCHydratedRouter
createFromReadableStream={
createFromReadableStream
}
payload={payload}
/>
</StrictMode>,
{
formState,
},
);
});
},
);
从服务端源码看这条链路的数据形态:RSCPayload 是四种载荷的联合类型——render(含 matches、loaderData、errors、actionData、formState)、manifest(懒路由发现的补丁)、action、redirect。matchRSCServerRequest 实现(server.rsc.ts)会先归一化 .rsc / _.rsc 后缀的数据请求 URL,判断 manifest 请求与数据请求,再经由 createStaticHandler 走标准的 loader/action 查询流程,最终把结果封装为 generateResponse 可渲染的 RSCMatch(statusCode + headers + payload)。仓库中 playground/rsc-vite-framework 是一个可直接运行的 Data Mode 示例,integration/rsc/rsc-test.ts 等集成测试则覆盖了 nojs、prerender 等场景。
CSP Nonce 配置
CSP 可以用每次响应独立的 nonce 来允许 RSC hydration 所需的内联脚本,同时禁止任意内联脚本。nonce 是 HTML 层面的问题,应配置在 entry.ssr.tsx 中,不需要传给 matchRSCServerRequest,也不应出现在 RSC payload 里。
RSC Framework Mode 下先运行 react-router reveal entry.ssr 生成自定义 SSR 入口;Data Mode 下直接更新现有 SSR 入口。每个文档响应生成新 nonce,并传给 routeRSCServerRequest、RSCStaticRouter 与 CSP 响应头:
export async function generateHTML(
request: Request,
serverResponse: Response,
): Promise<Response> {
const nonce = crypto.randomUUID();
const response = await routeRSCServerRequest({
request,
serverResponse,
createFromReadableStream,
nonce,
async renderHTML(getPayload, options) {
const payload = getPayload();
const bootstrapScriptContent =
await import.meta.viteRsc.loadBootstrapScriptContent(
"index",
);
return renderHTMLToReadableStream(
<RSCStaticRouter
getPayload={getPayload}
nonce={options.nonce}
/>,
{
...options,
bootstrapScriptContent,
formState: await payload.formState,
signal: request.signal,
},
);
},
});
response.headers.set(
"Content-Security-Policy",
`script-src 'self' 'nonce-${nonce}'`,
);
return response;
}
三个传递路径的作用:routeRSCServerRequest 的 nonce 选项把它应用到把 RSC payload 转移进 HTML 文档的内联脚本;把 renderHTML 的 options 展开进 renderHTMLToReadableStream 使其应用到 React 生成的脚本;传给 RSCStaticRouter 则让 <Links>、<ScrollRestoration> 这类感知 nonce 的组件默认使用它。默认 RSC Framework 入口不生成 nonce,只有当应用同时发送匹配 CSP 头时才应生成;对静态预渲染页面,优先使用 CSP hash 或外部脚本而非每响应 nonce。
客户端/服务端边界与数据加载
RSC 代码必须遵守 React 的客户端/服务端划分:
- 需要 Hooks、浏览器 API 或事件处理器的组件使用
"use client"; - 服务端数据访问与密钥使用 server-only 模块;
- RSC Framework Mode 下优先使用文档描述的
server-only与client-only边界导入; - 不要假设
.server/.client文件命名约定在 RSC Framework Mode 下行为一致,依赖这些约定前先读 RSC 文档。
RSC 改变了数据可以加载的位置:Server Components 可以直接在服务端取数;loaders/actions 仍然存在且可带 RSC 特有行为(如返回 React 元素、配合 useActionState 的 formState);客户端组件仍然只能拿到客户端安全的数据,不能直接访问 server-only 模块。在"Server Component 直接取数、loader、客户端 loader/action"之间做选择时,跟随 RSC 文档并与应用既有模式保持一致。
稳定性检查清单
RSC API 被明确标记为 unstable。在实现或重构 RSC 代码之前:
- 确认已安装的 React Router 版本(本仓库
unstable_前缀的 API 可能在 minor/patch 版本发生破坏性变更); - 确认已安装的
@vitejs/plugin-rsc版本(实验性插件,需与 RSC 入口 API 匹配); - 阅读应用现有的 RSC 入口/配置文件(
app/entry.rsc.ts、app/entry.ssr.ts、vite.config.ts); - 优先做符合当前模式的最小改动;
- RSC 路由模块中同一角色的成对导出(
default/ServerComponent、ErrorBoundary/ServerErrorBoundary、Layout/ServerLayout、HydrateFallback/ServerHydrateFallback)互斥,添加这些导出前先读 RSC 文档。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0623
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00