SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Next.jsの新しい概念を学ぶ

Next.jsの新常識「App Router」を学ぼう!

Next.jsの新しい概念を学ぶ 第1回

  • X ポスト
  • このエントリーをはてなブックマークに追加

はじめてのApp Router

 理屈の重さに反して、書き味はなかなか良いフレームワークに仕上がっておりますので、ここでひとつ、簡単なアプリケーションを作りながら、App Routerの基本的な使い方を体験してみましょう。

 題材として、ソーシャルニュースサイト「Hacker News」のJSON Web APIである、Hacker News APIからデータを取得して、画面に表示するWebサイトを作っていくことにしましょう。

 Hacker Newsの人気・最新の記事500件を取得できる /topstories.json というエンドポイントがあるのですが、500件は多すぎるので、このエンドポイントの上位20件を読める機能にしてみましょう(図2)。

図2:サンプルとして作成するアプリケーション
図2:サンプルとして作成するアプリケーション

 左サイドのメニューに記事の概要を表示して、右側のコンテンツ部に記事の詳細を出す形にします。

題材とするAPIの特性

 実は、このAPIは少し厄介な特性を持っています。「記事一覧」や「コメント一覧」といったデータを、リスト3のようなIDの配列として返してきます。

[リスト3]/topstories.json の戻り値
[ 36264744, 36265771, 36261411, 36256517, 36263349, ...]

 タイトルや本文を取得したい場合は、IDを使って /item/<id> のようにエンドポイントにアクセスすることで、該当の記事データやコメントデータを取得することになります。つまり、今回のように「上位20件の記事とそこに付随するコメントを読めるアプリ」を作る場合、次のような通信が必要になります。

 1. /topstories.json で500件分の記事IDを取得する

 2. 1の先頭20件分の記事IDを利用して、/item/<id> に20回アクセスして、左サイドメニューに表示するためのタイトルを入手する

 3. 記事のページを開くまでに、/item/<id> にアクセスして記事のタイトルや本文を取得する

 4. 記事データにはコメントIDのリストが含まれているので、コメントIDの1件ずつについて /item/<id> へのアクセスを行い、コメントデータを取得する(なおコメントの数は不定で、何回アクセスが発生するかはわからない)

 場合によっては1ページを開くだけで数十〜100回以上の通信が必要になることがお分かりいただけるでしょうか。ブラウザ上だけで動くアプリケーションとして実装するには、あまりにも過酷な条件ですが、App Routerを通じてサーバーの力を借りれば、ブラウザがアクセスするネットワークの負担を最小限にできます。

Next.jsプロジェクトをApp Router向けにセットアップする

 Next.jsのプロジェクトは create-next-app というCLIツールを使ってセットアップします。いくつか選択肢が出てきますが、リスト4を参考にしてください。

[リスト4]Next.jsプロジェクトをApp Router向けにセットアップする
$ npx create-next-app@latest
✔ What is your project named? … hackernews-app
✔ Would you like to use TypeScript with this project? … No
✔ Would you like to use ESLint with this project? … No
✔ Would you like to use Tailwind CSS with this project? … No
✔ Would you like to use src/ directory with this project? … No
✔ Use App Router (recommended)? … Yes
✔ Would you like to customize the default import alias? … No

 今回は次の選択肢を選びました。

  • アプリ名:hackernews-app
  • TypeScriptを利用しますか?:いいえ
  • ESLintを利用しますか?:いいえ
  • Tailwind CSSを利用しますか?:いいえ
  • src/ ディレクトリを利用しますか?:いいえ
  • App Routerを利用しますか?:はい
  • インポートのエイリアス機能をカスタマイズしますか?:いいえ

 サンプルとしての簡単さのために、App Routerを利用する以外の選択肢は「いいえ」で答えましたが、慣れていればTypeScriptやESLintは是非利用してください。

 しばらく待つと、セットアップが完了します。せっかくなので、一度起動してみましょう(リスト5)。

[リスト5]App Router製プロジェクトを起動する
$ cd hackernews-app
$ npm run dev

> hackernews-app@0.1.0 dev
> next dev

- ready started server on 0.0.0.0:3000, url: http://localhost:3000

 サーバーが起動したので、メッセージに表示された http://localhost:3000 にアクセスしてみましょう(図3)。

図3:App Routerで初期化したNext.jsプロジェクト
図3:App Routerで初期化したNext.jsプロジェクト

 チュートリアルや公式ドキュメントへのリンクが並んでいます。ひとまず、これで起動できることが確認できました。

pageとlayout

 ページをカスタマイズする前に、現状のappフォルダがどうなっているのかを確認しておきましょう(図4)。

図4:appフォルダの中身
図4:appフォルダの中身

 重要なファイルは2つだけで、ページを表す page.js と、それを囲むレイアウトを表す layout.js です。

 page.js には、そのフォルダ階層で表示すべきページが定義されています。app フォルダ内のフォルダ階層は、URL上のパスを表しており、その中に page.js という名前でファイルが定義されていると、そこからデフォルトエクスポートされたコンポーネントを画面に表示します。app/page.jsapp フォルダ内でいうとルートフォルダにあたるので、URLとしてはルート / のコンテンツを表すことになります。page.js というファイル名のファイルが存在しないフォルダ階層は、有効なルートとして認識されず、404ページが表示されます。

 同じように、ファイル名が重要なのが layout.js です。layout.js は各フォルダ階層で必須ではありませんが、配置することで、そのフォルダ階層以下の全てのページの外側に被さるコンポーネントを定義することができます。app/layout.js に定義したコンポーネントは、全てのパスの外側に被せられることになります。この説明だけだと分かりづらいかもしれないので、app/layout.js を見てみましょう(リスト6)。

[リスト6]app/layout.js
import './globals.css'
import { Inter } from 'next/font/google'

const inter = Inter({ subsets: ['latin'] })

export const metadata = {
  title: 'Create Next App',
  description: 'Generated by create next app',
}

export default function RootLayout({ children }) { // (1)
  return (
    <html lang="en">
      <body className={inter.className}>{children}</body>
    </html>
  )
}

 Webページにおいて、ルートパス( / )以下の全ての階層において、必ず表示されていてほしい、最も外側のコンポーネントといえば、そう、<html><body> ですね。App Routerでは、<html><body> を定義するための特別なコンポーネントを用意するのではなく、任意の階層の外側に被せるための layout.js という仕組みを使って、HTMLとしての外側を定義しています。

 layout.js が通常のコンポーネントと違う点は1つだけで、必ず children をレンダリングする必要があります。「外側に被せる」ための仕組みということで、「内側」になるページ実装が children として渡されてきます。children の実装を忘れると、pages.js の内容が表示されないので、忘れずに実装しましょう。

 改めて、図3で表示した初期状態のページについて、layout.jspage.js の関係を図示すると、図5のようになります。

図5:ルートフォルダでのpageとlayoutの関係
図5:ルートフォルダでのpageとlayoutの関係

 ルートフォルダのレイアウトには <html><body> しかないので、初期状態で目に見えている部分は、すべて page.js で実装されていることになります。今後扱う実装例の中では、目に見えるUIを持ったレイアウトについても扱っていくので、楽しみにしていてください。

次のページ
サーバーで取得したデータを画面に表示する

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
Next.jsの新しい概念を学ぶ連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 中川幸哉(ナカガワユキヤ)

WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/17925 2023/07/05 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング