2021/08/07

Next.jsチュートリアルをやってみる。

@ 酒井悠宇

Next.js

https://www.youtube.com/watch?v=F77RUjHZEAc&list=PLX8Rsrpnn3IUGEyanrHYGjY1WOzNe7Jd-
https://qiita.com/thesugar/items/01896c1faa8241e6b1bc

Next.jsのチュートリアルをやりながら、Next.jsがどんなものなのかを理解していけたらと思います。

Next.jsって何?

  1. SEOに強いSPA(シングルーページアプリケーション)開発
  2. パフォーマンスを効率化する仕組み
  3. ルーティングが楽
  4. APIの作成が簡単
  5. TypeScriptを簡単に導入できる。

以上のような特徴を持ったReactのフレームワーク。

今回は主にNext.jsのパフォーマンスを効率化する仕組みについて理解していけたらと思います。

とりあえずnpxでNext.jsのプロジェクトを作成します。

npx create-next-app nextjs-blog --use-npm --example "https://github.com/vercel/next-learn-starter/tree/master/navigate-between-pages-starter"


高速ページ遷移を体験する

Next.jsでは、pagesディレクトリ内のファイルからエクスポートされたReact Componentがページとなります。
ページは、そのファイル名に基づいてルートに関連付けられます。例えば、開発では、pages/index.jsは、' / 'ルートに関連付けられます。pages/posts/first-post.jsは、' /posts/first-post 'ルートに関連付けられています。


つまりNext.jsでは、pagesというディレクトリの構造がそのままそのページにアクセスする為のurlになるっぽいです。
スゲェでやんすね。

ページを作る

pages/postsに、first-post.jsというファイル( ページ )を作成したので、ここに遷移するためのロジックを作っていきたいと思います。

export default function FirstPost() {
  return <h1>First Post</h1>;
}


LinkComponent

通常Webサイトのページ間をリンクするときには、<a>というHTMLタグを使いますが、Next.jsでは、next/linkのLink Componentを使って、<a>タグをラップします。<Link>を使うと、クライアントサイドでアプリケーション内の別のページへのナビゲーションを行うことができます。


Linkコンポーネントは、以下のようにaタグをラッピングして使用します。
pages/index.js

<Link href="/posts/first-post"><a>this page!</a></Link>


pages/posts/first-post.jsにもホームに戻って来られるボタンを作成します。

import Link from "next/link";


export default function FirstPost() {
  return (
    <>
      <h1>First Post</h1>
      <h2>
        <Link href="/">
          <a>Back to home</a>
        </Link>
      </h2>
    </>
  );
}


爆速で遷移します。

Client-Side Navigation

クライアントサイド・ナビゲーションとは、JavaScriptを使ってページの遷移を行うことで、ブラウザが行うデフォルトのナビゲーションよりも高速に行うことができます。
Linkコンポーネントは、同じNext.jsアプリ内の2つのページ間のクライアントサイドナビゲーションを可能にします。


つまり、ユーザーのリクエスト(トップーページ見せて!とか、ニュース一覧見せて!とか )ごとに、それに対応したHTMLをファイルを返すのではなく、
javascriptによってHTMLを書き換えることでページ遷移しているように見せているようです。(クライアントサイドナビゲーション)

Code splitting

Next.jsは自動的にコード分割を行い、各ページはそのページに必要なものだけを読み込むようになっています。つまり、ホームページがレンダリングされるときに、他のページのコードが最初に提供されることはないのです。
これにより、何百ページものページがある場合でも、ホームページの読み込みが速くなります


これは気になっていましたが、画面描画に必要なコードだけを取り込んでくれるんですね。

prefetching

さらに、本番環境のNext.jsでは、ブラウザのビューポートにリンクコンポーネントが表示されると、Next.jsはバックグラウンドでリンク先のページのコードを自動的にプリフェッチします。ユーザーがリンクをクリックしたときには、リンク先のページのコードはすでにバックグラウンドで読み込まれており、ページの遷移はほぼ瞬時に行われます。


