目次

はじめに
本書の目的と対象読者について
サーバーサイドレンダリングについて
サンプルコードについて
免責
表記関係について
第1章 ゼロからのWebアプリ開発
1.1 Nuxtについて
1.2 ローカル開発環境の構築
1.3 Webページを作ってみよう
1.4 まとめ
第2章 ハイドレーション
2.1 ハイドレーションエラーを回避せよ
2.2 ハイドレーションを観測しよう
2.3 ハイドレーションエラーを発生させる
2.4 ハイドレーションエラーを解消する
2.5 その他のハイドレーションエラーの原因
2.6 まとめ
第3章 データ取得と状態管理
3.1 いい感じにデータを取得せよ
3.2 APIからのデータ取得
3.3 データ取得処理を検証しよう
3.4 同期データの取得処理
3.5 まとめ
第4章 Webアプリケーションを公開する
4.1 サーバーを調達せよ
4.2 デプロイの準備
4.3 デプロイ
4.4 プロジェクトの削除
4.5 まとめ

はじめに

本書の目的と対象読者について

 『はじめてのSSR Hands-on』を手にとっていただきありがとうございます。この本は、タイトルを見て「そろそろ私もサーバーサイドレンダリングの概要くらいは理解しておかなきゃ...」と感じたエンジニアに、簡単なハンズオンを通じてサーバーサイドレンダリングの基礎を身につけてもらうために書かれた本です。


 サーバーサイドレンダリングはWebアプリケーション開発の基本となる技術になりつつあります。一方で、「サーバーサイドレンダリングがどのような仕組みで実現されているか」とか、「アプリケーション実装時にどんなところに気をつけるべきか」みたいな話ができる人はそれほど多くありません。残念ですが、「知っている人が整えてくれたコードベースに乗っかって、見様見真似でなんとか動くものを作っている」「サーバーサイドレンダリング何もわからない」というエンジニアのほうが多数派です。

 大局的に見れば、それ自体は悪いことではありません。高度な知識がなくても動くアプリケーションが作れるということは、フレームワークやライブラリーがWeb開発の複雑さを隠蔽しようとする努力が実っていることの証左でもあります。コミュニティーの裾野を広げるという意味では非常に重要なことです。

 これからもそんなに短くはない間、JavaScriptはWebブラウザーにおいて主流のプログラミング言語であり続けるでしょう。そして、そうである限りWeb開発者はJavaScriptフレームワークを避けては通れません。たとえバックエンド開発をメインの担当とするエンジニアであっても、フロントエンド開発者がどんなところに気を使って開発しているのかを知らなければ、質の高いコードを書くことは難しくなります。


 この本では、とりわけ初学者がサーバーサイドレンダリングを理解する上でつまずきがちなハイドレーションとアプリケーションの状態管理というふたつのトピックを中心に扱います。本書のハンズオンに取り組むことによって、現代のWebアプリケーション開発に求められる基本的なお作法の一端くらいは獲得できるはずです。少しでもサーバーサイドレンダリングへの苦手意識を克服したり、Web開発の深淵へと一歩踏み出すきっかけになれば幸いです。

サーバーサイドレンダリングについて

 本題に入る前に、サーバーサイドレンダリングについて軽くおさらいしておきましょう。


 サーバーサイドレンダリング(SSR)とは、サーバーサイドでプログラムを実行してHTMLを生成し、レスポンスに乗せてクライアントに返す一連のプロセスを指します。対になる概念としてクライアントサイドレンダリング(CSR)がありますが、こちらはブラウザー上でJavaScriptを実行してHTMLを生成する方法です。

 SSRを採用したWebアプリケーションが実際にSSRを行うのはユーザーからの最初のリクエストに対してのみです。一度SSRが済んでしまえば、Webサイト内のページ遷移は普通のシングルページアプリケーションと同様にCSRを行います。つまり、実質的にSSRはCSRとのハイブリッドということになります。したがって、SSRとCSRは対立する概念というよりも、SSRがCSRの延長線上にあるものと考えたほうがしっくりくるのではないかとおもいます。

