1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Nextjs App routerでtrpcを試してみた

Posted at

はじめに

NextjsでAPIを公開したいなぁって思ったことはありませんか?
その時に認可処理どうしようとかエラーハンドリングどうしましょうと悩んだことはありませんか?
さらに、それらの処理を共通して定義しておきたいと思ったことはありませんか?
そんな時に、ossを探していたらtrpcが使えるかも?と神に教えてもらったので実験してみようと思いました。
この記事はそんな実験的な記事件備忘録です。

ゴール

  • 本記事ではローカル環境でのHTTPリクエストの疎通を目標としています。
  • クライアント側の処理はこの記事では取り扱いません。

準備

サンプルプロジェクトを用意してください

npx create-next-app@latest
cd sample-trpc

trpcをinstallしてください。

npm install @trpc/server@next @trpc/client@next

手順

router instanceを作成します。

(ファイルは公式ドキュメント通りに実施していきます。)
下記はtrpcのbackendの初期化になります

src/server/trpc.ts
import { initTRPC } from '@trpc/server';
 
/**
 * Initialization of tRPC backend
 * Should be done only once per backend!
 */
const t = initTRPC.create();
 
/**
 * Export reusable router and procedure helpers
 * that can be used throughout the router
 */
export const router = t.router;
export const publicProcedure = t.procedure;

query procedureを設定します

router instanceを初期化しつつ、query procedureを設定しています。
今回だと、helloが対象となります。

src/server/index.ts
import { publicProcedure, router } from "./trpc";

export const appRouter = router({
  hello: publicProcedure.query(() => {
    return "Hello World";
  }),
});

export type AppRouter = typeof appRouter;

fetchRequestHandlerを設定する

Nextjs App Routerを使用している場合、fetchRequestHandlerを使用するとAPIを公開できます。

src/app/api/trpc/[trpc]/route.ts
import { appRouter } from "@/server";
import { fetchRequestHandler } from '@trpc/server/adapters/fetch';

function handler(req: Request) {
  return fetchRequestHandler({
    endpoint: '/api/trpc',
    req,
    router: appRouter,
    createContext: () => ({ ... })
  });
}
export { handler as GET, handler as POST };

サーバーを立ち上げて疎通してみます。

npm run dev
curl http://localhost:3000/api/trpc/hello
# {"result":{"data":"Hello World"}}

疎通が完了しました。結構簡単にAPIを用意できますね!

実験

Q. fetchRequestHandlerのendopointって、なんで/api/trpcなの?

回答

fetchRequestHandlerのendopointはapp routerのパスと連動しているみたいです。

検証

src/app/api/v1/[trpc]/route.ts
import { appRouter } from "@/server";
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
function handler(req: Request) {
  return fetchRequestHandler({
    endpoint: "/api/trpc",
    req,
    router: appRouter,
    createContext: () => ({}),
  });
}
export { handler as GET, handler as POST };

ファイルパスを変えて、エンドポイントをそのままでcurlを叩いてみましょう

curl http://localhost:3001/api/trpc/hello

結果は、404のhtmlが返却されると思います。

src/app/api/v1/[trpc]/route.ts
import { appRouter } from "@/server";
import { fetchRequestHandler } from "@trpc/server/adapters/fetch";
function handler(req: Request) {
  return fetchRequestHandler({
-    endpoint: "/api/trpc",
+    endpoint: "/api/v1",  // ファイルパスと連動したエンドポイント
    req,
    router: appRouter,
    createContext: () => ({}),
  });
}
export { handler as GET, handler as POST };

ファイルパスとエンドポイント合わせてcurlを叩いてみましょう

curl http://localhost:3001/api/v1/hello

しっかりと結果が返ってくると思います。

蛇足

Q. [trpc]をパスから消してみるとどうなるの?
A. 404になります。

POSTメソッドの設定はどうするの?

回答

queryではなく、mutationを使います。

src/server/index.ts
import { publicProcedure, router } from "./trpc";

export const appRouter = router({
  hello: publicProcedure.query(() => {
    return "Hello World";
  }),
+  hello2: publicProcedure.mutation(() => {
+    return "Hello World";
+  }),
});

export type AppRouter = typeof appRouter;

curl http://localhost:3001/api/v1/hello2 -X POST -H "Content-Type: application/json"
# {"result":{"data":"Hello World"}}

他にも色々と試した結果を備忘録的に残したいけど、長くなってしまうので別の記事にします。

感想

NextjsのApp routerでも安心してtrpcを使える!

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?