###### tags: `Next.js` # Next.js 概要 ## 目次 * Next.jsとは * Next.jsのメリット * デフォルト環境構築 * ディレクトリ構成 * 基本知識 * 基本機能 **概要がまとめられている記事** https://qiita.com/Yuki_Oshima/items/5c0dfd8f7af8fb76af8f ## Next.jsとは Reactをベースとしたフレームワークです。 2016年にZEIT社(ツァイト社)がリリースし、2020年にVercelに社名を変更。 Vercel社はデプロイ・ホスティングサービスとして「Vercel」も運営しています。 Next.jsとVercelを合わせて利用することで、簡単にハイパフォーマンスなWebサイトが作れます。 **公式サイト** https://nextjs.org **非公式日本語訳サイト** https://nextjs-ja-translation-docs.vercel.app/ ### Reactとは JavaScriptのライブラリ Facebook社が開発したWebサイト上のUIパーツを構築するためのJavaScriptライブラリで、Yahoo!やNetflixにも導入されています。 #### Reactの特徴 - CSR(Client Side Rendering) - ユーザーからのリクエスト時に空のHTMLファイルをサーバーが返し、ブラウザ側がjsを実行してレンダリングを行う。 - 大規模サイトになるとjsの処理量が膨大になるため、初回レンダリングが遅くなる。 - ページを更新する際、全体を更新せずに変更箇所のみを更新するため高速表示が可能。 - SEO的に不利になるという説もある。(空のHTMLをクローラーが認識できずに不利になる?最近は改善されているという説もある。) - コンポーネントベース wordpressやpugのようにファイルを分割するイメージ - 部分導入が可能 コンテンツの一部にだけ導入することができるので、柔軟な対応が可能 - スマホアプリが作れる ReactをマスターすればReact Nativeという開発用フレームワークでスマホアプリを作れるようになる。 ### Next.jsで使えるSSRとSSGについて Next.jsで扱える機能。 **SSR(Server Side Rendering)** * リクエスト時にサーバー側でHTMLを生成して表示するので、CSRと比較してSEO的に不利になることはない。 * SSRは(CSRも)リクエストがあってからHTMLファイルを生成するため、規模が大きくなればなるほど初回レンダリングが遅くなる。 * ユーザーのリクエストなしではPre-rendering(ファイル生成)できないページ、最新状態を維持する必要があるページに向いている。(SNSのタイムライン・Twitterなど) **SSG(Static Site Generator)** * ビルド時にHTMLファイルを生成する。 * 予め生成しておいたHTMLファイルを返すため、SSRに比べて高速表示が可能。 * 予め生成したファイルを返す関係上、ビルド後にデータを変更することができないので、頻繁にページを更新するようなサイトには向かない。 * 事前に生成したファイルをクライアント側で表示させているので、常に最新の情報が表示されている訳ではない。 > SSGのデメリットをある程度解消できる(かもしれない)手段にISRがあります。 > ISR(Incremental Static Regeneration)は、ページに有効期限を設けて、有効期限が切れたあとの次の1回のリクエストはとりあえず古いファイルを返し、裏側でページを再ビルドしておく。 ### SSRとSSGの使い方 ページ単位で自由にSSRとSSGを切り替えることができる。 **SSR** `getServerSideProps`を使用する ```jsx // SSRを使うとき import { GetServerSideProps } from "next"; export const getServerSideProps = async () => {         //処理を書く }; ``` **SSG** `getStaticProps`を使用する ```jsx // SSGを使うとき import { GetStaticProps } from 'next' export const getStaticProps = async() => {         //処理を書く } ----------------------------------------------------------- //ISRを使うとき // revalidate: 秒数の指定でISRの挙動をするようになる。 // 15秒間はキャッシュを返す。15秒後の次のリクエスト時もキャッシュを返すが、 // そのリクエストをトリガーに裏側でページを再生成しておく。 import { GetStaticProps } from 'next' export const getStaticProps = async() => {         //処理を書く return { props, revalidate: 15 }; } ``` **参考記事** https://zenn.dev/mo_ri_regen/articles/implement-ssg-article https://maku.blog/p/iv4agnt/ ## Next.jsのメリット * SSR/SSG - Reactでは標準で扱えないがNext.jsだと使えるようになる! - Next.jsではページ単位で自由にSSRとSSGを切り替えることができる。 * ファイルベースルーティング Reactでページを作成するのはちょっと大変。。 →Next.jsでは、ファイルを所定のディレクトリに作成するだけでページを作成できる! * 画像最適化 遅延読み込みやレスポンシブ対応が容易になる * zero-config デフォルトの設定が充実している ## デフォルト環境構築 **next.jsの環境作成手順** プロジェクトを置きたいディレクトリに移動してから 下記のコマンドを実行(`node16.13.0`で動作確認) ```shell= yarn create next-app ``` TypeScript環境で作成するときは後ろに`--ts`をつける。 ```shell= yarn create next-app --ts ``` 上記を実行するとプロジェクト名を設定できるので、任意のプロジェクト名を入力する ``` shell= ? What is your project named? > learn-next ``` 以上でデフォルト環境が作成できました。 ### その他コマンド **yarn dev** 開発環境立ち上げ **yarn build** 本番用に最適化されたファイルを作成 **yarn start** 本番用に作成したファイルを立ち上げ ## ディレクトリ構成 * publicディレクトリは、必ずNext.jsプロジェクトのルートディレクトリに配置する必要がある。 * publicディレクトリ以下に配置したファイルは、ルートパス(/)からの相対パスで参照できるようになる。 * pagesディレクトリ内に`ページ名.jsx`を作成することでページを追加することができる。 * Next.jsのv9.1からsrcディレクトリの配下にpagesディレクトリを格納できるようになった。 ```js //デフォルト構成 sample-app ├── node_modules ├── public # 画像など静的ファイルなど格納、パスを指定する場合ドメイン直下で参照できる │ ├── vercel.svg │ └── favicon.ico ├── pages │ ├── api │ ├── _app.js   # globalなcssなど読み込む │ └── index.js # ファイルを増やすことでページを追加できる ex)about/jsx→/aboutが生成 ├── styles ├── package.json ├── README.md ├── next.config.js └──  yarn.lock ``` ```js //Next.jsチームの構成 sample2-app ├── node_modules ├── public │ ├── vercel.svg │ └── favicon.ico ├── src │ ├── components │ │ ├── layouts │ │ └── modules │ ├── pages │ │ ├── api │ │ ├── _app.js │ │ └── index.js │ └── styles ├── package.json ├── README.md ├── next.config.js └──  yarn.lock ``` ## 基本知識 ### js、jsxの違いについて Reactのrenderで用いるhtmlのようなxmlマークアップのことをjsxと呼ぶ js(ts)だとエディタがReactのファイルだと認識しない jsxを使用していないファイルはjsにしておくなど、後から見て判別できるようにしておくと良い ### React.Fragmentについて Next.jsではコンポーネントを作成して、作成したコンポーネントを集めてリターン(ページを表示)させます。 リターン内は一つの要素しか渡せないが、React.Fragmentでラップすることで複数の要素を渡せるようになる。 ```jsx const Home: NextPage = () => { return ( <Header /> <Wrap> <Side /> <Main /> </Wrap> <Footer /> ); }; ``` これだとエラーが出てしまうので、 ```jsx const Home: NextPage = () => { return ( <React.Fragment> <Header /> <Wrap> <Side /> <Main /> </Wrap> <Footer /> </React.Fragment> ); }; ``` このようにする。 * Fragmentを使用するときは、reactライブラリからインポートする必要がある。(後述するショートハンドではインポート不要) * 一つの要素でラップされていれば何を使用しても良いが、不必要なタグが発生する可能性があるので、状況に応じて使い分ける * 並列で構成したいときなどに有用 * ショートハンド`<></>`で記述することもできる <!-- * が、keyを使うことができないので注意(map関数などで利用) --> ## 基本機能 ### Nextコンポーネントについて #### Linkコンポーネントについて - `Link` コンポーネントがブラウザのビューポートに表示されると、自動的にリンク先のページのコードをバックグラウンドでプリフェッチする(作成したNext.jsアプリ内に限る) - よりSEOを気にかけ、semantic htmlを崩さないようにするために`Link`の中に`<a>`を入れる - 作成したNext.jsアプリ外へのリンク(外部リンク)のときは`<a>`のみを利用 - className といった属性を加える必要があるときは、`Link` コンポーネントでなく、`<a>`に加える ```jsx import Link from "next/link"; //importして使う <Link href="about"><a className={hoge}>About</a></Link> ``` ブラウザに表示されるときは下記の形式で表示されます。 ```jsx <a href="/about" class="hoge">About</a> ``` #### Imageコンポーネントについて * 遅延読み込み (Lazy loading) * 画像の最適化 PNGやJPEGなどの形式の画像を自動でWebPにしてくれる(WebP対応ブラウザのみ) 画像をデバイスに応じてリサイズ表示してくれる * レスポンシブ 画像に`width` `height`を指定していても、レスポンシブ対応してくれる。 ```jsx import Image from 'next/image'//importして使う <Image src="/examle.jpg" width={400} height={200} /> ``` 指定必須のProps * src * width * height ※`width` `height`を指定しない方法もあるが、パフォーマンスの観点から指定した方がよい。 **Imageコンポーネントについての記事** https://zenn.dev/catnose99/articles/883f7dbbe21632a5254e ### コンポーネント間の値の受け渡し 例)各ページのタイトルを表示 * `Pagetitle`コンポーネントを呼び出す * それぞれのタイトルを設定(`title`に格納) * 呼び出し元のコンポーネント(`Pagetitle`)で`props`を定義 * 設定した`title`を呼び出す ```jsx // Aboutコンポーネントファイル const About: NextPage = () => { return ( <Pagetitle title="About" /> //ここの「About」を渡す ); }; // Blogコンポーネントファイル const Blog: NextPage = () => { return ( <Pagetitle title="Blog" /> //ここの「Blog」を渡す ); }; // Pagetitleコンポーネントファイル // propsの型指定 type props = { title?: string; }; export const Pagetitle: React.FC<props> = ({ title }) => { return ( <Head> <title>{title}</title>//ここに「About」「Blog」を受ける </Head> ); }; ``` ### React hooksについて Reactの state やライフサイクルの機能などを、コンポーネント内に使用できるようにするための関数です。 ライフサイクルは代表的なものに * マウント(ブラウザでjsxがDOMになるときのこと) * アンマウント(コンポーネントが何かしらの処理で消えてしまうこと) などがあります。 React hooksは * useState * useEffect * useCallback * useRef 等がある。(他にもたくさんあります) #### useState 関数コンポーネントでstate(状態)を管理するための機能です。 (コンポーネントの中で変数を扱うことができる機能) ```jsx import { useState } from "react";//reactのuseStateをimport // 基本形 const [state(変数), setState(メソッド)] = useState(初期値); // 下記はcountが変数でsetCountメソッドを使ってcountの値を変更(更新)する const [count, setCount] = useState(0) <button onClick={() => setCount(count + 1)}> 1増やす </button> ``` >コンポーネントのsetCountで更新したらブラウザ上にも反映されるのが不思議だと感じる人もいるかもしれません。即座に反映されるのはuseStateで変数の値を更新する度にコンポーネントが再実行され、ブラウザ上で変数の再描写が行われているためです。ReactではuseStateによる変数の更新だけではなくpropsが更新されてもコンポーネントの再描写が行われるということを理解しておく必要があります。再描写を行う仕組みがない場合はstateを更新しても最新の情報がブラウザに表示されることはありません。 #### useEffect(レンダリング時の処理) ```jsx import { useEffect } from "react";//reactのuseEffectをimport     useEffect(() => { document.body.style.backgroundColor = "lightblue"; //マウント時の処理 return () => { document.body.style.backgroundColor = ""; } // アンマウント時の処理 }, [])//空配列を指定することで初回レンダリング時のみ動作 ``` `useEffect`の使いどき * レンダリングが行われたタイミングで処理を実行できる。(デフォルトではレンダリングされる度に毎回動作するが、第二引数に配列を与えることで、特定の値が変化した時のみ動作させることができる。) * 初回レンダリング時のみ処理を実行する。(配列を空にする。) * 特定のstateの更新による再レンダリングのタイミングで処理を実行する。 <!-- linaria(css-in-js)を利用するなら入れておきたいvscode拡張機能 「Vscode-styled-components」 補完が効くようになったり、シンタックスハイライトがついたりとめちゃくちゃ便利です! →補完に少しクセがあるので触って慣れる必要がある ex)df→display: flex; がdf→dfnと出てきたりする。 -->