跳至主内容
版本:11.x

从 v10 迁移到 v11

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

从 v10 迁移到 v11

技巧

对大多数用户而言,迁移过程应该快速且直接。

如果以下三个步骤不够,请查阅下方文档中标记为 "rarely breaking" 的部分。

1. 安装新版本

npm install @trpc/server@^11 @trpc/client@^11 @trpc/react-query@^11 @trpc/next@^11 @tanstack/react-query@^5 @tanstack/react-query-devtools@^5

2. 如果您正在使用 transformer,请更新链接

更多信息请参阅 transformer 已移至链接

3. 如果您正在使用 @trpc/react-query,请更新 @tanstack/react-query 版本

更多信息请参阅 react-query-v5

完整倒序更新日志

全新 TanStack React Query 集成!(非破坏性变更)

我们很高兴地宣布,tRPC 的 next 版本现已支持全新的 TanStack React Query 集成!

Read the blog post for more information.

从服务端终止订阅(rarely breaking)

现在支持从服务端终止订阅,这意味着您可以实现如下操作:

ts
const myRouter = router({
sub: publicProcedure.subscription(async function* (opts) {
for await (const data of on(ee, 'data', {
signal: opts.signal,
})) {
const num = data[0] as number | undefined;
if (num === undefined) {
// This will now stop the subscription on the client and trigger the `onComplete` callback
return;
}
yield num;
}
}),
});
ts
const myRouter = router({
sub: publicProcedure.subscription(async function* (opts) {
for await (const data of on(ee, 'data', {
signal: opts.signal,
})) {
const num = data[0] as number | undefined;
if (num === undefined) {
// This will now stop the subscription on the client and trigger the `onComplete` callback
return;
}
yield num;
}
}),
});

更多信息请参阅 订阅文档

新增惰性加载路由支持(非破坏性变更)

更多信息请参阅 惰性加载路由文档

作为此项变更的一部分,我们已将内部方法 callProcedure() 的参数改为接收 { router: AnyRouter } 参数,而非 { _def: AnyRouter['_def'] } 参数。

独立适配器支持自定义 basePath(非破坏性变更)

独立适配器现在支持 basePath 选项,该选项会从请求路径开头截取 basePath。

更多信息请参阅 独立适配器文档

新增 HTTP/2 服务器支持(非破坏性变更)

现在支持 HTTP/2 服务器,这意味着您可以使用 createHTTP2HandlercreateHTTPServer 函数创建 HTTP/2 服务器。

更多信息请参阅 独立适配器文档

TRPCProcedureOptions 移至 @trpc/client(对多数用户非破坏性变更)

如果您之前使用 @trpc/server 中的 ProcedureOptions,现在需要改用 @trpc/client 中的 TRPCProcedureOptions

允许嵌套数据中嵌入 Promise(非破坏性变更)

现在使用 httpBatchStreamLink 时,允许在嵌套数据中嵌入 Promise,这意味着您可以实现如下操作:

ts
const router = router({
embedPromise: publicProcedure.query(() => {
async function slowThing() {
await new Promise((resolve) => setTimeout(resolve, 1000));
return 'slow';
}
return {
instant: 'instant',
slow: slowThing(),
};
}),
});
ts
const router = router({
embedPromise: publicProcedure.query(() => {
async function slowThing() {
await new Promise((resolve) => setTimeout(resolve, 1000));
return 'slow';
}
return {
instant: 'instant',
slow: slowThing(),
};
}),
});

reconnectAfterInactivityMs 移至 sse.client(非破坏性变更)

已更新 HTTP 订阅链接改进 章节及相关文档。

要求 TypeScript 版本 >=5.7.2(非破坏性变更)

tRPC 现在要求 TypeScript 版本 >=5.7.2。此项变更是针对 错误报告 做出的,我们决定采取前瞻性的方法。

如果你尝试使用不受支持的 TypeScript 版本安装 tRPC,在安装过程中会遇到 peer 依赖错误。

如果发现编辑器显示 any 类型,很可能是因为编辑器未使用正确的 TypeScript 版本。要解决此问题,需要将编辑器配置为使用项目 package.json 中安装的 TypeScript 版本。

对于 VSCode 用户,请将以下设置添加到你的 .vscode/settings.json 文件:

.vscode/settings.json
json
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}
.vscode/settings.json
json
{
"typescript.tsdk": "node_modules/typescript/lib",
"typescript.enablePromptUseWorkspaceTsdk": true
}

experimental.sseSubscriptions 移至 sse(非破坏性变更)

experimental.sseSubscriptions 选项已移至 initTRPC.create() 函数中的 sse

增加了对陈旧连接的检测和恢复支持:

在服务器端,你可以配置 ping 间隔以保持连接活跃:

ts
export const t = initTRPC.create({
// ...
sse: {
ping: {
enabled: true,
intervalMs: 15_000,
},
client: {
// Reconnect if no messages or pings are received for 20 seconds
reconnectAfterInactivityMs: 20_000,
},
},
});
ts
export const t = initTRPC.create({
// ...
sse: {
ping: {
enabled: true,
intervalMs: 15_000,
},
client: {
// Reconnect if no messages or pings are received for 20 seconds
reconnectAfterInactivityMs: 20_000,
},
},
});

