[初学者向け] Next.js で開発を始める前に知っておきたいポイントと開発方法
想定読者
- Next.js に触れたことがあまりない人
- ちょっとした使い方を知りたい人
執筆同時のNext.js
- next: v12.3.2
Next.js とは
Next.js は、Vercel 社が提供する React フレームワークである。
なぜ、Next.js を使うのか
現在のフロントエンド開発において、React を始めとするフレームワークやライブラリは選択肢の1つとなっている。しかし、単独で React を使った場合、ルーティングやサーバーサイドレンダリング、パフォーマンスなどの面で課題が出てくる。
Next.js は React をより使いやすくするために開発されたフレームワークであり、以下のようなフロントエンド開発のベストプラクティスを特徴として持っており、この恩恵を開発の初期段階から享受できる。
- ゼロコンフィグ
ゼロコンフィグであるため、開発者は煩雑な環境設定などを行う必要がない - ファイルベースルーティング
ルーティングの設定が非常に簡単でページの追加や変更が容易 - 事前レンダリング
ページの初期表示を高速化できるため、ユーザーエクスペリエンスの向上にも繋がる - 画像やフォントの最適化
パフォーマンスの向上も期待できる
以上のように、Next.js は開発において多くの課題を解決するフレームワークであり、今後のフロントエンドの開発においても重要な選択肢となるだろう。
セットアップ
Next.js は執筆時点での最新バージョン v12.1.6
を想定。
手動でセットアップも可能だが、体系的に Next.js を学ぶのを目的とするため自動セットアップを利用する。
任意のディレクトリに移動して、下記のコマンドを実行する。コマンドを実行したディレクトリに任意のディレクトリ名(後述の「プロジェクト名」)で Next.js をインストールしたディレクトリが作成される。
npx create-next-app@latest --typescript --use-npm
--use-npm
を付けないと yarn でセットアップが行われる。こちらは環境に応じて任意でつける。
上記のコマンドを実行すると以下の流れで Next.js のインストールが行われる。
- 下記のように訊かれたら、
y
を入力Need to install the following packages: create-next-app@latest Ok to proceed? (y)
- プロジェクト名を訊かれるので、任意のプロジェクト名を入力
✔ What is your project named?
- 作成されたファイル一覧
. ├── .eslintrc.json ├── .gitignore ├── .next ├── README.md ├── next-env.d.ts ├── next.config.js ├── package-lock.json ├── package.json ├── pages │ ├── _app.tsx │ ├── about.js │ ├── api │ │ └── hello.ts │ └── index.tsx ├── public │ ├── favicon.ico │ └── vercel.svg ├── styles │ ├── Home.module.css │ └── globals.css └── tsconfig.json
基本的な開発手順
- 下記のコマンドを実行し、開発サーバを起動する
(他のコマンドについては割愛)npm run dev
- 開発サーバ起動後、
http://localhost:3000
でアプリケーションの実行を確認
(デフォルトの設定だとポートは3000
)
![](https://user-images.githubusercontent.com/3617124/171777342-d9fdec1f-ac60-4622-8add-a807d2073edf.png)
ファイルベースルーティング
pages
ディレクトリ内に配置した React コンポーネント(.js
,.jsx
,.ts
,.tsx
ファイル)によって、ルーティングが決定する。
例えば、以下のような React コンポーネントを pages/about.js
というファイルで配置すると、/about
へとアクセスできるようになる。ディレクトリを任意の名称にして、index を配置する形(pages/about/index.js
)でも同様の動きになる。
// pages/about.js
const About = () => {
return <div>About</div>;
};
export default About;
インデックスルート
index
というファイルは、ルートとしてルーティングされる。
pages/index.jsx
→/
pages/about.jsx
pages/about/index.js
→/about
ネストされたルート
ネストされたディレクトリ構造も同じようにルーティングされる。
pages/posts/first-post.jsx
→/posts/first-post
pages/dashboard/settings/username.jsx
→/dashboard/settings/username
事前レンダリング(プリレンダリング)とは
Next.js には、SSR(Server-side Rendering)と SG(Static Generation)の 2 つの事前レンダリング形式がある。
事前レンダリングとは、各ページの HTML をクライアントサイドの JavaScript でレンダリングするのではなく、サーバサイドの JavaScript で事前に生成しておくことを指す。
これらの違いは、ページの HTML を生成するタイミングにある。
- SG(Static Generation): ビルド時に HTML を生成する
- SSR(Server-side Rendering): リクエストごとに HTML を生成する
事前レンダリングなし
![事前レンダリングなし](https://user-images.githubusercontent.com/3617124/172182390-164cd2c9-3373-4690-9742-d33fb6a24f70.png)
事前レンダリングがない場合、クライアントサイドで HTML を生成するため、JavaScript によるレンダリングが完了するまでコンテンツを見ることができない。また、JavaScript が無効化された状態では見ることが出来ない。
事前レンダリングあり
![事前レンダリング(Next.js利用時)](https://user-images.githubusercontent.com/3617124/172182469-dac44d43-ffbf-4ead-8fb9-1730b40481bd.png)
事前レンダリングの場合、事前に HTML は生成されたものをクライアントサイドはレンダリングする。生成された HTML は JavaScript と関連付けられており、ページが読み込まれた後に JavaScript は実行され、アプリケーションはインタラクティブになる。このプロセスはハイドレーション(Hydration)と呼ばれる。
SG: Static Generation / SSG: Static-site Generation
SG(Static Generation)は、ビルド時に HTML を生成する事前レンダリング方式。
![Static Generation](https://user-images.githubusercontent.com/3617124/172182559-67560a19-ff32-4ca5-9771-6b2bc8cadf35.png)
We recommend using Static Generation (with and without data) whenever possible because your page can be built once and served by CDN, which makes it much faster than having a server render the page on every request.
https://nextjs.org/learn/basics/data-fetching/two-forms
ちなみに Next.js は、パフォーマンスの観点から可能な限り SG を使用することを推奨している。
Next.js での利用方法
pages ディレクトリ内のコンポーネントでgetStaticProps()
を利用する。
export async function getStaticProps(context) {
return {
props: {}, // ページコンポーネントに props として渡す
};
}
以下はBlog
コンポーネントのデータを SG 時に API 経由でセットするケース。
// この関数はサーバーサイドのビルド時(Node.js)に呼び出される
// ブラウザ上ではなく Node.js で実行されるので DOM などへのアクセスはできない
export async function getStaticProps() {
const res = await fetch("https://.../posts");
const posts = await res.json();
// `props: { posts }` を返すことで
// Blog コンポーネントはビルド時に `posts` を `props` として受け取れる
return {
props: {
posts,
},
};
}
// `posts` は、ビルド時に `getStaticProps()` で取得した値が設定される
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
);
}
export default Blog;
いつ使うべきか
- ページをレンダリングするのに必要なデータが、ビルド時にユーザーのリクエストよりも先に利用可能である場合
- データをヘッドレス CMS や API から取得する場合
- データがユーザー固有のものでなく public にキャッシュできる場合
- SEO などの理由でページを事前レンダリングする必要があり、かつ非常に高速でなければならない場合
SSR: Server-side Rendering
SSR(Server-side Rendering)は、ユーザのリクエストごとに HTML をサーバー側で生成する事前レンダリング方式。
![Server-side Rendering](https://user-images.githubusercontent.com/3617124/172182642-eddec195-4772-4e27-a11c-74f922d0249f.png)
Next.js での利用方法
pages ディレクトリ内のコンポーネントでgetServerSideProps
を利用する。
export async function getServerSideProps(context) {
return {
props: {}, // ページコンポーネントに props として渡す
};
}
以下はBlog
コンポーネントのデータを SSR でセットするケース。
// この関数はサーバーサイドのリクエスト時(Node.js)に呼び出される
// ブラウザ上ではなく Node.js で実行されるので DOM などへのアクセスはできない
export async function getServerSideProps(context) {
const res = await fetch("https://.../posts");
const posts = await res.json();
// `props: { posts }` を返すことで
// Blog コンポーネントはリクエスト時に `posts` を `props` として受け取れる
return {
props: {
posts,
},
};
}
// `posts` は、リクエスト時に `getServerSideProps()` で取得した値が設定される
function Blog({ posts }) {
return (
<ul>
{posts.map((post) => (
<li>{post.title}</li>
))}
</ul>
);
}
export default Blog;
いつ使うべきか
- クエリパラメータで動的にデータが変わるページ
- HTTP ヘッダーを必要とするページ
参考
- Create a Next.js App | Learn Next.js
- Pre-rendering - Pre-rendering and Data Fetching pre-rendering | Learn Next.js
- Pre-rendering - Pre-rendering and Data Fetching two-forms | Learn Next.js
WIP