✍️

Next.jsバックエンド 初心者向けハンズオン資料

2023/09/24に公開

はじめに

この記事は,とある初心者向けハッカソンのバックエンド開発ハンズオンの教材補足用の資料になります.このハッカソン参加者に限らず,Next.jsを用いて初めてバックエンド開発する人の教材としても使用できるような内容となっていますが,もし利用される場合はあくまで一学生が作成したものであることを把握した上で,参考程度に活用してください.(記.2023/9/24,改.2024/8/25)

前提条件

  • Node.jsの環境構築が完了している
  • JavaScript/TypeScriptについて基本的な文法を理解している

事前準備

こちらのレポジトリをクローンし,READMEに従って環境構築を行い,起動できることを確認してください.
Dockerのインストールが必要になります.環境によってはアカウントの作成が必要かもしれません.

教材の内容

新規投稿・投稿の編集・投稿の削除ができるごくシンプルな掲示板アプリです.新規投稿などの操作の後の画面の更新にはページの再読み込みが必要です.
ひな形だけ作成してあるページと実際に動くサンプルページがあり,フロントエンドはどちらも既に完成しています.
/pages/api/sample/posts.tsにサンプルページ用の完成版APIがあり,これを見ながら/pages/api/posts.tsのAPIを完成させてもらうという教材になっています.(ひな形だけ既に用意されています.)

必要となる知識

基本的な用語

  • リクエスト: フロントエンドからバックエンドへの通信のこと.必要に応じてQueryやBodyなどに値を格納する.
  • レスポンス: バックエンドからフロントエンドへの通信のこと.リクエストに対する返答.Bodyに値やその他の情報を格納する.
  • Query: http://localhost:3000/api/hoge?id=1のようなURL(Google検索なんかで見たことあるはず)の?より後ろの部分.URLに情報を付加することができ,アクセスされた先でその情報を取り出すことができる.
  • Body: リクエストやレスポンスに付加するJsonデータ.アクセスされた先でその情報を取り出すことができる.QueryではURLが長くなってしまう場合やセキュリティ的に問題がある場合に使用される.
  • Json: 構造体のような雰囲気のデータ形式の一種.長くなるのでこちらの記事を参照
  • メソッド: 下記参照
  • HTTPステータスコード: 下記参照

メソッドについて

フロントエンドからバックエンドにリクエストを送ってデータベースなどの情報を取得する際,そのリクエストの種類を指定するためのものです.よく使われるものとして

  • POST: 新規作成.ユーザー登録や記事の投稿など,一から新しくデータを作成する時に使用される.
  • GET: 既に存在するデータの取得.プロフィールの取得やタイムラインの取得など,データベースの内容を取得するときに使用される.全件取得とidなどで指定する一件取得の両方が実装されることが多い.場合によってはタグ検索など絞り込み取得などが実装されることもある.
  • PUT: 既に存在するデータの編集.プロフィールや記事の編集など,既にPOSTやPUTされた内容を更新する時に使用される.
  • DELETE: 既に存在するデータの削除.ユーザーの退会や記事の削除など,データベースからデータを削除する時に使用される.DELETEされるとそのデータはGETやPUTができなくなる.

の4つがあります.情報を渡す際,格納場所としてGETとDELETEではQueryを,POSTとPUTではBodyを使用します.
他にPATCHやOPTIONSなどのあまり使わないメソッドも存在しますが,このハッカソンで使用することはまず無いため,ここでは扱いません.

HTTPステータスコードについて

送られてきたリクエストに対してバックエンドからフロントエンドにレスポンスを返す際,そのリクエストに対する返答の種類を指定するためのものです.よく使うものとして,

  • 200 OK: リクエストが正しく,バックエンドでの処理も正常に実行され,レスポンスに返すべき内容が含まれている状態.200を返す場合はレスポンスのBodyに返すべき内容が含まれていることを保証する必要がある.
  • 500 Internal Server Error: バックエンドで何かしらのエラーが起きている状態.これだけでは何が起きているかフロントエンドからは全く分からないため,別途レスポンスのBodyでエラーメッセージなどを返す必要がある.
  • 400 Bad Request: リクエストに含まれるべき値が不足している,もしくは正常でない状態.何が不足しているかをレスポンスのBodyに含める.
  • 404 Not Found: ページが見つかりませんでおなじみ404だが,API開発においてはデータベースの中に要求されたデータが存在しない場合に使用される.

