FEATURED · 精选文章

tRPC Next.js App Directory 实验适配器:RSC、Server Actions 与缓存的一体化实战指南

发布时间 / 2026/9/6 20:55:31
来源 / 创域科博编辑部
栏目 / 资讯中心
tRPC Next.js App Directory 实验适配器:RSC、Server Actions 与缓存的一体化实战指南 tRPC Next.js App Directory 实验适配器RSC、Server Actions 与缓存的一体化实战指南【免费下载链接】trpc‍♀️ Move Fast and Break Nothing. End-to-end typesafe APIs made easy.项目地址: https://gitcode.com/GitHub_Trending/tr/trpc本篇围绕 tRPC 仓库中的实验性示例 examples/.experimental/next-app-dir讲解如何在 Next.js App Directory 中以同一套 API 调用方式同时支持 Server ComponentsRSC、Server Actions 与客户端组件并理解其基于react-server模块条件拆分入口、nextCacheLink缓存与revalidate失效机制的实现细节。读完本文你可以复现该实验架构的完整搭建步骤并判断它在生产环境中的适用边界。一、这是什么一个官方适配器的 Playground该示例的定位在 README 中开宗明义这是一个用于验证tRPC Next.js App directory 官方适配器的 playground 仓库并明确标注 This is experimental and is subject to change实验性质、接口随时可能变化。README 中同时给出了一条重要背景说明在正式适配器落地之前App Directory 下已有两条可用的既有路径直接在组件中使用trpc/clientRSC 与非 RSC 组件均可在客户端组件中使用trpc/next。而本实验要验证的是第三条路一个针对 App Directory 专门设计的客户端/服务端调用层让开发者no matter if you are in a server component无论身处服务端组件还是客户端组件都能以相同方式使用 tRPC。README 中的进度清单如实反映了当前成熟度事项状态RSC 支持的概念验证PoC已完成Server Actions 的概念验证PoC已完成缓存caching实现已完成服务端调用触发的缓存失效未完成客户端调用触发的缓存失效未完成服务端与客户端调用的双向失效联动未完成API 最终定型、重测试未完成对应地README 也给出了明确的生产环境警告Dont use this in production unless you are okay with large refactoring.——除非你能接受大规模重构成本否则不要在生产中使用。这个警告在评估任何实验性方案时都应当放在第一位。二、总体架构一个本地 tRPC 包两种运行时入口实验的核心思路README 的 Overview 章节可以概括为两句话创建一个tRPC API handler路由处理器创建一个本地 tRPC 包为use client与use server场景提供不同的 entrypoint。第二个步骤是整个架构的枢纽Next.js 打包时会根据模块是否带use client标识选择不同的模块条件module condition。该示例通过一个通过 pnpm 链接进应用包的本地包trpc-api实现了这种分流。2.1 用 exports 条件区分 RSC 与客户端入口包声明见 src/trpc/package.json{ name: trpc-api, typings: client.ts, exports: { .: { types: ./client.ts, react-server: ./server-invoker.ts, default: ./client.ts } } }关键点react-server条件命中时即无use client的服务端组件 / Server Components 环境解析到 server-invoker.ts其余情况客户端组件走default分支解析到 client.ts。应用侧则在 package.json 中通过trpc-api: link:./src/trpc将该本地包以 workspace link 方式引入与next^15.3.8、react^19.1.0、tanstack/react-query^5.80.3等依赖共同工作。这样同一个import { api } from trpc-api语句在 RSC 与客户端组件中会拿到两个不同的客户端实现但暴露相同的调用形态——这正是 README 所承诺的same way。2.2 API Handler标准 fetch 适配器README 的第一步Create an API handler for tRPC对应 src/app/api/trpc/[trpc]/route.tsimport { fetchRequestHandler } from trpc/server/adapters/fetch; import { createContext } from ~/server/context; import { appRouter } from ~/server/routers/_app; const handler (req: Request) fetchRequestHandler({ endpoint: /api/trpc, req, router: appRouter, createContext, }); export { handler as GET, handler as POST };这是标准的 App Directory Route Handler 写法将fetchRequestHandler同时挂到GET/POST上。源码注释中还留了一行// Add back once NextAuth v5 is released的runtime edge占位说明边缘运行时支持当时受 NextAuth v5 状态限制这也是一处值得注意的适用前提。2.3 RSC 入口nextCacheLink 直接调用不走 HTTPserver-invoker.ts 是react-server条件下被解析的客户端export const api experimental_createTRPCNextAppDirServertypeof appRouter({ config() { return { links: [ loggerLink({ enabled: (op) true }), experimental_nextCacheLink({ // requests are cached for 5 seconds revalidate: 5, router: appRouter, transformer, createContext: async () ({ session: await auth(), headers: { cookie: (await cookies()).toString(), x-trpc-source: rsc-invoke, }, }), }), ], }; }, });从源码结构看该 link 有两个核心特征进程内直调文件头注释写明 This client invokes procedures directly on the server without fetching over HTTP即传入router后在 Node 进程中直接执行 procedure省去 HTTP 往返Next.js 数据缓存接入revalidate: 5将结果按 Next.js 的revalidate语义缓存 5 秒并复用请求级 contextsession、cookie 头同时通过x-trpc-source: rsc-invoke标记请求来源便于服务端区分 RSC 直调与浏览器请求。2.4 客户端入口HTTP link Server Action 双通道client.ts 面向带use client的组件暴露了两个对象export const api experimental_createTRPCNextAppDirClientAppRouter({ config() { return { links: [ loggerLink({ enabled: (op) true }), experimental_nextHttpLink({ transformer, batch: true, url: getUrl(), headers() { return { x-trpc-source: client }; }, }), ], }; }, }); export const useAction experimental_createActionHookAppRouter({ links: [loggerLink(), experimental_serverActionLink({ transformer })], });api通过experimental_nextHttpLinkbatch: true走/api/trpc端点即 2.2 节的路由处理器useAction是一个 React Hook底层由experimental_serverActionLink承载把 mutation 调用转换为 React Server Action 的表单提交语义。两个入口共享同一份 shared.tsgetUrl()按环境返回端点地址浏览器下为相对路径/api/trpc服务端下回落到http://localhost:3000/api/trpctransformer则是在superjson基础上注册了Temporal.PlainDate/Temporal.PlainDateTime自定义序列化器依赖js-temporal/polyfill保证 Temporal 类型在跨边界传输后保真。README 中引用的对照示例即 ClientGreeting.tsx客户端侧与 ServerInvokedGreeting.tsxRSC 侧。后者展示了 RSC 直调与失效按钮的完整形态export async function ServerInvokedGreeting() { const greeting1 await api.greeting.query({ text: i never hit an api endpoint }); const secret await api.secret.query(); // ... form action{async () { use server; await api.greeting.revalidate({ text: i never hit an api endpoint }); }} button typesubmitRevalidate Cache 1/button /form }注意api.secret.query()的用法直调发生在服务端进程内可以访问仅服务端可达的数据如会话密钥这在经由 HTTP 的客户端调用中无法直接做到——从源码结构看这是选择 RSC 直调而非一律走 API 端点的主要动机之一。三、缓存与失效revalidate procedure 专用端点缓存是 README 进度表中唯一已完成的能力项Implement caching。其落地由三部分组成nextCacheLink的revalidate参数见 2.3 节决定 RSC 查询结果在 Next.js data cache 中的存活时间router 中声明revalidateprocedure如上例api.greeting.revalidate(input)按 procedure 输入精确失效对应缓存项调用入口是一个内联 Server Actionuse serverHTTP 失效端点src/app/api/trpc/revalidate/route.ts 只有一行——export { experimental_revalidateEndpoint as POST } from trpc/next/app-dir/server;它把trpc/next/app-dir/server导出的experimental_revalidateEndpoint直接挂载为POST处理器供客户端或浏览器在不走完整 RPC 流程的情况下触发缓存失效。需要强调边界README 进度表中 Implement cache invalidation on server calls / on client calls 均为未勾选状态意味着失效链路当前依赖显式的revalidate调用尚不具备一次 mutation 自动联动失效查询缓存的能力。若你的业务强依赖自动失效应把这一条列入风险清单。四、Server ActionscreateAction 把 procedure 变成 actionserver-action 示例目录 给出了procedure → Server Action的标准包装方式use server; import { createAction, publicProcedure } from ~/server/trpc; import { z } from zod; export const testAction createAction( publicProcedure .input(z.object({ text: z.string().min(1) })) .mutation(async (opts) { console.log(testMutation called, opts); return { text: Hello world, date: new Date() }; }), );createAction复用 tRPC 的 procedure builder输入校验、middleware 均可保留仅在语义上把 mutation 标记为 Server Action 友好客户端侧则通过 2.4 节的useActionHook 消费目录中的ReactHookFormExample.action.tsx等文件进一步演示了与 React Hook Form 的表单集成配合hookform/resolvers与 zod。五、配套TanStack Query 的 RSC 预取与水合playground 中还内置了 RSC 预取链路可直接作为App Directory TanStack Query tRPC的组合参考服务端 rq-server.tsxcreateTRPCOptionsProxy生成trpc选项代理内部经server-only包锁定在服务端并导出HydrateClient基于dehydrateHydrationBoundary与prefetch自动区分prefetchQuery/prefetchInfiniteQuery。context 与 queryClient 均用cache()包裹保证同一请求内稳定复用客户端 rq-client.tsxgetQueryClient采用服务端每次新建、浏览器单例的经典模式序列化配置在 shared.tsstaleTime设为 30 秒以避免水合后立即重复拉取且shouldDehydrateQuery放开了pending状态查询的脱水——源码注释解释了原因we set a stale time so that queries arent immediately refetched on the client 以及 include pending queries in dehydration ... allows us to prefetch in RSC and send promises over the RSC boundary即允许把进行中的 Promise 经由 RSC 边界传给客户端续用消费端示例见 rsc-rq-prefetch/post.tsxuseSuspenseQuery(trpc.getLatestPost.queryOptions())搭配useMutationinvalidateQueries完成读预取、写后手动失效的闭环。六、验证方式与工程约束包脚本package.json提供dev/build/start以及基于 Playwright 的 e2etest:e2e、test-devstart-server-and-test起 3000 端口后跑playwright test测试文件 test/client.test.ts 与 test/server-cache.test.ts 分别覆盖客户端行为与服务端缓存语义是理解nextCacheLink行为契约的入口目录名.experimental带前导点本身即仓库层面的隔离声明README 提示若要贡献修改应到上游仓库的对应目录进行并通过官方社区渠道讨论方案取向README 指向官方 Discord。七、适用判断什么时候值得参考这个方案综合 README 与源码该实验方案的取舍可以归纳为收益RSC 与客户端共享同一 router 类型与调用语法RSC 直调省 HTTP 往返并可访问服务端私有数据revalidate机制让 RSC 数据缓存可控procedure 体系输入校验、中间件、transformer完整保留。代价与限制全部 API 均带experimental_前缀experimental_createTRPCNextAppDirClient/experimental_nextHttpLink/experimental_createTRPCNextAppDirServer/experimental_nextCacheLink/experimental_serverActionLink/experimental_createActionHook/experimental_revalidateEndpoint接口稳定性不保证缓存自动失效链路未完成README 明确警告生产使用可能伴随大规模重构。建议姿势把它当作App Directory 下 tRPC 架构演进的活参考重点研读react-server入口拆分、nextCacheLink与 revalidate 端点的设计若需在生产落地当前更稳妥的组合仍是 README 提示的既有路径——组件内直接使用trpc/client或在客户端组件中沿用trpc/next并配合 next-minimal-starter 等稳定示例。理解这一实验仓库等于拿到了一张tRPC 官方 App Directory 适配器的需求清单与原型实现入口按模块条件分流、RSC 进程内直调、缓存与失效显式化、Server Action 包装 procedure——这四点很可能就是正式适配器 API 定型时的骨架。【免费下载链接】trpc‍♀️ Move Fast and Break Nothing. End-to-end typesafe APIs made easy.项目地址: https://gitcode.com/GitHub_Trending/tr/trpc创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