なぜサーバーサイドレンダリングが必要なのか

 SSRが必要な理由を調べると、いくつかの理由を見つけることができます。その中でも最もよく言われるものはSEO対策ではないでしょうか。最近のクローラーはCSRのWebサイトでも頑張ってJavaScriptの実行結果を解釈しようとしてくれるようですが、さまざまな制約がついてまわります。そのため、安定した結果が得られるようにしようと思ったらSSRを採用することになります。著しい発達を見せるAIの台頭によりいつまで検索エンジンが現在の地位を維持できるかという点に関して疑問はありますが、仮にAIが検索エンジンに取って代わったとしてもクローリングの仕組みがすぐに変わることを期待するのはやや無理がありそうです。


 ソーシャルメディア向けのOGP設定も、SEOと同様に対策を怠ってはならないもののひとつです。マーケティング手法としてのSNSへのシェアは年を追うごとに重要度を増しており、顧客の心に刺さるOGPを設定することはもはや当たり前といっていいでしょう。もしOGPのメタタグを動的に生成しようとするのであれば、SSRは欠かせない技術となります。


 これらふたつよりはやや弱い主張になりますが、SSRはCSRにくらべてパフォーマンスに優れるといわれています。正直なところ性能面だけでSSRを採用すべきと結論づけるほどの決定的な差があるとはあまり思いませんが、いざパフォーマンスチューニングが必要となったときにはSSRを採用しておいたほうが打てる手の候補は多そうです。

広義のサーバーサイドレンダリング

 広義には、Ruby on RailsやLaravelのようなサーバーサイド中心のフルスタックフレームワークを用いる方式もSSRと呼ぶことができます(そう呼ばれているところはあまり見かけませんが)。ただし、モダンなWebアプリケーションで要求されるダイナミックなUIを実現するにはやはりブラウザー上でプログラムを実行できるJavaScriptのサポートが必要不可欠であり、これらのフレームワークを採用する場合はVueやReact(もう少し古ければjquery)のようなライブラリーを併用することになります。

 このような「サーバーサイドフレームワークのテンプレートエンジンを用いたSSR+JavaScriptフレームワークによるダイナミックなUI」という技術スタックはいまでも多くのWebアプリケーションで採用されていますが、プレゼンテーションに関するコードがバックエンドとフロントエンド(JavaScript)に分散してしまう、つまり、関心の分離ができていないという欠点を抱えています。本書で紹介するNuxtのような、いわゆるユニバーサルJavaScriptフレームワークはこの問題を解消することを大きな目標のひとつとして発展してきました。これらのフレームワークはサーバーサイドとクライアントサイドの両方で同一のコードを用いてWebページをレンダリングすることによって、『関心の分離』の問題を解決しようとしています。

サーバーサイドレンダリングへの期待

 現代のWebアプリケーション開発で「サーバーサイドレンダリング」と言った場合、それは単にサーバーサイドでHTMLを出力すればいいということではありません。SSRを採用するということはすなわち、次に挙げるような要求が暗黙的に存在していることになります。

 ・SSRとCSRを同一のコードで処理すること

 ・CSRを採用したアプリケーションと少なくとも同等か、それ以上のパフォーマンスを発揮すること

 ・SSRがどのようなものかを理解し、SSR固有の技術的課題をクリアすること

 本書で紹介するNuxtのようなユニバーサルJavaScriptフレームワークの登場により、同一のコードでSSRとCSRを行うこと自体はそれほど難しくはなくなりました。また、パフォーマンスについても原始的な部分についてはフレームワークやエコシステムのサポートを受けられるため、特別な事情がない限りはフレームワークの作法に従うことで標準的な最適化が行われます。


 さて、最後に残ったSSR固有の技術的課題にはどんなものがあるでしょうか。筆者はその代表的なものが本書でフォーカスする「ハイドレーション」と「状態管理」であろうと考えています。SSRの方式が劇的に変わらない限り、このふたつはどんなフレームワークを採用するにしてもクリアしなければならない課題となります。

