0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【前編】SDDで近況ノートをNext.jsへ移行した〜仕様を作るまで〜

0
Posted at

はじめに

個人開発している「近況ノート」を、React RouterのSPAからNext.js へ移行しました。

近況ノートは、同窓会や久しぶりの集まりを前に、同級生同士で現在地や仕事、最近の出来事を共有するためのWebアプリです。

共有URLを知っている人はログインせずに近況を閲覧でき、自分の近況を投稿・編集するときはLINE Loginを利用します。投稿へのいいねやコメントなど、簡単な交流機能もあります。

今回の移行を始めた一番の理由は、SDD(Spec-Driven Development/仕様駆動開発)を練習してみたかったからです。

すでに動いているアプリを題材にして、AIへいきなり実装を依頼するのではなく、先にプロジェクトの前提、要件、設計、実装タスクを文章にしてから移行を進めました。

この記事は全3編でまとめます。

  • 前編:steering documentsと移行仕様を作るまで
  • 中編:作成したタスクに沿ってNext.jsへ移行する過程
  • 後編:本番切り替え、旧構成の削除、SDDを試して分かったこと

前編では、実装を始める前に何をAIへ伝え、どのような文書を作ったのかを紹介します。

SDDの題材にNext.js移行を選んだ

今回は、SDDを導入して開発上の問題を解決しようとしたというより、まず一度SDDの流れを最後まで試してみることが目的でした。

題材には、近況ノートのNext.js移行を選びました。

新規アプリの開発では、途中で仕様そのものを変えたくなることがあります。一方、既存アプリの移行では、移行前の画面や操作が比較対象になります。

近況ノートにも、移行で壊したくないものがすでにありました。

  • グループごとのURL
  • 近況の閲覧、投稿、編集
  • LINE Loginとログイン後の投稿再開
  • Honoで作った既存API
  • Cloudflare D1に保存しているデータ
  • いいね、コメント、アバター画像
  • モバイル向けの画面と操作感

「何を変えるか」と「何を変えないか」がはっきりしているため、要件と受入条件を書く練習に向いていると考えました。

最初にsteering documentsを作る

本格的な設計と実装に入る前に、既存リポジトリを調べてもらい、プロジェクト全体の前提となるsteering documentsを作りました。

作成したのは、次の3ファイルです。

.spec-workflow/steering/
  product.md
  tech.md
  structure.md

AIへ伝えた内容を要約すると、次のようになります。

既存の近況ノートを調査し、プロダクトの目的、採用技術、プロジェクト構造をsteering documentsとして整理して。

実際には移行要件のたたき台も並行して作っていましたが、その後の設計と実装で判断基準として使えるように、先にこの3文書を整えました。

product.md

product.mdには、近況ノートが誰のための、どのようなアプリなのかをまとめました。

主な内容は次のとおりです。

  • 同級生や小規模な仲間同士で近況を共有する
  • 幹事が一人ずつ近況を集める手間を減らす
  • 閲覧は気軽にし、投稿や編集では本人性を守る
  • ログインの往復があっても入力内容を失わせない
  • 不特定多数向けSNSではなく、小さなコミュニティの安心感を優先する

この文書によって、技術移行でも守るべき利用体験が明文化されました。

Next.jsへ移行できても、ログイン後に入力途中の近況が消えてしまえば、近況ノートとしては移行成功とはいえません。

tech.md

tech.mdには、現在の技術構成と移行後も維持する境界をまとめました。

移行前の主な構成は次のとおりです。

React + Vite + React Router
  -> Hono API on Cloudflare Workers
  -> Drizzle ORM
  -> Cloudflare D1

このほか、LINE Login、セッション、CSRF、Zod、React Hook Form、Tailwind CSSなども記録しました。

