跳至主内容
版本:11.x

独立适配器

非官方测试版翻译

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

tRPC 的独立适配器是新项目启动的最简方案,特别适合本地开发和基于服务器的生产环境。本质上它只是对标准 Node.js HTTP Server 的封装,并集成了 tRPC 相关配置选项。

若需将 tRPC 集成到现有 API 部署环境(如 ExpressFastifyNext.js),请查阅对应的适配器文档。同样地,如果倾向在无服务器或边缘计算环境部署,我们提供 AWS LambdaFetch 等适配器方案。

当部署环境的适配器难以在本地运行时,常见做法是在应用中设置双入口:开发环境使用独立适配器,生产环境切换为其他适配器。

示例应用

DescriptionLinks
Standalone tRPC Server
Standalone tRPC Server with CORS handling

配置独立 tRPC 服务器

1. 实现应用路由

实现 tRPC 路由,例如:

appRouter.ts
ts
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
export const t = initTRPC.create();
export const appRouter = t.router({
getUser: t.procedure.input(z.string()).query((opts) => {
return { id: opts.input, name: 'Bilbo' };
}),
createUser: t.procedure
.input(z.object({ name: z.string().min(5) }))
.mutation(async (opts) => {
// use your ORM of choice
return await UserModel.create({
data: opts.input,
});
}),
});
// export type definition of API
export type AppRouter = typeof appRouter;
appRouter.ts
ts
import { initTRPC } from '@trpc/server';
import { z } from 'zod';
export const t = initTRPC.create();
export const appRouter = t.router({
getUser: t.procedure.input(z.string()).query((opts) => {
return { id: opts.input, name: 'Bilbo' };
}),
createUser: t.procedure
.input(z.object({ name: z.string().min(5) }))
.mutation(async (opts) => {
// use your ORM of choice
return await UserModel.create({
data: opts.input,
});
}),
});
// export type definition of API
export type AppRouter = typeof appRouter;

更多实现细节请参考快速入门指南

2. 使用独立适配器

该适配器会启动一个简易的 Node.js HTTP 服务器。

server.ts
ts
import { initTRPC } from '@trpc/server';
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { appRouter } from './appRouter.ts';
createHTTPServer({
router: appRouter,
createContext() {
console.log('context 3');
return {};
},
// basePath: '/trpc/', // optional, defaults to '/'
}).listen(2022);
server.ts
ts
import { initTRPC } from '@trpc/server';
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import { appRouter } from './appRouter.ts';
createHTTPServer({
router: appRouter,
createContext() {
console.log('context 3');
return {};
},
// basePath: '/trpc/', // optional, defaults to '/'
}).listen(2022);

处理 CORS 与 OPTIONS 请求

默认情况下,独立服务器不会响应 HTTP OPTIONS 请求,也不设置任何 CORS 头信息。

若部署环境(如本地开发时)未自动处理跨域,您可能需要手动配置。

1. 安装 cors 包

可通过流行的 cors 包自行添加支持:

bash
yarn add cors
yarn add -D @types/cors
bash
yarn add cors
yarn add -D @types/cors

完整配置方法请查阅文档

2. 配置独立服务器

此示例为开发便利开放了全量 CORS,生产环境应严格限制访问源:

server.ts
ts
import { initTRPC } from '@trpc/server';
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import cors from 'cors';
createHTTPServer({
middleware: cors(),
router: appRouter,
createContext() {
console.log('context 3');
return {};
},
}).listen(3333);
server.ts
ts
import { initTRPC } from '@trpc/server';
import { createHTTPServer } from '@trpc/server/adapters/standalone';
import cors from 'cors';
createHTTPServer({
middleware: cors(),
router: appRouter,
createContext() {
console.log('context 3');
return {};
},
}).listen(3333);

