独立适配器
tRPC 的独立适配器是让新项目运行的最简单方法。它非常适合本地开发和基于服务器的生产环境。本质上,它只是标准 Node.js HTTP 服务器 的封装,包含与 tRPC 相关的常规选项。
¥tRPC's Standalone Adapter is the simplest way to get a new project working. It's ideal for local development, and for server-based production environments. In essence it's just a wrapper around the standard Node.js HTTP Server with the normal options related to tRPC.
如果你有现有的 API 部署(例如 Express、Fastify 或 Next.js),并且想要将 tRPC 集成到其中,则应该查看它们各自的适配器。同样,如果你更喜欢在无服务器或边缘计算上托管,我们有 AWS Lambda 和 拿来 等适配器可能适合你的需求。
¥If you have an existing API deployment like Express, Fastify, or Next.js, which you want to integrate tRPC into, you should have a look at their respective adapters. Likewise if you have a preference to host on serverless or edge compute, we have adapters like AWS Lambda and Fetch which may fit your needs.
当部署的适配器很难在本地计算机上运行时,应用中有 2 个入口点的情况也很常见。你可以使用独立适配器进行本地开发,并在部署时使用不同的适配器。
¥It's also not uncommon, where the deployed adapter is hard to run on local machines, to have 2 entry-points in your application. You could use the Standalone Adapter for local development, and a different adapter when deployed.
示例应用
¥Example app
描述 | 链接 |
---|---|
独立 tRPC 服务器 | |
具有 CORS 处理功能的独立 tRPC 服务器 |
设置独立 tRPC 服务器
¥Setting up a Standalone tRPC Server
1. 实现你的应用路由
¥ Implement your App Router
实现你的 tRPC 路由。例如:
¥Implement your tRPC router. For example:
appRouter.tsts
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 choicereturn await UserModel.create({data: opts.input,});}),});// export type definition of APIexport type AppRouter = typeof appRouter;
appRouter.tsts
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 choicereturn await UserModel.create({data: opts.input,});}),});// export type definition of APIexport type AppRouter = typeof appRouter;
欲了解更多信息,你可以查看 快速入门指南
¥For more information you can look at the quickstart guide
2. 使用独立适配器
¥ Use the Standalone adapter
独立适配器运行一个简单的 Node.js HTTP 服务器。
¥The Standalone adapter runs a simple Node.js HTTP server.
server.tsts
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.tsts
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 和选项
¥Handling CORS & OPTIONS
默认情况下,独立服务器不会响应 HTTP OPTIONS 请求,也不会设置任何 CORS 标头。
¥By default the standalone server will not respond to HTTP OPTIONS requests, or set any CORS headers.
如果你没有托管在可以为你处理此问题的环境中(例如在本地开发期间),你可能需要处理它。
¥If you're not hosting in an environment which can handle this for you, like during local development, you may need to handle it.
1. 安装 cors
¥ Install cors
你可以使用流行的 cors
包自行添加支持
¥You can add support yourself with the popular cors
package
bash
yarn add corsyarn add -D @types/cors
bash
yarn add corsyarn add -D @types/cors
有关如何配置此包的完整信息,检查文档
¥For full information on how to configure this package, check the docs
2. 配置独立服务器
¥ Configure the Standalone server
此示例只是向任何请求抛出开放的 CORS,这对于开发很有用,但你可以而且应该在生产环境中更严格地配置它。
¥This example just throws open CORS to any request, which is useful for development, but you can and should configure it more strictly in a production environment.
server.tsts
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.tsts
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
以外的处理。然而,它的目的是作为一个简单的应急方案,因此它本身不允许你将多个中间件组合在一起。如果你想这样做,那么你可以:
¥The middleware
option will accept any function which resembles a connect/node.js middleware, so it can be used for more than cors
handling if you wish. It is, however, intended to be a simple escape hatch and as such won't on its own allow you to compose multiple middlewares together. If you want to do this then you could:
-
使用具有更全面的中间件支持的备用适配器,例如 快速适配器
¥Use an alternate adapter with more comprehensive middleware support, like the Express adapter
-
使用解决方案来编写中间件,例如 connect
¥Use a solution to compose middlewares such as connect
-
使用自定义 http 服务器扩展独立
createHTTPHandler
(见下文)¥Extend the Standalone
createHTTPHandler
with a custom http server (see below)
向自定义 HTTP 服务器添加处理程序
¥Adding a handler to an Custom HTTP server
createHTTPServer
返回 Node 内置 http.Server
(https://nodejs.cn/api/http.html#class-httpserver)的一个实例,这意味着你可以访问它的所有属性和 API。但是,如果 createHTTPServer
不足以满足你的用例,你还可以使用独立适配器的 createHTTPHandler
功能来创建自己的 HTTP 服务器。例如:
¥createHTTPServer
is returning an instance of Node's built-in http.Server
(https://nodejs.cn/api/http.html#class-httpserver), which means that you have an access to all it's properties and APIs. However, if createHTTPServer
isn't enough for your usecase, you can also use the standalone adapter's createHTTPHandler
function to create your own HTTP server. For instance:
server.tsts
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.tsts
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);
自定义处理请求的基本路径下
¥Custom base path to handle requests under
独立适配器还支持 basePath
选项,它将从请求路径的开头切分 basePath。
¥The Standalone adapter also supports a basePath
option, which will slice the basePath from the beginning of the request path.
server.tsts
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.tsts
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);
HTTP2
独立适配器还支持 HTTP/2。
¥The Standalone adapter also supports HTTP/2.
server.tsts
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.tsts
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.tsts
import {CreateHTTP2ContextOptions } from '@trpc/server/adapters/standalone';export async functioncreateContext (opts :CreateHTTP2ContextOptions ) {opts .req ;opts .res ;opts .info ;return {};}export typeContext =Awaited <ReturnType <typeofcreateContext >>;
context.tsts
import {CreateHTTP2ContextOptions } from '@trpc/server/adapters/standalone';export async functioncreateContext (opts :CreateHTTP2ContextOptions ) {opts .req ;opts .res ;opts .info ;return {};}export typeContext =Awaited <ReturnType <typeofcreateContext >>;