Linkコンポーネント内の要素から必要になるページのコードを予測して、それをあらかじめ裏側で読み込んでおくから、ボタンを押したら瞬時ページ遷移が行われるようです。夢のような機能ですね。
Linkコンポーネントを使わないと該当のページをprefetchingしてくれないようなのでボタンはLinkコンポーネントで作っておくのが吉ですね。

画像、メタデータ、そしてCSS

画像などの静的ファイルを使おう

Next.jsで画像ファイルを追加する際は、publicディレクトリ直下に画像ファイルを配置します。

パスはpublicをルートとしたルートパスで記述します。
例えば、publicディレクトリ直下にimgのディレクトリを作成して、その中にLogo.svg(画像ファイル)を配置したならば、以下のような書き方になります。

<img src="/img/logo.svg"/>


headタグのメタデータを編集しよう

Next.jsではHeadタグが用意されており、これをnext/headからインポートすることでメタデータを編集することができるようになります。
ページごとにメタデータを設定するとSEO的にいい感じらしいです。

import Head from 'next/head'


よく使う項目としては以下のような感じです。

<Head>
  #サイト/ページタイトル
  <title>Create Next App</title>
  #CSSやCDNの読み込み
  <link rel="icon" href="/favicon.ico" />
  <meta description="サイトページの説明(120時程度がOK)"/>
  <meta property="SNSシェア時にサイト/ページ情報を表示するOGPタグ"/>
</Head>


Next.jsのCSS


tailwindでしょ。

Pre-rendering と Data Fetching

Pre-renderingとは

Pre-renderingとは、事前にHTMLを生成することです。Next.jsはデフォルトで全ページをPre-renderしています。


通常のReactアプリケーション(create-react-appで作ったようなアプリケーション)はクライアントサイドレンダリングという方式になっています。
これは、ユーザーがwebページにアクセスして、今まさにwebページを表示しようとしているときに、ブラウザ側でHTMLを組み立てるという方式です。

対してPre-renderingは、ユーザーがwebページにアクセスする以前にHTMLを組み立ておく方式のことです。
なので結果的にブラウザの負荷を下げることに繋がり、表示を高速化することができるます。

この方式だと検索エンジンのクローラーにコンテンツを見せられるので、SEO的にも良いとされています。

クローラーとは、検索エンジン検索の順位を決めるための要素を、サイトから収集してくるロボットのこと

クローラーはそのサイトが現在データーの読み込みをしているしていないにかかわらず、画面のキャプチャみたいなの撮って判断するので、読み込みが遅いサイトだとコンテンツが何もないと判断されてSEO的に良くなかったりするみたいです。

2種類のPre-rendering

Next.jsniには、Static Generation と Server-side Renderingという2種類のPre-renderingが用意されています。
両者の違いは、HTMLファイルを生成するタイミングです。
・Static Generationは、ビルドした段階でHTMLを生成
・Server-side Renderingは、ユーザーがサイトにアクセスした時々で毎回HTMLを生成

Next.jsでは、この両者の方式をページごとに選択することができます。

Static Generationを使用する時

基本的には、Static Generationを使用することが推奨されています。
なぜならこの方式が最も表示速度が速くSEO的にも良いからです。
最適なページは、更新頻度が低いページです。具体的には以下のようなページです。
・ブログ
・ECサイト
・LP
・お問い合わせ

Server-side Renderingを使用する時

更新頻度が高いページを作成するときは、Server-Side Renderingが最適です。
なぜなら、ユーザーがアクセスする度に毎回最新のHTMLファイルが生成されるからです。
表示速度はStatic Generationの方が早いですが、ユーザーが常に最新の情報が見れるのはServer-side Renderingです。
具体的には以下のようなページです。
・SNS
・チャット
・動画配信

おまけ的にですが、クライアントサイドレンダリング(JavaScriptによってクライアントサイドでHTMLを書き換えていく方式)だと、SEO的にあまり良くないみたいです。なぜならこの方式は、Static GenerationやServer-Side RenderingのようにサーバーサイドでHTMLを構成するのではなく、クライアントサイドでHTMLを構成していくからです。クローラーにコンテンツを見せることができないので、コンテンツの少ないページであると判断されてしまいます。