サンプルコードについて

 本書ではWebアプリケーションフレームワークとしてNuxtを使用して説明しますが、これは筆者の知識の限界とエゴによる選択の結果にすぎません。読者の皆様には、NuxtだとかNextだとか細かい話にこだわるのではなく、サーバーサイドレンダリングという一段階抽象度の高いトピックを理解することに注力してほしいと願っています。したがって、なるべく平易なサンプルコードを用いてNuxt(あるいはVue)に依存した話はできる限り避け、Vueになじみがない方でも十分に理解できるように配慮したつもりです。


 本書の執筆時に使用した主要なライブラリーのバージョンを表1に示します。

表1: ライブラリーとバージョン
ライブラリー バージョン
nuxt 3.4.3
@nuxt/devtools 0.4.6
node 18.16.0
firebase-tools 12.0.0

 また、本書で紹介している各ハンズオンの内容はNode.jsのパッケージマネージャーであるnpmがインストールされていることを前提としています。ここから先を読み進める前に、あらかじめnpmをインストールしておいてください。

免責

 本書は情報の提供のみを目的としています。本書に記載されている内容は筆者個人の執筆時点での知見に基づくものであり、所属する組織の見解ではありません。また、情報の正確性を保証するものでもありません。本書に記載されている内容を実行して発生したいかなる結果に関しても責任は負いかねます。

表記関係について

 本書に記載されている会社名、製品名などは、一般に各社の登録商標または商標、商品名です。会社名、製品名については、本文中では©、®、™マークなどは表示していません。

第1章 ゼロからのWebアプリ開発

それではさっそくサーバーサイドレンダリングをやってみましょう!……というのはやや勇み足かと思います。まずはウォーミングアップを兼ねて、Nuxtアプリケーションをローカル環境で開発・動作させることに慣れるところからはじめましょう。第1章ではサーバーサイドレンダリングのことは一旦脇に置いておいて、Nuxtとその基本的な開発方法について解説します。

1.1 Nuxtについて

 Nuxtは、フロントエンドフレームワークのVueとその周辺のライブラリーを組み合わせて構成されたWebアプリケーションフレームワークです。ユーザーインターフェースを構築するためのVueに加えて、ルーティング(ページ遷移)を制御するVue Routerや、サーバーエンジンのnitro、サーバーサイドレンダリングを扱うためNuxt独自のコンポーザブル(composables)を追加した、Webアプリケーションを構築するために必要な要素をひとつのパッケージに統合したフレームワークです。


 筆者の個人的な感想になりますが、Nuxtは結構主張の強いフレームワークであると言えます。標準となるディレクトリー構成や自動インポートの仕組みなど、プロジェクト全体の構成に関わる細かな規約が複数存在しており、これに沿って開発することで高い生産性を得ることができます。

 ただし、そういったルールの意図を理解するには一定の経験値が必要です。特に他のフレームワークに慣れている方だと、単に制約の強い(あるいは面倒くさい)フレームワークだなと感じるかもしれません。しかし、Nuxtの規約はこれまでの数々のVueプロジェクトの経験から導き出されたベストプラクティス集でもあります。先人が積み重ねた苦労の恩恵にあずかる意味でも、素直にNuxtの思想に従ってみるのも悪い選択ではないと思います。

 良いか悪いかは別として、これらの規約の存在によりプロジェクトのセットアップ時点で頭を悩ませることはほとんどなく、スムーズにアプリケーション開発を始められる点はNuxtの強みと言えるでしょう。本書では扱いませんが、必要であれば設定により規約を変更することもできますし、モジュールシステムによる高い拡張性も備えているため、おおよそどんなWebアプリケーションの開発にも安心して採用できるフレームワークです。読者の皆様には、このハンズオンを通じてNuxtの提供する優れた開発体験を感じていただければ幸いです。

1.2 ローカル開発環境の構築

 Nuxtがどんなものかをあらかた把握したところで、ローカル開発環境の構築に入りましょう。

1.2.1 Nuxtプロジェクトのセットアップ

 まずはじめにターミナルを開き、適当な作業用ディレクトリーでnpx nuxi initコマンドを実行してNuxtプロジェクトの雛形を生成します。nuxiは、Nuxtプロジェクトを管理するためのコマンドラインツールです。npmリポジトリーに登録されているため、npxを通じて事前準備なしに実行することができます。

 Nuxtのインストール