などがあります.200番台は正常,400番台はフロントエンド側に問題があるエラー,500番台はバックエンド側に問題があるエラーということを理解しておけばとりあえずは問題ありません.他のステータスコードはここに載っているので余裕があれば目を通してみてください.

便利なツールの紹介

起動・インストール方法や使い方についてはレポジトリのREADMEに記載しています.

  • Prisma Studio: ブラウザからデータベースの中身を見ることができるツール.データをの作成,編集,削除も可能.
  • Postman: GUIでバックエンドへのリクエストを送ることができるツール.もちろんQueryやBody,メソッドも設定できるのでバックエンドだけ完成した時点で正しく動いているかどうかのテストにとても便利.

演習

/pages/api/sample/posts.tsを見ながら/pages/api/posts.tsを完成させてください.コード内にコメントがかなり丁寧に書かれているので参考にしてください.それかChatGPTなどのAIに聞いてください.
どの関数,どの命令が何を実行しており,どこを消せば何が動かなくなるのかを確かめながら書くと理解が深まると思います.何も分からなければ写経のように書き写すだけでも構いませんが,コピペは避けてください.
POSTの場合は

    case 'POST':
      // まだ実装されていないため,NotImplementedを返している
      res.status(501).json({ message: 'this method is not implemented' })
      break

の部分を

    case 'POST':
      // リクエストの中のcontentを取得
      const newContent = await req.body.content
      // contentが存在しない場合,BadRequestを返す
      if (newContent == null) {
        res.status(400).json({ message: 'content is required' })
        break
      }
      // contentが空文字列の場合,BadRequestを返す
      if (newContent === '') {
        res.status(400).json({ message: 'content is empty' })
        break
      }
      // データベースに新しい投稿を作成
      try {
        const newPost = await prisma.posts.create({
          data: {
            content: newContent,
          }
        })
        // 作成に成功した場合,作成した投稿を返す
        res.status(200).json(newPost)
        break
      } catch(error) {
        // データベースの接続エラーなどで作成できなかった場合,InternalServerErrorを返す
        res.status(500).json({ message: error })
        break
      }

のように完成させてください.GET,PUT,DELETEも同様です.
Prisma StudioやPostmanを使用して動作を確認しながら書くと分かりやすいと思います.
Prismaを使用してデータベースを操作するコードについては公式ドキュメントを参照してください.英語だからといって目を逸らしたりせずに読んでください.新しくSQLとかいう別の文法覚えるよりははるかに楽なので.
初めてのハッカソンでここまでしっかりエラーハンドリングする必要があるかと言われるとなんとも言えませんが,フロントエンドからはバックエンドの中身が見えないため,レスポンスではできるだけ多くの情報を返してあげると良いです.

応用課題

時間が余った人向けの課題です.掲示板で本文だけでなく名前も表示できるようにしてみてください.
なお,今回はバックエンドのハンズオンのため,React/Next.jsの文法については解説を行いません.fetchについてはこの記事が丁寧で分かりやすいです.

ヒント

  • prisma/schema.prismaを編集し,データベースに名前も保存できるようにする必要があります.
  • /pages/api/posts.tsのそれぞれのメソッドを編集し,contentと一緒に名前も保存・取得する必要があります.
  • /pages/index.tsxで投稿を取得する際,components/PostForm.tsxで新規投稿を作成する際,/components/PostItem.tsxで投稿を編集・削除する際に名前もfetchする必要があります.
  • 同様に,fetchで取得した名前を表示したり,名前を入力・編集するためのテキストボックスを用意する必要があります.

Discussion