停止手动在 Next.js 中设置 tRPC —— 使用此 CLI

发布: (2026年3月7日 GMT+8 14:28)
3 分钟阅读
原文: Dev.to

Source: Dev.to

Introduction

每次我用 tRPC 开始一个新的 Next.js 项目时,都要:打开文档、复制文件、安装依赖、包装 layout.tsx、修复 QueryClient 错误,然后在下一个项目中重复这些步骤。为了消除这种重复的设置,我创建了一个 CLI:

npx create-trpc-setup

What the CLI Does

在任意已有的 Next.js 项目中运行该命令会自动:

  • 安装所需的包(@trpc/server@trpc/client@trpc/tanstack-react-query@tanstack/react-queryzod 等)。
  • 检测你的包管理器(npm、pnpm、yarn、bun)。
  • 读取 tsconfig.json 以遵循路径别名(@/*~/ 或自定义别名)。
  • 检测身份验证提供商(Clerk 或 NextAuth)并相应地配置上下文。
  • 适配你的文件夹结构(src/ 或根目录的 layout)。

随后它会生成以下文件:

trpc/
├── init.ts         ← context, baseProcedure, protectedProcedure, Zod error formatter
├── query-client.ts ← SSR‑safe QueryClient
├── client.tsx      ← TRPCReactProvider + useTRPC hook
├── server.tsx      ← prefetch, HydrateClient, caller
└── routers/
    └── _app.ts     ← health + greet procedures with Zod

app/api/trpc/[trpc]/route.ts   ← API handler with real headers
app/trpc-status/               ← test page (delete after confirming)

Updating layout.tsx

Before


  {children}
  

After


  
    {children}
    
  

Using the Generated Setup

Server Component – Prefetch Data

// app/page.tsx
import { HydrateClient, prefetch, trpc } from "@/trpc/server";
import { MyClient } from "./my-client";

export default function Page() {
  prefetch(trpc.greet.queryOptions({ name: "World" }));
  return (
    
      
    
  );
}

Client Component – Consume Data

// my-client.tsx
"use client";

import { useSuspenseQuery } from "@tanstack/react-query";
import { useTRPC } from "@/trpc/client";

export function MyClient() {
  const trpc = useTRPC();
  const { data } = useSuspenseQuery(
    trpc.greet.queryOptions({ name: "World" })
  );
  return {data.message};
}

Comparison with create-t3-app

  • create-t3-app 非常适合 项目。
  • create-trpc-setup 适用于 已有 项目,即使它们已经使用了 Clerk、Shadcn UI 或自定义提供商。该命令会在不修改现有代码的情况下添加所有必需的文件。

Protected Procedure Helper

生成的 init.ts 包含一个 protectedProcedure,当 ctx.userId 缺失时会自动抛出 UNAUTHORIZED 错误:

export const protectedProcedure = t.procedure.use(({ ctx, next }) => {
  if (!ctx.userId) {
    throw new TRPCError({ code: "UNAUTHORIZED" });
  }
  return next({ ctx: { ...ctx, userId: ctx.userId } });
});

你可以在任何路由中使用它:

getProfile: protectedProcedure.query(({ ctx }) => {
  return { userId: ctx.userId }; // guaranteed non‑null
}),
  • npm package:
  • GitHub repository:

如果这个 CLI 为你节省了时间,请考虑给仓库点星并与团队分享。

0 浏览
Back to Blog

相关文章

阅读更多 »