我们未来可能会添加默认的 ping 间隔和超时配置,但目前尚未决定。欢迎在 Discord 的 🎏-rfc-streaming 频道提供反馈。

有关这些功能的更多详情,请参阅 httpSubscriptionLink 文档

引入 retryLink(非破坏性变更)

请参阅 retryLink —— 允许重试失败的操作

useSubscription 改进(非破坏性变更)

订阅过程输出类型改为 AsyncGenerator(非破坏性变更)

如果你在 v11 中使用过带异步生成器的订阅,这可能会影响你的类型推断方式。

Details

We changed the inferred output from:

ts
SubscriptionProcedure<{
input: __INPUT__;
output: __OUTPUT__;
}>;
ts
SubscriptionProcedure<{
input: __INPUT__;
output: __OUTPUT__;
}>;

to

ts
SubscriptionProcedure<{
input: __INPUT__;
output: AsyncGenerator<__OUTPUT__, void, unknown>;
}>;
ts
SubscriptionProcedure<{
input: __INPUT__;
output: AsyncGenerator<__OUTPUT__, void, unknown>;
}>;

If you need to infer the value you can use a helper like the below:

ts
type inferAsyncIterableYield<TOutput> =
TOutput extends AsyncGenerator<infer $Yield> ? $Yield : never;
ts
type inferAsyncIterableYield<TOutput> =
TOutput extends AsyncGenerator<infer $Yield> ? $Yield : never;

此变更是为了确保库与未来更新保持兼容,并允许在订阅的 AsyncGenerator 中使用 return 类型。

更多信息请参阅 订阅文档

增加对订阅中输出验证器的支持(非破坏性变更)

更多信息请参阅 订阅文档

弃用返回 Observable 的订阅(非破坏性变更)

我们现在支持返回异步生成器函数用于订阅,且此前已添加 httpSubscriptionLink

要了解如何使用异步生成器函数进行订阅,请参阅 订阅文档

移除 AbortControllerEsque-ponyfill(极少破坏性变更)

我们已从 tRPC 中移除 AbortControllerEsque-ponyfill,如需支持旧版浏览器,可使用类似 abortcontroller-polyfill 的 polyfill。

支持服务器发送事件(SSE)(非破坏性变更)

现在支持使用 SSE 进行订阅,这意味着无需启动 WebSocket 服务器即可在应用中获取实时更新,且客户端可在连接丢失时自动重连恢复。

👉 更多内容请参阅 httpSubscriptionLink 文档

支持通过 HTTP 流式传输响应(非破坏性变更)

现在支持使用 httpBatchStreamLink 流式传输变更和查询。

这意味着查询和变更解析器现在既可以是支持 yieldAsyncGenerator,也可以是支持延迟执行返回的 Promise。这样您就能在不使用 WebSocket 的情况下,通过 HTTP 实现流式响应。

我们非常期待您对这个功能的反馈!请试用后通过 Discord 的 🎏-rfc-streaming 频道告诉我们您的想法。

👉 详见 httpBatchStreamLink 文档

resolveHTTPRequest 已被基于 Fetch API 的 resolveRequest 取代(极少破坏性变更)

函数 resolveHTTPRequest 已替换为使用 Fetch API(Request/Response)的 resolveRequest

这对 HTTP 适配器属于破坏性变更,但普通用户不会受影响。

如果您正在开发适配器,请参考我们的适配器实现代码,并欢迎随时通过 Discord 寻求帮助。

TRPCRequestInfo 已更新(极少破坏性变更)

输入数据现在改为按需延迟加载(当流程真正调用时才加载),这意味着在 createContext 被调用时,输入参数和流程类型将不再可用。

您仍可通过 info.calls[index].getRawInput() 访问原始输入。

所有实验性 form-data 支持已被替换(极少破坏性变更)

仅当您使用过实验性 formdata 功能时才会受影响

  • experimental_formDataLink → 改用 httpLink

  • experimental_parseMultipartFormData → 不再需要

  • experimental_isMultipartFormDataRequest → 不再需要

  • experimental_composeUploadHandlers → 不再需要

  • experimental_createMemoryUploadHandler → 不再需要

  • experimental_NodeOnDiskFile 和 experimental_createFileUploadHandler → 当前版本暂不支持磁盘存储,如有需求请提交 issue

  • experimental_contentTypeHandlers → 不再需要,但若社区有新型数据类型需求可能重新引入

新实现方案请参考 examples/next-formdata 示例

Procedure._def._output_in / Procedure._def._input_in 已迁移至 Procedure._def.$types(非破坏性变更)

这属于 tRPC 内部破坏性变更,但普通用户不受影响。

除非您直接在代码中使用 Procedure._def._output_inProcedure._def._input_in,否则无需任何操作。

显式 Content-Type 检查(非破坏性变更)

