FrontEnd

Next.js 入門してみた

投稿日:

はじめに

Next.jsに入門して1週間で学んだことを記事にまとめます。

なぜNext.jsなのか?

今年は自分でも何か作ってみたいと思っているのですが、エンジニアとしてのテーマとして、経験したことのないフレームワークやプログラミング言語を取り入れたいと考えています。
とはいえ、領域から大きく外れすぎるとなかなか完成しないと思ったので、開発するものはWebアプリケーションとして、その中で新しい学びのある技術を選定する中で、フロントエンドにNext.jsを使いたいと思いました。
Reactでも良い気はしましたが、開発するとしたら、to C向けで、SNSの要素のあるサービスを開発したいと考えていて、その場合はSEOに強かったり、外部でシェアされる際にOGPが効くのもNext.js強みだと思ったため、とりあえずNext.jsを学んでみることにしました。

Next.jsとは何か

Next.jsは、ReactベースのWebフレームワークです。Reactを単体利用する場合との最大の違いは、ページをコンポーネントをSSRできるかどうかという点になります。
例えば、create-react-appで生成されたアプリケーションをビルドすると、生成されるHTMLはindex.htmlのみで、実際に表示されるDOMはすべてJavaScriptによって描画されます(SPA – Single Page APplication)。

かつてはRailsで構築されたWebアプリケーションのように、テンプレートエンジンがHTMLを生成するタイプのMPA(Multiple Page Application)が全盛の時代もありましたが、画面遷移するごとにページそのものが遷移するため、もっさり感がありました。
そこにSPAが登場することで、いちいちページ遷移することの煩わしさが解消されるようになりましたが、SPAはJavaScriptによってページが描画されるため、HTMLを静的解析するタイプのクローラに情報を提供することが難しいという問題がありました。

GoogleはSPAのページも読み取ってくれるようですが、TwitterやFacebookなどでOGPを設定するのは難しいようで、パブリックアクセスが必要となるニュースサイトやECサイトなどでは、導入が難しかったのではないかと思います。
そこで、Next.jsの強みは、ページが読み込まれたタイミングで、初期レンダリングされたHTMLをブラウザ側に返すことができる点です。これについて、Next.jsではいくつかのアプローチがあり、その概要を説明します。

Static Site Generation (SSG)

Next.jsのページは、デフォルトでビルド時にPre-renderされ、静的なHTMLファイルとして出力されます。レンダリングされる内容は、各ページのReactコンポーネントの初回レンダリングの内容になります。そのため、stateによって変化する内容については、含まれません。
これが一番シンプルなSSGなのですが、実際のコンテンツはAPIで取得するケースがほとんどではないかと思います。その場合は、ビルド時にAPIリクエストし、その内容をページのPropsの初期値として設定することができる getStaticProps を使用することで、外部リソースを含めてPre-renderすることができます。

さらに、Vercelが提供している useSWR というhookを組み合わせて、アクセス時にクライアント側で最新データをフェッチすることで、ビルド後も常に最新の状態を表示することができます。

Incremental Static Regeneration (ISR)

SSGによってPre-renderされるのは、Componentに埋め込んだ内容か、ビルド時にフェッチしたデータです。ビルド時より後に追加されたデータはPre-renderには含まれないため、SEOやOGPで不利であることは、CSRとほとんど変わりません。
そこで、ブラウザによりページアクセスがあった際に一旦は古いHTMLを返しつつ、前回のHTMLの生成から一定時間が経過している場合は、最新のデータを取得しなおした上でHTMLファイルを再生成することができるのが、ISRです。
これにより、最新のデータを含めるために再ビルドし直すことなく、SSGによるパフォーマンスやSEO・OGPなどの恩恵を受けることができます。ただし、ISRを使用している場合は、トリガーとなったページへのレスポンスや、HTML生成中のアクセスでは古いHTMLがレスポンスされるため、タイミングによっては整合性が取れなくなります。

Server Side Rendering (SSR)

ISRではタイミングによっては整合性が取れない場合がありますが、リクエスト毎に最新データを取得しつつ、サーバサイドでレンダリングすることでSEO・OGPに対応するには、どのようにすれば良いでしょうか。

そのような場合は、 getServerSideProps を使用します。この関数はページがリクエストされる毎にサーバサイドで実行され、この関数で返却されたPropsが渡された状態のコンポーネントがSSRされ、クライアントにレスポンスします。
あとは、SSGの時と同じように渡されたPropsをそのまま使ってコンポーネントを生成すれば、静的なHTMLとしてレスポンスされるため、SEO・OGPに対応することができます。

実際にNext.jsをセットアップ

Next.jsを特徴が分かってきたところで、実際にNext.jsを使ったアプリケーションを作ってみたいと思います。

