開発体験(developer experience) DB query in API routes or RCS

将来ちゃんとしたAPIのエンドポイントを作るか迷っていたため、RSCにてDBクエリを書く方法で行くか迷っていたためNext.js API routesに書いていたんですがtypeのinferしてくれなくて使いづらいかった。 まずはこんな感じで api routes export async function GET( request: NextRequest, { params }: { params: Promise<{ id: string }> } ) { try { const { id } = await params; const spot = await db.query.napSpots.findFirst({ where: eq(napSpots.id, id), with: { ratings: { with: { user: true, }, }, }, }); if (!spot) { console.error("[API] Nap spot not found for ID:", id); return NextResponse.json( { error: "Nap spot not found" }, { status: 404 } ); } return NextResponse....

April 4, 2025 · 1 min · 171 words · me

サーバーサイド・レンダリング/サーバーアイランドでのCDNと活用法

SSR ? Sever islands? Server side rendering(SSR)とはブラウザからのリクエストをサーバー上データをフェッチしたなどの上で生成されたhtmlを返す方法です。 Server islandsとはSSRと多少似てはいますが、返ってくる静的htmlがjsバンドルをもっておりそこからその部分のJSからサーバーにデータをとりにいったりするという方法です。 対象 CSRからSSRまたはServer Islandsモデルでのプロジェクトに関わるかた。 SSR/Server IslandsモデルではどうやってCDNを使用するか。 SSRとのAstroにおけるServer islandsでのCDNの静的htmlの違い。 SSRでは、静的なhtmlをいわゆる静的なファイルをおくcdn上に置くことはできません。 CSRではCDNに静的HTMLをおいてありそこからすぐに送り返すことができました。 しかし、SSRではデータをフェッチする時やランディングページが動的なコンポーネントがある場合はedge computing といわれるそこにHTMLをおいてそこからブラウザに送って上げるというかたちになります。 しかし、それらを提供しているのはvercel, netlifyなどであり、また会社のチームでそのようなものをサービスを通さずにつくるのは自前で作成するのは複雑という面もあるかと思います。 ここで Astroが静的htmlを返す方法が活躍します。 Astroにてブラウザがリクエストを送った際に返ってくるのは静的なHTMLです。そこに必要なJSバンドルがついておりそこからそのJSファイルを読みデータフェッチやイベントハンドラーなど必要な作業をします。 一番の違いは静的HTMLであるということです。このメリットは以外にも大きくて一番はCDNなどに静的ファイルであるためおいておけるというメリットがあります。上記で述べたSSRモデルとは違い、インフラの面においてもS3,R2などにもホスティングできるのでそこまで複雑にはならないです。 まとめ。じゃあどれを採用するか。 どんな種類のアプリを開発するかなどいろいろな視点がありますがCDNの面に視点を当てると Next.js: SSRでは、edge computingや動的コンテンツ用のCDNワなど、より複雑なCDN戦略が必要となります。 静的レンダリングと動的レンダリングを組み合わせたハイブリッド・アプローチが有効な場合がある。Experimental PPR (Partial Pre-Rendering) Astro: ほとんどのコンテンツでCDNキャッシングを活用しやすい 静的HTMLをCDN経由で効率的にグローバルに配信可能 などが採用する際にCDNに関して考えることかと今のところは思います。

February 17, 2025 · 1 min · 40 words · me

Refactor client to server component

Very simple example to convert React server component(RSC) from Client component. lets look at this code. the export async function addTodo(title: string) { await db.insert(todoTable).values({ title }); revalidatePath("/"); } TodoForm.tsx "use client"; import { useState } from "react"; import { addTodo } from "../server/queries"; export default function TodoForm() { const [title, setTitle] = useState(""); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (title.trim()) { await addTodo(title); setTitle(""); } }; return ( <form onSubmit={handleSubmit} className="flex space-x-2"> <input type="text" value={title} onChange={(e) => setTitle(e....

December 12, 2024 · 2 min · 300 words · me