middleware 选项接受任何类 connect/node.js 中间件函数,因此不仅限于处理 cors。但需注意:这仅是简易扩展方案,无法直接组合多个中间件。如需高级功能可尝试:

  1. 改用支持完整中间件体系的适配器(如 Express 适配器

  2. 使用中间件组合方案(例如 connect

  3. 基于独立适配器的 createHTTPHandler 扩展自定义 HTTP 服务器(见下文)

为自定义 HTTP 服务器添加处理器

createHTTPServer 返回的是 Node.js 内置的 http.Server(https://nodejs.org/api/http.html#class-httpserver) 实例,您可访问其所有属性和 API。若 createHTTPServer 无法满足需求,还可使用适配器的 createHTTPHandler 函数构建自定义 HTTP 服务器:

server.ts
ts
import { createServer } from 'http';
import { initTRPC } from '@trpc/server';
import { createHTTPHandler } from '@trpc/server/adapters/standalone';
const handler = createHTTPHandler({
router: appRouter,
createContext() {
return {};
},
});
createServer((req, res) => {
/**
* Handle the request however you like,
* just call the tRPC handler when you're ready
*/
handler(req, res);
}).listen(3001);
server.ts
ts
import { createServer } from 'http';
import { initTRPC } from '@trpc/server';
import { createHTTPHandler } from '@trpc/server/adapters/standalone';
const handler = createHTTPHandler({
router: appRouter,
createContext() {
return {};
},
});
createServer((req, res) => {
/**
* Handle the request however you like,
* just call the tRPC handler when you're ready
*/
handler(req, res);
}).listen(3001);

处理指定基路径下的请求

Standalone 适配器支持 basePath 选项,该配置会从请求路径开头截取指定基路径。

server.ts
ts
import { createServer } from 'http';
import { initTRPC } from '@trpc/server';
import { createHTTPHandler } from '@trpc/server/adapters/standalone';
const handler = createHTTPHandler({
router: appRouter,
basePath: '/trpc/',
});
createServer((req, res) => {
if (req.url?.startsWith('/trpc/')) {
return handler(req, res);
}
// [... insert your custom logic here ...]
res.statusCode = 404;
res.end('Not Found');
}).listen(3001);
server.ts
ts
import { createServer } from 'http';
import { initTRPC } from '@trpc/server';
import { createHTTPHandler } from '@trpc/server/adapters/standalone';
const handler = createHTTPHandler({
router: appRouter,
basePath: '/trpc/',
});
createServer((req, res) => {
if (req.url?.startsWith('/trpc/')) {
return handler(req, res);
}
// [... insert your custom logic here ...]
res.statusCode = 404;
res.end('Not Found');
}).listen(3001);

HTTP/2 支持

Standalone 适配器同样兼容 HTTP/2 协议。

server.ts
ts
import http2 from 'http2';
import { createHTTP2Handler } from '@trpc/server/adapters/standalone';
import { appRouter } from './_app.ts';
import { createContext } from './context.ts';
const handler = createHTTP2Handler({
router: appRouter,
createContext,
// basePath: '/trpc/', // optional, defaults to '/'
});
const server = http2.createSecureServer(
{
key: '...',
cert: '...',
},
(req, res) => {
/**
* Handle the request however you like,
* just call the tRPC handler when you're ready
*/
handler(req, res);
},
);
server.listen(3001);
server.ts
ts
import http2 from 'http2';
import { createHTTP2Handler } from '@trpc/server/adapters/standalone';
import { appRouter } from './_app.ts';
import { createContext } from './context.ts';
const handler = createHTTP2Handler({
router: appRouter,
createContext,
// basePath: '/trpc/', // optional, defaults to '/'
});
const server = http2.createSecureServer(
{
key: '...',
cert: '...',
},
(req, res) => {
/**
* Handle the request however you like,
* just call the tRPC handler when you're ready
*/
handler(req, res);
},
);
server.listen(3001);
context.ts
ts
import { CreateHTTP2ContextOptions } from '@trpc/server/adapters/standalone';
 
export async function createContext(opts: CreateHTTP2ContextOptions) {
opts.req;
(property) req: http2.Http2ServerRequest
opts.res;
(property) res: http2.Http2ServerResponse
 
opts.info;
(property) info: TRPCRequestInfo
return {};
}
 
export type Context = Awaited<ReturnType<typeof createContext>>;
context.ts
ts
import { CreateHTTP2ContextOptions } from '@trpc/server/adapters/standalone';
 
export async function createContext(opts: CreateHTTP2ContextOptions) {
opts.req;
(property) req: http2.Http2ServerRequest
opts.res;
(property) res: http2.Http2ServerResponse
 
opts.info;
(property) info: TRPCRequestInfo
return {};
}
 
export type Context = Awaited<ReturnType<typeof createContext>>;