create-next-app

create-next-app を使用すると、次のように対話形式でセットアップすることができます。

後半2つの質問はNext.js特有のものになります。

Would you like to use src/ directory with this project?

ここまで説明していなかったのですが、Next.jsではpagesディレクトリ配下の構成がそのままRoutingのパスとして解釈されます。デフォルトでは、pagesディレクトリはプロジェクトのルートに存在する必要があるのですが、これを src/pages に変更できるオプションです。
デフォルトではNoになっているため、私も今回はNoを選択しましたが、もしかしたらソースコードはsrcディレクトリの中にまとめてしまった方が、ルートがスッキリしてわかりやすくなるかもしれません。

Would you like to use experimental app/ directory with this project?

Next.js 13で追加されたapp directoryを使用するかどうかです。現時点ではベータ版の機能です。app directoryを使用しない、従来のNext.jsでは、コンポーネントの初回レンダリングの結果をHTMLとしてレスポンスし、その後はクライアント側でCSRが行われるという流れが1つのコンポーネントで完結できていました。
app directoryを使用した場合は、コンポーネントをServer SideとClient Sideに明確に分けるようになります。デフォルトではServer Sideで、Client Sideにする場合はファイルの先頭に use client とする必要があります。

Server Sideコンポーネントの場合は、これまで通りサーバサイドでレンダリングされ、これまで通りデータフェッチは可能ですが、stateやイベントハンドリングといったインタラクティブなことはできません。そのような部分はClient Sideとして実装する必要があるのですが、Client Sideコンポーネントはサーバ側ではレンダリングできません。

このような明確な分け方をすることにより、SSRした時のパフォーマンスが向上するとのことですが、実装時にはServer SideとClient Sideを上手く使い分ける必要がありそうです。
Next.jsのドキュメントに使い分けの例があるので、こちらを参考にした方が良さそうです。
https://beta.nextjs.org/docs/rendering/server-and-client-components

今回は、app directoryを使用しないことにしました。その理由は、MUIが未対応であるからです。
https://github.com/mui/material-ui/issues/34896

MUIほどの人気パッケージでさえ未対応なので、app directoryは正式版になるまで待っても遅くはないかなと思い、今回は使用しないことにしました。

nextの起動

yarn dev でnextアプリケーションを起動することができます。その他のコマンドは、以下がpacakge.jsonに定義されていました。

ちなみに、 dev で立ち上げた場合は、ページにアクセスされる毎に getStaticProps が呼び出されますが、 yarn build でプロダクション用のビルドをすると、ビルド時に取得したHTMLが使用されるようになります。

さいごに

次回も引き続き学んだ内容を記事にしていきたいと思います!

おすすめ書籍

TypeScriptとReact/Next.jsでつくる実践Webアプリケーション開発 Reactハンズオンラーニング 第2版 ―Webアプリケーション開発のベストプラクティス プログラミングTypeScript ―スケールするJavaScriptアプリケーション開発

blog-page_footer_336




blog-page_footer_336




-FrontEnd
-, ,

執筆者:


comment

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA


関連記事

AMPに対応してモバイルページを高速に表示させる

1 はじめに2 AMPとは3 なぜAMPでは高速に表示されるのか3.1 非同期スクリプトのみを許可3.2 リソース読み込みに優先度を付ける3.3 プリレンダリング4 AMPの3要素4.1 AMP HT ...

react-icon

React QueryのSuspese Modeを使ってみた! [TypeScript]

1 はじめに2 React Suspenseとは3 React QueryのSuspense Mode3.1 事前準備3.2 Suspenseモードの有効化3.3 データをフェッチするコンポーネントの ...

laravel logo

Inertia使ってみた①

1 はじめに2 Inertiaとは3 ルーティング4 LaravelからReactに値渡し5 レスポンス5.1 初回5.2 page object5.3 2回目以降5.4 リロード時6 さいごに7 お ...

js

TypeScriptでJavaScriptのライブラリを使用するには?

1 はじめに2 対応方法2.1 npmで@typesからインストールする2.2 自分で型定義ファイルを作る3 Declaration Space3.1 Type Declaration Space3. ...

Vue.js入門その6〜RouterとComponentを使ってTODOアプリを修正〜

1 はじめに2 vue-routerのインストール3 サーバーサイドの改修3.1 APIに詳細(show)を追加3.2 元となるビューファイルを作成3.3 ルーティングの修正4 Vue.jsの実装4. ...

フォロー

blog-page_side_responsive

2023年1月
1234567
891011121314
15161718192021
22232425262728
293031  

アプリ情報

私たちは無料アプリもリリースしています、ぜひご覧ください。 下記のアイコンから無料でダウンロードできます。