$ npx nuxi init shiodaifuku

 このコマンド中のshiodaifukuはサンプルのNuxtプロジェクト名です。読者の皆さんはご自分の好きな名前を利用していただいて構いません。

 コマンドを実行すると、リスト1.1のようなログが出力されます。指定したプロジェクト名と同じ名前のディレクトリーが作成され、その中にNuxtアプリケーションの実行に必要なファイル一式が生成されます。

リスト1.1: Nuxtプロジェクトの初期化

i cloned nuxt/starter#v3 to /Users/hecateball/Workspace/shiodaifuku

 🎉  Another peachy Nuxt project just made! Next steps:

     📁  `cd shiodaifuku`

     💿  Install dependencies with `npm install` or `yarn install`

     🚀  Start development server with `npm run dev` or `yarn dev`

 このステップで生成されるファイルは、リスト1.2のようになります。

リスト1.2: 生成されるファイルの一覧

shiodaifuku
├ README.md
├ app.vue
├ nuxt.config.ts
├ package.json
├ public
│ └ favicon.ico
└ tsconfig.json

 ログの出力に従い、Nuxtプロジェクトのルートディレクトリーに移動して、依存モジュールをインストールしましょう。

 依存モジュールのインストール

$ cd shiodaifuku

$ npm install

 CLIを通じて生成されたpackage.jsonには、postinstallのスクリプトがあらかじめ登録されています。npm installを実行すると、完了後にpostinstallに指定されているnuxt prepareが自動的に実行されます。nuxt prepareは、Nuxtアプリケーションが利用する自動インポートの型定義を生成するコマンドです。IDEやCI環境などでインポートをうまく解決するために必要になります。


 これで準備完了です。引き続きnuxi initのログ出力に沿って、アプリケーションを動かしてみましょう。developmentモードでアプリケーションを実行するコマンドはnpm run devです。

 アプリケーションの実行

$ npm run dev

リスト1.3: 出力

Nuxi 3.4.3
Nuxt 3.4.3 with Nitro 2.4.0

  > Local:    http://localhost:3000/
  > Network:  http://192.168.1.3:3000/
  > Network:  http://[240d:1a:5d9:ba00:405:8786:611d:161a]:3000/
  > Network:  http://[240d:1a:5d9:ba00:5cc5:bd4d:91c5:e34a]:3000/
  > Network:  http://[240d:1a:5d9:ba00:81d2:61b4:5ae9:5869]:3000/
  > Network:  http://[240d:1a:5d9:ba00:8c10:79f5:6749:8204]:3000/
  > Network:  http://[240d:1a:5d9:ba00:9439:7ce:759e:e251]:3000/
  > Network:  http://[240d:1a:5d9:ba00:9e2:808c:4e3f:ef98]:3000/
  > Network:  http://[240d:1a:5d9:ba00:bde6:61f3:36f3:424d]:3000/
  > Network:  http://[240d:1a:5d9:ba00:e9a5:3649:c547:4387]:3000/

i Vite client warmed up in 705ms
  Nitro built in 251 ms

 http://localhost:3000/にアクセスしてみましょう。図1.1のようなウェルカムページが表示されていたら成功です。

図1.1: ウェルカムページ

1.2.2 devtoolsの有効化

 Nuxtでは、devtoolsという開発者向けのツールが提供されています。執筆時点では実験的な機能という扱いになっていますが、Nuxtが隠蔽しているアプリケーション内部の状態を可視化することができる便利なツールです。このステップの実行は必須ではありませんが、よりよい開発者体験を得るためにdevtoolsを有効にして開発を行うことを強くおすすめします。

 devtoolsを有効化するには、nuxt.config.ts1をエディターで開き、リスト1.4のように修正します。

リスト1.4: ~/nuxt.config.ts

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  devtools: { enabled: true }
})

 修正できたら、npm run devコマンドでアプリケーションを実行します。

 アプリケーションの実行(再)

$ npm run dev

 設定変更後に初めてアプリケーションを実行する際に、@nuxt/devtoolsパッケージをインストールすることを確認するプロンプトが表示されます。ここでyesを入力すると、devtoolsのダウンロードが始まります。そのまましばらく待っていると、devtoolsが有効化された状態でアプリケーションが実行されます。