Next.jsへ移行しても、既存の/api/*、D1スキーマ、LINE OAuth、Cookieの振る舞いは安定した境界として扱う方針にしました。

structure.md

structure.mdには、コードをどこへ置き、どの方向へ依存させるかをまとめました。

近況ノートでは、移行前から次のような責務分離を採用していました。

presentation
  -> application
  -> infrastructure
  -> shared

Next.js移行後は、ここへApp Routerのappディレクトリが加わります。

ルートファイルへ業務処理を集めないこと、ブラウザAPIが必要な部分だけをClient Componentにすること、既存のユースケースやAPIクライアントを再利用することなどを決めました。

Next.js移行の仕様を作る

steering documentsを判断基準として使える状態にしたあと、Next.js移行のspecを作りました。

AIへ伝えた移行内容を要約すると、次のようになります。

Vite + React Routerで作られた近況ノートをNext.js App Routerへ移行する。Cloudflare WorkersへのデプロイにはOpenNextを使い、既存のHono API、D1、LINE Login、URL、画面、主要な操作は維持する。

設計では、Next.jsとCloudflareの公式資料に加えて、akfm_satoさんの『Next.jsの考え方』を参考にすることも伝えました。

この指示から、次の3文書を作成しました。

.spec-workflow/specs/nextjs-migration/
  requirements.md
  design.md
  tasks.md

それぞれを作って終わりにせず、内容を確認して承認してから次の段階へ進めました。

requirements.mdで移行の成功条件を決める

最初に作ったのが要件定義書です。

要件は、次の7項目に分かれました。

  1. 既存の振る舞いを維持したNext.js移行
  2. API互換性とバックエンドの継続性
  3. Cloudflareに適合するデプロイ構成
  4. フロントエンド構成とルーティングの明確化
  5. Server Components中心のデータ取得と状態遷移
  6. セキュリティとプライバシーの維持
  7. 検証可能性とロールバックの安全性

各要件には受入条件も作りました。

たとえば「既存の振る舞いを維持する」だけでは、どこまで確認すればよいか分かりません。

そこで、既存URLをNext.jsで表示できること、存在しないグループはNot Foundにすること、LINE OAuthやCSRFを維持すること、移行中はD1スキーマを変更しないことなどを具体的な条件にしました。

この段階で、単に「Next.jsで画面が表示されたら完了」ではないことが明確になりました。

design.mdで移行後の構成を決める

要件の次に、設計書を作りました。

設計で大きな判断になったのは、Next.jsと既存のHono APIをどう組み合わせるかです。

最終的に、次の2 Worker構成を採用しました。

ブラウザ
  -> Next.js / OpenNext 公開Worker
       -> Service Binding
            -> Hono API Worker
                 -> Cloudflare D1

ブラウザからは、これまでと同じ同一オリジンの/api/*へアクセスします。

公開WorkerはAPIリクエストをService Binding経由でHono API Workerへ転送します。D1やLINE LoginのシークレットはHono側だけに持たせます。

画面については、初期データをServer Componentで取得し、フォーム、下書き保存、画像処理、いいね、コメント、共有操作など、ブラウザでの操作が必要な部分だけをClient Componentとして残す設計にしました。

設計書には、このほかにも次の内容が含まれています。

  • App RouterへのURL対応
  • Server ComponentとClient Componentの境界
  • API GatewayとCookieの転送
  • キャッシュとRequest Memoization
  • CSP、CSRF、認証、認可
  • テスト方法
  • 本番デプロイとロールバック

ここまで決めてから、実装単位への分解に進みました。

tasks.mdで21個の実装タスクへ分解する

要件と設計をもとに、移行作業は21個のタスクに分かれました。

大きく分けると、次の流れです。

移行用の依存関係とテスト基盤を追加
  -> Next.js WorkerとHono API Workerを分離
  -> App Routerの土台を作成
  -> 各画面をServer/Client Componentへ分割
  -> React Router依存を除去
  -> 自動テストとOpenNextプレビューで検証
  -> 本番へ段階的にデプロイ
  -> 安定確認後にVite版を削除

各タスクには、作業内容だけでなく、次の項目も含まれています。

  • 変更対象のファイル
  • タスクの目的
  • 再利用する既存コード
  • 対応する要件
  • やってはいけないこと
  • 完了と判断する条件

たとえば、最初のタスクはNext.jsとOpenNextの依存関係を追加する作業です。

ただし、同時にVite版を削除することは禁止しました。まず両方を動かせる状態にし、Next.js版の検証が終わるまでVite版をロールバック手段として残すためです。

また、本番環境を変更するタスクには、実行直前に利用者の明示的な許可を得る条件も入りました。

単なるTODOリストではなく、要件と設計を実装時にも守るための指示書になっています。

前編のまとめ

今回は、SDDの練習として近況ノートのNext.js移行に取り組みました。

実装前に作ったものは、次の6文書です。

steering documents
  product.md
  tech.md
  structure.md

Next.js移行spec
  requirements.md
  design.md
  tasks.md

既存アプリを調査してプロジェクトの前提を整理し、移行要件、設計、21個の実装タスクへ順番に具体化しました。

ここまでの段階では、まだNext.jsの画面はほとんど作っていません。

それでも、守るべき機能、採用する構成、検証方法、ロールバック方法まで文章になっているため、実装中に判断がぶれにくい状態を作れました。

中編では、作成したタスクに沿って、Vite版を残したままNext.jsとOpenNextの構成を作り、各画面をServer ComponentとClient Componentへ分割していった過程をまとめます。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?