create-react-appで作ったサイトは最初だけHTMLファイルが返されますが、それ以降はJavaScriptによるクライアントサイトレンダリングを行うので、差分描画によって高速には動作しますが、コンテンツが少ないとみなされ、SEO的にはあまりよろしくないということです。

データ有り/無しStatic Generation

Static Generationは以下静的ジェネレーションと略します。

静的ジェネレーションは、外部データが有るか無いかによって挙動が変わってきます。

外部データがないとき

ビルド時にレンダリングを行います。

外部データがあるとき

ビルド時にDBや外部APIからデータを取得してきて、その取得してきたデータを使用して、HTMLをレンダリングします。
このときに「getStaticProps()」を使用します。

getStaticPropsでデータを取得する

getStaticPropsの特徴

  • 外部データを取得するために使用する。
  • async/awaitを使って非同期処理を制御できる。
  • 本番環境ではビルド時に実行される関数
  • 開発環境ではリクエスト毎に実行される
  • pageコンポーネントでのみ使用可能(pageディレクトリ配下に作成したコンポーネントでのみ使用できる。)

本番環境でビルド時ではなくリクエストごとにデータを持ってきたい場合は、getServerSidePropsを使用する。

getServerSidePropsでデータを取得する

getServerSidePropsの特徴

  • リクエスト毎に実行される関数
  • Server-Side Renderringのために使う
  • 外部データを取得するために使う
  • async/awaitを使って非同期処理を制御できる
  • pageコンポーネントでのみ使用可能

内容が頻繁に変更されるデータはリクエストごとにデータが更新された方が良いので、そのようなときは、getStaticPropsではなく、getServersSidePropsを使用する。

まとめ

今回は主にNext.jsのパフォーマンスを効率化する仕組みについて学習していきました。
理解を深めるために簡単にまとめていきたいと思います。

  • Next.jsでページ遷移を実現する際は、<a>タグではなく、<Link>で<a>タグをラッピングして使用する。このLinkコンポーネントを使用することで、JavaScriptによってページ遷移を行うCliend-Side Navigationを実現することができる。
  • Next.jsでは、自動的にコード分割を行い、各ページはそのページに必要なものだけを読み込むようになっている(Code splitting)ので、何百というページがあったとしても、ホームページの読み込みの速度が遅くならない。
  • 本番環境でのNext.jsでは、ブラウザのビューポートにリンクコンポーネントが表示されると、バックグラウンドでリンク先のコンポーネントを自動的に読み込みます。(Prefetching)なので、ユーザーがリンクをクリックしたらページの遷移が瞬時に行われます。
  • Next.jsではHeadコンポーネントをimportすることでページごとにメタデータを編集することができます。
  • Next.jsではユーザーがwebページにアクセスする前にHTMLを構成(Pre-rendering)しています。ブラウザの負荷が下がり、表示が高速化します。
  • Pre-renderingには2種類あります。Static Generation と Server-side Renderingです。
  • Static Generationはビルドした段階でHTMLを生成します。更新が多いページには向きませんが、表示速度はこれが最速です。
  • Server-side Renderingはユーザーのリクエストごとに毎回HTMLを生成します。Static Generationよりは表示速度が遅いですが、更新の多いページには最適です。
  • Static Generationは外部データの有無によって挙動が変化します。
  • 外部データがないときはビルド時にHTMLのレンダリングを行います。
  • 外部データがあるときは、データを取得してからHTMLをレンダリングします。
  • Static Generationで外部データを取得する方法には、getStaticPropsを使用する方法と、getServerSidePropsを使用する方法があります。両者pageディレクトリ配下のコンポーネントでのみ使用可能です。async/awaitで非同期処理を制御します。
  • getStaticPropsは本番環境ではビルド時に実行されます。(開発環境ではリクエスト毎に実行)Static Generationを行いたい場合に使用します。
  • getServerSidePropsはリクエスト毎に実行されます。Server-Side Renderingを行いたい場合(内容が頻繁に更新されるデータを扱う場合)はこちらを使用します。


以上がNext.jsのパフォーマンスを効率化する仕組みです。
まぁなんとなくいい感じにわかったと思います。
最後までご覧いただきありがとうございました!

© 2021 powerd by UnReact