リスト1.5: 出力

Nuxi 3.4.3
Nuxt 3.4.3 with Nitro 2.4.0
i Package @nuxt/devtools is missing

? Do you want to install @nuxt/devtools package? › (Y/n)

  Do you want to install @nuxt/devtools package? … yes


i Installing @nuxt/devtools...
npm WARN deprecated @npmcli/move-file@2.0.1: This functionality has been moved to @npmcli/fs

added 239 packages, and audited 867 packages in 22s

135 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
  Installed @nuxt/devtools

  > Local:    http://localhost:3000/
  > Network:  http://192.168.1.3:3000/
  > Network:  http://[240d:1a:5d9:ba00:1c14:96d4:d48d:cc85]:3000/
  > Network:  http://[240d:1a:5d9:ba00:4037:1880:48d6:d919]:3000/
  > Network:  http://[240d:1a:5d9:ba00:405:8786:611d:161a]:3000/
  > Network:  http://[240d:1a:5d9:ba00:798b:4473:f696:6966]:3000/
  > Network:  http://[240d:1a:5d9:ba00:84d3:9252:7729:78fa]:3000/
  > Network:  http://[240d:1a:5d9:ba00:8c21:d31c:19:1851]:3000/
  > Network:  http://[240d:1a:5d9:ba00:a5a2:f01a:717c:1a40]:3000/
  > Network:  http://[240d:1a:5d9:ba00:ed90:a8cf:656a:dedf]:3000/
  > Network:  http://[fda1:ff44:4fbc:4bef:85d:93dd:1d70:bb05]:3000/

  Nuxt Devtools is enabled v0.4.6 (experimental)
i Vite client warmed up in 587ms
  Nitro built in 282 ms

 アプリケーションが起動したら、再度ブラウザーでhttp://localhost:3000/にアクセスしてみましょう。無事にdevtoolsが有効になっていれば、画面中央の一番下に下部にNuxtのロゴマークが入った半円形のボタンが表示されます。このボタンを押すと、devtoolsを開いたり閉じたりできます。

図1.2: devtoolsを開いた状態

1.3 Webページを作ってみよう

 ここまでの手順は順調でしょうか。すべて成功していれば、Nuxtのセットアップは完了です。いよいよ最初のページを作ってみるときがやってきました。

1.3.1 インデックスページを作成する

 新しいページを作成するときは、ページを表示するためのVueコンポーネントをプロジェクトに追加します。まず初めに、インデックスページを作成しましょう。

 新しくコンポーネントを作りたいときは、nuxi addコマンドを使用します。プロジェクトのルートディレクトリーで次のコマンドを実行してください。

 indexページを作成する

$ npx nuxi add page index

リスト1.6: 実行結果

Nuxi 3.4.3
i Creating directory /Users/hecateball/Workspace/shiodaifuku/pages
i This enables vue-router functionality!
i 🪄 Generated a new page in /Users/hecateball/Workspace/shiodaifuku/pages/index. vue

 pagesディレクトリーと、その中にindex.vueという名前のVueコンポーネントファイルが作成されます。Nuxtではファイルベースのルーティングシステムを採用しており、pagesディレクトリー内の構造がそのままルートとして登録されます。

 単にページを表示するだけならこのままでもいいのですが、少し寂しいので見出しと簡単な文章をおいてみましょう。

 index.vueの中身をリスト1.7のように書き換えてください。

リスト1.7: ~/pages/index.vue

<script lang="ts" setup></script>

<template>
  <div>
    Page: foo
    <h1>はじめてのSSR Hands-on</h1>
    <p>Hello, world!</p>
  </div>
</template>