现在对 POST 请求执行显式的 Content-Type 标头检查。这意味着当发送的请求 Content-Type 与预期不匹配时,将返回 415 Unsupported Media Type 错误。

tRPC 客户端已自动发送内容类型标头,因此仅当您手动调用 tRPC 时才可能受此变更影响。

新增方法覆盖支持(极少破坏性变更)

允许您覆盖流程的 HTTP 方法,使其始终通过 POST 发送,从而解决诸如 URL 长度限制等问题。

关闭 #3910

新增双向无限查询支持(非破坏性变更)

参见 useInfiniteQuery()

新增 inferProcedureBuilderResolverOptions<T> 辅助工具(非破坏性变更)

新增用于推断过程构建器解析器选项的辅助工具。适用于需要为不同过程创建可复用函数的情况。

使用示例参见测试用例

转换器移至链接层(破坏性变更) -

TypeScript 将引导您完成此迁移

仅在使用数据转换器时适用

现在需要在 links 数组中配置数据转换器,而非在初始化 tRPC 客户端时配置:

在使用 HTTP 链接的位置,若需使用转换器需添加 transformer: superjson

ts
httpBatchLink({
url: '/api/trpc',
transformer: superjson, // <-- add this
});
ts
httpBatchLink({
url: '/api/trpc',
transformer: superjson, // <-- add this
});
ts
createTRPCNext<AppRouter>({
// [..]
transformer: superjson, // <-- add this
});
ts
createTRPCNext<AppRouter>({
// [..]
transformer: superjson, // <-- add this
});

@trpc/next SSR 模式现需配合 ssr: true 的预渲染助手(罕见破坏性变更)

此变更是为了修复 #5378,在该问题中 react-dom 被无条件导入,无论你是否使用该功能。

参见 SSR 文档

新增支持简写路由定义(非破坏性变更)

参见合并路由

ts
const appRouter = router({
// Shorthand plain object for creating a sub-router
nested1: {
proc: publicProcedure.query(() => '...'),
},
// Equivalent of:
nested2: router({
proc: publicProcedure.query(() => '...'),
}),
});
ts
const appRouter = router({
// Shorthand plain object for creating a sub-router
nested1: {
proc: publicProcedure.query(() => '...'),
},
// Equivalent of:
nested2: router({
proc: publicProcedure.query(() => '...'),
}),
});

移除 inferHandlerInput<T>ProcedureArgs<T>(对多数用户无影响)

若您代码中未使用这些类型,可忽略此变更

请改用 inferProcedureInput<TProcedure>TRPCProcedureOptions

新增 useSuspenseQueries()

参见 useSuspenseQueries

https://github.com/trpc/trpc/pull/5226

重构内部泛型(罕见破坏性变更)

我们重构了内部泛型实现以提升可读性(待补充过程构建器文档链接)

React 最低版本要求提升至 18.2.0(罕见破坏性变更)

参考 React 迁移指南:https://react.dev/blog/2022/03/08/react-18-upgrade-guide

现需 NodeJS 18+ 及现代浏览器支持(罕见破坏性变更)

因新增 FormData/File/Blob/ReadableStream 等 API 的使用,现需 NodeJS 18+ 环境(浏览器端已支持多年)

  • 支持在 url 回调中返回 Promise 以适应部署期间的服务器位置变更

  • 新增 lazy 选项,当无挂起请求时自动断开 WebSocket 连接

中间件中 rawInput 变更为 getRawInput(罕见破坏性变更)

虽然内部实现暂未改变,但此变更为支持 tRPC 的高频需求:非 JSON 内容类型处理铺平道路

简化类型及 .d.ts 输出

路由中的过程现在仅输出其输入/输出类型。此前每个过程都会包含完整上下文对象,导致 .d.ts 等输出产生不必要的复杂性

React Query 同级依赖升级至 v5(破坏性变更) -

您需要做的主要事情是将大量的 isLoading 替换为 isPending

请查阅他们的迁移指南:https://tanstack.com/query/v5/docs/framework/react/guides/migrating-to-v5

导出名称 AbcProxyXyz 已重命名为 AbcXyz(非破坏性变更)

代理名称的出现是因为 v9 使用了 AbcXyz 名称,这些已被移除,代理名称已重命名为非代理名称,例如:

  • createTRPCClient 从 v9 开始已被弃用,现在已完全移除。createTRPCProxyClient 已重命名为 createTRPCClientcreateTRPCProxyClient 现在标记为已弃用。

SSG 助手(很少引起破坏性变更)

  • createSSGHelpers 用于 v9 现已移除。v10 中的等价物 createProxySSGHelpers 现已重命名为 createSSGHelpers

  • createProxySSGHelpers 现已弃用,但为了向后兼容已别名化为 createSSGHelpers

  • 已移除导出的类型 CreateSSGHelpersOptions

interop 模式已被移除(很少引起破坏性变更) -

我们已从 tRPC 中移除了 interop 模式。该模式旨在帮助您从 v9 轻松过渡到 v10。此模式从未计划长期支持,现已被移除。