「Reactは習得できたからNext.jsを触ってみたい」
「Next.jsを勉強しているけど古い記事だとコマンドやコードが違うため扱えない」
「Next.jsを使いたいけどインストールの時点でよくわからないエラーに当たる」
本日はそんな方に向けてNext.jsの最新バージョン14のインストール方法を解説していきます。
最新のWeb開発のフレームワークであるNext.jsはその柔軟性と効率性において、ますます注目を集めています。
特にバージョン14では多くの新機能や改善点が導入され、開発者にとってより魅力的な選択肢となっています。
この記事ではNext.jsの最新バージョンである14をインストールから解説し、その新機能や変更点を詳しく掘り下げていきます。
次世代のWebアプリケーション開発における最先端のツールとテクノロジーを取り入れるために、本記事を通じてNext.jsの最新版を理解し活用する手助けを行います。
最新のNext.js14のインストール手順
Next.js14についてはまだ使用していない会社が多くあるかもしれませんが、新しい機能が搭載されているので順次アップデートされていく見込みです。
本記事の執筆日時点で公式サイトではNode.jsのバージョンを18.17以上にすることを求めています。
https://nextjs.org/docs/getting-started/installation
試しに18.00と少し下げたバージョンのNode.jsがインストールされた状態でNext.jsのインストールコマンドを実行してもインストールはできてもローカルサーバーが立ち上がりませんでした。
ご自身のNode.jsのバージョンを確認の方法はターミナルで以下のコマンドを打って返ってくる数字を確認します。
また「Not Found」などが表示された場合はそもそもNode.jsがパソコン上にインストールされていないことになります。
node -v
初めてインストールする、アップグレードされる方は以下のサイトより手順を確認しましょう。
Node.jsが新しいバージョンでインストールされている状態になれば、Next.jsのインストールコマンドを任意のディレクトリで実行します。
npx create-next-app@latest
こちらのコマンドで初期設定のための質問が何点かターミナル上で表示されるので「yes」「no」をスペースキーで選択してエンターキーを押していきます。
今回はTypeScript込みでNext.jsを使用しますので以下の回答にしました。
What is your project named?
→next-demoと入力してEnter
Would you like to use TypeScript? No / Yes
→Yesを選択してEnter
Would you like to use ESLint? No / Yes
→Yesを選択してEnter
Would you like to use Tailwind CSS? No / Yes
→Yesを選択してEnter
Would you like to use `src/` directory? No / Yes
→Yesを選択してEnter
Would you like to use App Router? (recommended) No / Yes
→Yesを選択してEnter
Would you like to customize the default import alias (@/*)? No / Yes
→Noを選択してEnter
全ての回答が終わるとインストールが開始されますので3分程度待ちます。
インストールが完了すると上記の一番最初の質問で入力したキーワード名でフォルダが作成されます。
作成されたフォルダまでcdコマンドで移動しましょう。
本記事では「next-demo」というフォルダが作成されましたので以下のように実行します。
cd next-demo
Reactと同じくNext.jsではローカルサーバーでブラウザ表示ができますので以下のコマンドを実行します。
npm run dev
そうすると以下のようなターミナルになるので「http://localhost」から始まるURLをブラウザで立ち上げます。
上図の場合だと「http://localhost:3000」をブラウザで立ち上げると画面が表示されます。
画面にも表示されていますがNext.jsは/src/app/page.tsxがトップページとして使用されます。
そのためpage.tsxの中身を以下のように変えてみます。
import React from 'react';
const page = () => {
return <div>page</div>;import React from 'react';
const page = () => {
return <div>page</div>;
};
export default page;
};
export default page;
そうすると画面の状態は以下のように切り替わることが確認できます。
Next.js14におけるルーティングのやり方
Next.jsのルーティングの特徴としては、ブラウザでアクセスできるURLはファイルとフォルダの階層によって決定される点です。
すべてのルートは「/src/app」フォルダ内に配置するのが大前提のルールとしてあります。
またファイル名はTypeScriptなら「page.tsx」、JavaScriptのみであれば「page.jsx」とすることになっています。
下層ページについては「/src/app」以下の各フォルダ名がURLのクエリに対応しています。
以下のようなディレクトリ構成を作ってみます。
src
|-app
|-about
| |-page.tsx
|
|-contact
| |-page.tsx
|
|-page.tsx
|-layout.tsx
「/src/app/page.tsx」「/src/app/layouy.tsx」はすでにあるので、「/src/app/about/page.tsx」「/src/app/contact/page.tsx」を新しく追加します。
import React from 'react';
const page = () => {
return <div>About</div>;
};
export default page;
import React from 'react';
const page = () => {
return <div>contact</div>;
};
export default page;
ここまでの状態でブラウザの状態を確認してみると「http://localhost:3000」は以下のトップページです。
つづいて「http://localhost/about」にアクセスするとページが変わります。
さらに「http://localhost/contact」にアクセスするとさらにページが切り替わります。
ちなみに存在しないディレクトリ名をURLのクエリにすると自動的に404ページのような扱いになります。
例えば「http://localhost:3000/xxxxx」としてみると以下のようになるはずです。
本来であれば404ページになるページを「NotFound.tsx」のようにファイルを作成してコーディングしておく必要があるはずですが、Next.jsでは自動的にファイルが生成される仕組みになっています。
先ほど紹介したディレクトリ構成でルーティングが動作する仕組みと併せてルール化された仕様になっているのです。
ちなみにオリジナルの404ページを作成したいときは「/src/app/not-found.tsx」というファイルを作成すると自動的にnot-found.tsxで作成された内容が404ページに差し替えられます。
ファイル名は固定ですので注意してください。
import React from 'react';
const NotFound = () => {
return <div>お探しのページはありません。</div>;
};
export default NotFound;
Next.js14でネストされたルーティングを作成する
ちなみにネストされたルーティングも同じようにディレクトリ構成で作ります。
ブログなどコンテンツが多いページ、カテゴリーのあるページなどでは「https://localhost:3000/blogs/0001」のようにしたいわけです。
例えば以下のようにディレクトリ構成を作成して、各フォルダにはpage.tsxを配置します。
src
|-app
|-about
| |-page.tsx
|
|-contact
| |-page.tsx
|
|-blogs
| |-page.tsx
| |
| |-0001
| | |-page.tsx
| |-0002
| |-page.tsx
|-page.tsx
|-layout.tsx
import React from 'react';
const page = () => {
return <div>ブログページ</div>;
};
export default page;
import React from 'react';
const page = () => {
return <div>ID:0001</div>;
};
export default page;
import React from 'react';
const page = () => {
return <div>ID:0002</div>;
};
export default page;
まずはhttps://localhost:3000/blogsにアクセスしてみます。
続いてblogs配下で作成していたディレクトリまでURLで移動してみます。
それぞれ親子関係になっているディレクトリのpage.tsxにアクセスすることができています。
一方で新規ページの追加、削除の頻度が多いケースだと毎回ディレクトリを作成したり削除することを手動でやらねばなりません。
そのような場合にNext.jsではparamsという仕組みを持っていて追加や削除が多くても簡易に運営できるようになっています。
以下のようなディレクトリ構成にしてみます。
src
|-app
|-about
| |-page.tsx
|
|-contact
| |-page.tsx
|
|-blogs
| |-page.tsx
| |
| |-0001
| | |-page.tsx
| |-0002
| |-page.tsx
|
|-products
| |-page.tsx
| |
| |-[productId]
| |-page.tsx
|
|
|-page.tsx
|-layout.tsx
新しくproductsというディレクトリを作成して[productId]という子供のディレクトリを持たせています。
ディレクトリ名を[]で囲むことがポイントです。
import React from 'react';
const page = () => {
return (
<div>
<h1>商品一覧</h1>
<p>商品A</p>
<p>商品B</p>
<p>商品C</p>
</div>
);
};
export default page;
import React from 'react';
const page = ({ params }: { params: { productId: string } }) => {
console.log(params);
return <div>商品名:{params.productId}</div>;
};
export default page;
[]で囲むことでその中にあるデータはparamsというpropsを使用できるようになります。
またparamsはオブジェクト形式になっています。
上記コードでconsole.logを書いておいたのでhttp://localhost:3000/product/0001にアクセスしてみます。
ターミナルにparamsの中身が表示されていて、オブジェクト形式でproductId: “0001”となっていることがわかります。
またブラウザも先ほどの手動でURLのクエリ名を使ったディレクトリを作成した時と同じような画面遷移ができています。
[]で囲んだディレクトリでは[プロパティ名]という意味になり、paramsのオブジェクトのプロパティ名として登録されます。
プロパティに対応する値はブラウザ上でURLのクエリ名になって、クエリ名が変わるたびにプロパティの値も動的に変わる仕組みです。
WordPressのようなCMSツールを扱ったことがあれば「スラッグ」に当たる部分になります。
この方法であればディレクトリを作成することを手動でやらなくても[]で囲んだディレクトリとpage.tsxさえ用意しておけばOKということです。
またparamsというprops自体はNext.js側で自動で生成されるのでconst params = {}というように宣言するコードを書く必要がない点も嬉しいです。
APIを取得してデータを表示する場合にはAPIのクエリをparamsのプロパティ名になると考えればAPIのクエリに連動した下層ページを動的に大量に作成することも可能になりますね。
また[]で囲んだディレクトリは子供のディレクトリを持ってネストさせることも可能です。
ディレクトリ構成を以下のように変更します。
src
|-app
|-about
| |-page.tsx
|
|-contact
| |-page.tsx
|
|-blogs
| |-page.tsx
| |
| |-0001
| | |-page.tsx
| |-0002
| |-page.tsx
|
|-products
| |-page.tsx
| |
| |-[productId]
| |-reviews
| | |-[reviewId]
| | |-page.tsx
|-page.tsx
|-layout.tsx
[productId]の下にreviewsというフォルダを作成して、その下に[reviewsId]というフォルダを作成しています。
import React from 'react';
const page = ({
params,
}: {
params: {
productId: string;
reviewId: string;
};
}) => {
console.log(params);
return (
<div>
商品ID:{params.productId}のレビューID:{params.reviewId}
</div>
);
};
export default page;
ネストされたので[]で囲まれたparamsのプロパティ名は2つに増えています。
こちらもconsole.logを入れているのでhttp://localhost:3000/products/0001/reviews/AAAというURLにアクセスしましょう。
ターミナルに表示されるparamsの中身が変わっていますね。
またブラウザの表示もできています。
スラッグ名が決まっていなかったり動的に追加、削除される可能性があるとき
ここまで紹介してきたディレクトリ名=スラッグ名にするルーティングは「スラッグ名が事前に決まっている」ことが前提となります。
例えばコーポレートサイトのお知らせ一覧ページを作成するとして、そのお知らせ一覧を年単位でまとめるのか月単位でまとめるのかは創業時には想像つかない顧客が多いのも現実です。
また日付を起点にしたルーティングをするにしても、未来はどこまでも続いていくのと過去はいくらでも遡れますのでディレクトリは追加もあれば削除もあり得るわけです。
そのような不確実性の高いコンテンツを運営するにあたりスラッグをどのようなキーワードでカテゴライズすれば良いのかわからないケースに合ったルーティングがNext.jsに用意されています。
先ほど紹介したものに少し似ていて[[…slug]]とすることで入れ子のディレクトリを好きなだけ追加したり削除しても問題なくできるようになります。
[productId]となっていた部分がスプレッド構文で…slugとなっていることから、配列の中身を自由に変更できるJavaScriptの特性を利用しているためです。
具体的には以下のようなディレクトリ構成にします。
src
|-app
|-about
| |-page.tsx
|
|-contact
| |-page.tsx
|
|-news
| |-[[...slug]]
| |-page.tsx
|
|-page.tsx
|-layout.tsx
先ほどまで紹介していた方法も便利であることには変わりありませんが、事前にスラッグ名を決めてディレクトリ構成を用意する必要がありファイルの数に大きな差があることがわかります。
<これまでのディレクトリ構成>
src
|-app
|-about
| |-page.tsx
|
|-contact
| |-page.tsx
|
|-blogs
| |-page.tsx
| |
| |-0001
| | |-page.tsx
| |-0002
| |-page.tsx
|
|-products
| |-page.tsx
| |
| |-[productId]
| |-reviews
| | |-[reviewId]
| | |-page.tsx
|-page.tsx
|-layout.tsx
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
<今から作るディレクトリ構成>
src
|-app
|-about
| |-page.tsx
|
|-contact
| |-page.tsx
|
|-news
| |-[[...slug]]
| |-page.tsx
|
|-page.tsx
|-layout.tsx
/src/app/news/[[…slug]]/page.tsxについては以下のように書きます。
import React from 'react';
const page = ({ params }: { params: { slug: string[] } }) => {
if (params.slug?.length === 2) {
return (
<h1>
{params.slug[0]}年{params.slug[1]}月のお知らせ一覧です。
</h1>
);
} else if (params.slug?.length === 1) {
return <h1>{params.slug[0]}年のお知らせ一覧です。</h1>;
} else {
return <h1>お知らせ一覧です。</h1>;
}
};
export default page;
お知らせ一覧を表示することには変わりませんがスラッグの数によって「/news/2024/01」のような年月でカテゴライズするのか、「/news/2024」のように年単位のみでカテゴライズするのか簡単にスイッチできるのです。
通常であればサイトを運営中にカテゴライズの方法を変更するにはDBの設定を変更したり、コードを大幅に変更したりなどしなければなりません。
現在コーポレートサイトを運営しているとして、まだ数件しかコンテンツがないときはカテゴライズする必要もないので「/news」として全て表示できます。
しばらくしてコンテンツの件数が増えてきたので年単位でカテゴライズして表示することも可能です。
さらに件数が増えてきて年単位だけでも煩雑になってきたら年月で細かくカテゴライズして表示することも可能です。
たった今作った短いコードを保存しておけば途中で大きなコード修正の必要なく動的にURLの運営方法を変更できるわけです。
従来の静的サイトやWordPressのようなCMSツールを使ったサイト構築を経験された方なら少し信じ難いかもしれませんね。
このようなバックエンド系の言語で取り入れられているルーティングの考え方をフロントエンドで使用できるようになっている点がNext.jsが支持されている理由です。
Next.jsでネストされたルーティングを作ってURLにフォルダ名を表示させたくない時
ネストするとURLがどんどん長くなっていきますので、途中の階層のディレクトリ名をURLから省略させたい時があります。
そのような時は「(ディレクトリ名)」と()で囲んだフォルダ名を命名すると、その配下にあるURLをルーティングに活用しつつ()で囲まれたフォルダ名をURLから削除することができます。
例えば以下のようなディレクトリ構成を作ったとします。
src
|-app
|-about
| |-page.tsx
|
|-contact
| |-page.tsx
|
|-news
| |-[[...slug]]
| |-page.tsx
|
|-page.tsx
|-layout.tsx
|
|-auth
| |-login
| | |-page.tsx
| |
| |-signup
| | |-page.tsx
| |
| |-signout
| | |-page.tsx
loginフォルダのpage.tsxを表示するにはhttp://localhost:3000/auth/loginというURLになります。
そこでauthフォルダを以下のように「(auth)」と変更してみます。
src
|-app
|-about
| |-page.tsx
|
|-contact
| |-page.tsx
|
|-news
| |-[[...slug]]
| |-page.tsx
|
|-page.tsx
|-layout.tsx
|
|-(auth)
| |-login
| | |-page.tsx
| |
| |-signup
| | |-page.tsx
| |
| |-signout
| | |-page.tsx
そうするとhttp://localhost:3000/loginだけでloginフォルダのpage.tsxにアクセスできるようになります。
逆にURLの中にauthを含めると404ページになります。
今回のようなauthというフォルダの中に複数の子ディレクトリがあるときはauthというスラッグは省略される方が良いとされています。
Next.jsで管理者だけに表示するプライベートフォルダを作る
続いてCMSのような管理者画面が必要な場合や、現在作成途中でまだ公開したくないページがあった時の運用について紹介します。
Next.jsはディレクトリによってURLのルーティングが決まることを前章までに解説しましたが、実は各フォルダのファイルはpage.tsxかpage.tsじゃないとユーザーから公開データとして確認できないようになっています。
例えば以下のようなフォルダを作ったとします。
src
|-app
|-about
| |-page.tsx
|
|-contact
| |-page.tsx
|
|-news
| |-[[...slug]]
| |-page.tsx
|
|-page.tsx
|-layout.tsx
|
|-dashboard
| |-dashboard.tsx
dashboardフォルダの中にdashboard.tsxを作りましたが、http://localhost:3000/dashboardにアクセスしても404ページになります。
一方でdashboard.tsxをpage.tsxに変更すると読み込みが変わります。
src
|-app
|-about
| |-page.tsx
|
|-contact
| |-page.tsx
|
|-news
| |-[[...slug]]
| |-page.tsx
|
|-page.tsx
|-layout.tsx
|
|-dashboard
| |-page.tsx
実はpage.tsxかpage.tsを公開するファイルとして読み込むような仕様になっているので、それ以外の名前にするとユーザーからは見えないページになるのです。
この特性を利用して管理者だけが確認できるページや未完成で非公開にしておきたい作業途中のページを運用することができるわけです。
ただしファイル名をpageにするかしないかだと運用ミスの原因に成りかねないので実務ではフォルダ名を「_〇〇」にすることでプライベートページとして運用することになります。
先ほどと同じく「_」から始まるURLスラッグはルーティングとして認識しないようになっているので同じくユーザーに見えないページを作ることができるのです。
先ほどのdashboardフォルダを_dashboardフォルダに変更します。
src
|-app
|-about
| |-page.tsx
|
|-contact
| |-page.tsx
|
|-news
| |-[[...slug]]
| |-page.tsx
|
|-page.tsx
|-layout.tsx
|
|-_dashboard
| |-page.tsx
ファイル名はpage.tsxのままですがフォルダ名の先頭に「_」がついたことで再度404ページに変わりました。