<style scoped></style>

 これで、インデックスページを表示するためのコンポーネントが準備できました。

 nuxi addコマンドは使い方をぜひ覚えておきましょう。一度ヘルプを参照してみることを強くおすすめします。新しいページだけでなく、一般のVueコンポーネントやプラグイン、ミドルウェアなどNuxtでアプリケーションを開発する際によく作成するファイルは、大抵このコマンドでテンプレートを出力できます。

 続いて、作成したインデックスページを表示するための修正を行います。Nuxtでは、ルートディレクトリーに配置されているapp.vueという名前のVueコンポーネントが最初に呼び出されます。

 app.vueをエディターで開いてみましょう。Nuxtをセットアップした状態では、<NuxtWelcome>というコンポーネントが表示されるようになっています。このコンポーネントが最初に動作確認したときに見たウェルカムページを出力しています。

 pagesディレクトリー内に作成したページを表示するためには、<NuxtPage>コンポーネントを使います。ウェルカムページの中央に書いてあったGet startedの導きに従い、app.vueのtemplate部分をリスト1.8のように書き換えましょう。

リスト1.8: ~/app.vue

<template>
  <div>
    <NuxtWelcome />
  </div>
  <NuxtPage />
</template>

1.3.2 コンポーネントを作成する

 技術的なメリットはほとんどありませんが、細かいことは気にせず練習のためにインデックスページの一部をコンポーネントとして分割してみましょう。これから行うコンポーネント分割はあくまでハンズオンの一環です。なんでもかんでもコンポーネントに分割していると、先輩エンジニアに怒られてしまいますので気をつけて。


 nuxi addコマンドを使って、コンポーネントファイルを作成します。今度は通常のコンポーネントを作成するため、最初のパラメータはcomponentになるところに注意してください。

$ npx nuxi add component HelloWorld

 componentsディレクトリーが作成され、その中にHelloWorld.vueというファイルが作成されます。このファイルの中身はリスト1.9のようになります。このハンズオンの手順ではこのまま使用することにしますが、内容を適当に修正していただいても差し支えありません。

リスト1.9: ~/components/HelloWorld.vue

<script lang="ts" setup></script>

<template>
  <div>
    Component: HelloWorld
  </div>
</template>

<style scoped></style>

 このコンポーネントを先程作ったインデックスページに表示しましょう。~/pages/index.vueファイルを開き、テキスト部分をコンポーネントに置き換えます。

リスト1.10: ~/pages/index.vue

<script lang="ts" setup></script>

<template>
  <div>
    <h1>はじめてのSSR Hands-on</h1>
    <p>Hello world!</p>
    <HelloWorld />
  </div>
</template>

<style scoped></style>

自動インポート

 親切なIDEなどはscript部にインポート文を書き出してくれるかもしれませんが、HelloWorldコンポーネントのインポートを書く必要はありません。Nuxtでは、既定のディレクトリー構成に従って配置されているVueコンポーネントやコンポーザブルを自動でインポートします。

 「コンポーネントの名前はどうなるんだろう?」とお気づきの方は、優れた感性ををお持ちです。コンポーネント名は、ファイルが置かれているパスとファイル名を繋いでキャメルケースにしたものになります。自動インポートを駆使しながら可読性の高いコードを書くには、極めて高いネーミングセンスが要求されるため、実際の開発現場では自動インポートに頼る機会は少ないかもしれません。

 一気に進めてきましたが、ここで動作確認をしておきましょう。npm run devでアプリケーションを実行し、ブラウザーで表示を確認します。図1.3のようなページが出力されていれば、順調に進んでいます。

図1.3: indexページ

1.3.3 レイアウトを適用する

 第2章以降では、ページをさらに追加していきます。ナビゲーションを用意して、ページ間の遷移がスムーズにできるようにしておきましょう2

 このナビゲーションは、今後追加するどのページにも設置したいものになります。Nuxtでは、複数のページに共通のコンポーネントを配置する際にはレイアウト機能を使います。

 これまでと同様に、コマンドラインツールを使ってレイアウトを追加します。今度はレイアウトを作成するので、最初のパラメータはlayoutです。レイアウトの名前はdefaultとします。

$ npx nuxi add layout default

 defaultレイアウトはその名の通り、アプリケーションのデフォルトレイアウトとなります。明示的にレイアウトを指定していないページにレイアウトを適用するとき、デフォルトレイアウトが選択されます。

 さて、作成された~/layouts/default.vueをエディターで開き、ページ上部にナビゲーションを表示する簡単なロジックを追加しましょう。せっかくレイアウトを用意するので、ヘッダとページタイトルもレイアウト内に置くことにします。

リスト1.11: ~/layouts/default.vue

<script setup lang="ts">
const router = useRouter()
const routes = router.getRoutes()
</script>

<template>
  <div>
    <header>
      <h1>はじめてのSSR Hands-on</h1>
    </header>
    <aside>
      <h2>メニュー</h2>
      <nav>
        <ul>
          <li v-for="route in routes">
            <NuxtLink :to="route">{{ route.name }}</NuxtLink>
          </li>
        </ul>
      </nav>
    </aside>
    <main>
      <!-- このスロット部分がページコンポーネントに置き換わります -->
      <slot />
    </main>
  </div>
</template>

 レイアウトを適用するためには、<NuxtLayout>コンポーネントが必要です。~/app.vueをエディターで開き、<NuxtPage>を<NuxtLayout>で囲みます。

リスト1.12: ~/app.vue

<template>
  <NuxtLayout>
    <NuxtPage />
  </NuxtLayout>
</template>

 <h1>はレイアウトに移動したので、インデックスページのコンポーネント内の見出しは<h2>に変更しましょう。どんなときでも適切なセマンティックのHTMLを書くことが重要です。内容は何でもいいのですが、ここではルートの名前を表示することにします。

リスト1.13: ~/pages/index.vue

<script lang="ts" setup></script>

<template>
  <div>
    <h1>はじめてのSSR Hands-on</h1>
    <h2>{{ $route.name }}</h2>
    <HelloWorld />
  </div>
</template>

<style scoped></style>

 修正後のインデックスページは、図1.4のようになります。

図1.4: レイアウト適用後のindexページ

 これ以降、ページコンポーネントにはレイアウトの<main>部分に表示されるコンテンツのみを記述します。

1.3.4 クラスレスCSSでデザインを整える

 本書ではCSSを用いたスタイリングについては扱いませんが、何もスタイルを当てないとページの見栄えがちょっとよくないですね。ここでは簡単に見た目の体裁を整えることができる、Water.css3というクラスレスCSSを適用してみましょう。

 Nuxtでアプリケーション全体にCSSを適用するには、nuxt.config.tsに設定を記述します。すべてのページを対象として<head>タグ内に<link>タグを出力するための設定は、app.head.linkセクションに記述します。ここに、Water.cssが配信されているCDNのURLを指定します。

リスト1.14: ~/nuxt.config.ts

// https://nuxt.com/docs/api/configuration/nuxt-config
export default defineNuxtConfig({
  devtools: { enabled: true },
  app: {
    head: {
      link: [
        {
          rel: 'stylesheet',
          href: 'https://cdn.jsdelivr.net/npm/water.css@2/out/light.css'
        }
      ]
    }
  }
})

 さて、改めて動作を確認してみましょう。ローカル環境でアプリケーションを動作する際に使うコマンドは、npm run devです。アプリケーションが起動したら、ブラウザーでhttp://localhost:3000にアクセスしてみましょう。図1.5のような画面が表示されていれば成功です。

図1.5: CSSを適用したインデックスページ

 CSS適用前の図1.4と比べてみると、すこしシュッとしたのがわかると思います。

1.4 まとめ

 第1章では、Nuxtプロジェクトをセットアップしてローカル環境で実行する方法と、コンポーネントやレイアウトの基本的な作成方法について学習しました。スムーズにできたでしょうか?


 モダンなWebフレームワークのおかげで、プロジェクトのセットアップから最初にアプリケーションを実行するまでの手順は劇的にシンプルになりましたが、依然としてこのステップを恐れるエンジニアは少なくありません。ゼロからWebアプリ開発を始める経験は今後も必ず役に立つので、この章の内容は呼吸をするようにできるようになるまで復習しておいてください。すべての手順を暗記する必要はありませんが、「こういうことをしたいときはここを見ればいいんだ」というアタリがつけられるようになっておくことは非常に重要です。

1. nuxt.config.tsはNuxtアプリケーション全体の設定ファイルです。

2. 聡明な読者の中にはdevtoolsにページ遷移の機能があることに気づいている方もいらっしゃるかもしれませんが、気づいていないフリをしてお付き合いください。

3. https://watercss.kognise.dev/

試し読みはここまでです。
この続きは、製品版でお楽しみください。