Next.jsのフォルダ構造 | ページレベル最適化と効率的な開発のためのベストプラクティス
はじめに
前回のNext.js入門に続き、本日はNext.jsでプロジェクトを構造化する方法について説明していきます。
前回の記事は以下となります。
Next.jsに適したフォルダ構造を自分で考えることは一般的です。
Next.jsにはページレベルでの最適化が存在し、ビルド時にログに記録されたページが表示されます。
すべてのコンポーネントファイルは「pages」フォルダ内でページとして処理されます。
そのため、ページに関係のないコンポーネントを「pages」フォルダに配置すると、ビルド時に不要なコンポーネントがページとして処理され、ビルド時間が増加してしまいます。
今回は、個人開発や小規模なチーム開発向けのNext.jsフォルダ構造を紹介します。
これは、個人的な意見をもとにしたものであり、開発者は自分に合ったファイルとディレクトリの構造を採用することができます。
開発者には多くのアプローチがあり、プロジェクトを構築するために必要なパスに従うか、いくつかの方法を組み合わせるかを選択することができます。
プロジェクト構成
まずは、初めてNext.jsを使用する初心者向けの例を以下に示します。
- components - Layout - index.js - Events - EventForm.js - EventsActions.js - constants - theme.js - page.js - hooks - useEvents.js - lib - api.js - validation.js - pages - index.js - events - [event].js - public - favicon.ico - styles - global.css - layout.module.css - tests - event.test.js - .babelrc - .eslintrc - .gitignore - jest.config.js - next.config.js - package.json - README.md
上記の構成では、機能や概念に基づいたフォルダ構造を採用しています。
componentsディレクトリには再利用可能なUIコンポーネントが配置され、pagesディレクトリには実際のページコンポーネントが配置されます。
constantsディレクトリにはテーマやページの定数が配置され、hooksディレクトリにはカスタムフックが配置されます。
libディレクトリはAPI通信やバリデーションなどのライブラリ関連のファイルが配置されます。
スタイル関連のファイルはstylesディレクトリにまとめられ、グローバルスタイルとコンポーネント固有のスタイルが分けられています。
テストファイルはtestsディレクトリに配置され、各コンポーネントや機能のテストを行います。
また、.babelrc
と.eslintrc
はBabelとESLintの設定ファイルであり、.gitignore
はGitの追跡を無視するファイルやディレクトリのリストです。
jest.config.js
とnext.config.js
はJestとNext.jsの設定ファイルです。
このような構成では、機能ごとにファイルをグループ化し、メンテナンスや拡張性を向上させることができます。ただし、プロジェクトの規模や要件に合わせて調整することも重要です。
以下の、プロジェクト構成はNext.jsの初心者にとってはやや複雑かもしれません。
- public - favicon.ico - src - core - components -layouts -Layout.js - events - EventForm.tsx - EventsActions.tsx - constants - theme.js - page.js - lib - events - hooks - queries - server - pages - api - events - [event].tsx _ .eslintignore _ .eslintrc _ .env _ babel.config.js _ Dockerfile _ jest.config.js _ next.config.js _ package.json _ README.md
※上記の構成はあくまでも個人開発や小規模チーム用となります
上記のプロジェクト構成を元にNext.jsのプロジェクト構成に関する説明をしてきます。
Next.jsにおけるプロジェクト構成とディレクトリの役割
Next.jsアプリケーションでは、通常以下のディレクトリが存在します。
・ 「public/」ディレクトリ:静的なファイルを配置するディレクトリです。
ここに配置されたファイルはビルド時にルートに転送されます。
一般的には画像やテキストファイルなどが含まれます。
これらのファイルは、ベースURL(/)から始まるコードで参照することができます。ただし、実行時に追加されたファイルは利用できず、また「pages/」ディレクトリ内に同じ名前の静的ファイルがある場合も利用できません。
静的フォルダを「public/」ディレクトリ内に配置することで、すべてのアセットをバンドルおよび圧縮することができます。
・ 「src/」ディレクトリ:Next.jsアプリケーションのソースコードを配置するディレクトリです。ここには主に以下の要素が含まれます。
「pages/」ディレクトリ: 各ページを配置するためのディレクトリです。ファイルシステムベースのルーターとして機能し、各「.js(x)」ファイルが対応するページとなります。
「components/」ディレクトリ: アプリケーションのコンポーネントを配置するディレクトリです。再利用性の高いコンポーネントをここに配置することで、見た目や機能を提供します。
「lib/」ディレクトリ: ドメインに関連するライブラリやカスタムフック、クエリ、コンテキストなどを配置するディレクトリです。これらのコードは、アプリケーション内の複数の場所で使用される場合があります。
・ 「core/」ディレクトリ:アプリケーションに関係のないコードを配置するディレクトリです。ここにはデータベース接続関数や再利用可能なUIコンポーネント、メール送信プロバイダーなどが含まれます。
ただし、コアレイヤーからドメインレイヤーへのインポートはできない場合があります。
・ 「layouts/」ディレクトリ:ページのレイアウトや定数、ライブラリの配置に関するガイダンスを提供するディレクトリです。
Next.jsには組み込みのレイアウトシステムはありませんが、複数のページで使用される要素やコンポーネントを使用してメタコンポーネントを作成することで、レイアウトを構築することができます。
このディレクトリ内には、共通のレイアウトコンポーネントを配置することが一般的です。
・ 「constants/」ディレクトリ:定数を配置するためのディレクトリです。関連する定数を同じディレクトリにまとめることで、ファイルの整理が容易になります。必要な定数ごとにファイルを作成することができます。
これらの構成に従うことで、Next.jsアプリケーションのコードを整理し、再利用性や保守性を向上させることができます。
ただし、プロジェクトの要件や個別の開発チームのスタイルによって、構成は異なる場合もあります。
ルートディレクトリファイル
ディレクトリのルートには、下記ようないくつかの構成ファイルとセットアップファイルがあります。
・ eslintignoreおよび.eslintrc
・ .envファイル
・ babel.config.js
・ jest.config.js
・ next.config.js
・ package.json
・ README.md
可能な構成ファイルはこれらだけではありません。
より複雑なシナリオで使用できる構成ファイルも沢山あります。
構成ファイルもプロジェクトの要件や開発チームの好みによって異なる場合があります。
そのため、具体的なプロジェクトによってさらなる構成ファイルが存在する可能性があります。
また、Next.jsでは環境変数を使用することができます。
ただし、重要なポイントは、デフォルトでは環境変数はサーバーサイドのコードからのみアクセス可能です。
ブラウザ上で実行されるクライアントサイドのJavaScriptから直接アクセスすることはできません。
クライアントサイドで利用するためには、接頭辞として「NEXT_PUBLIC_」を付けた環境変数を使用する必要があります。
例えば、「NEXT_PUBLIC_APP_URL」という環境変数を設定する場合は、次のように設定します。
NEXT_PUBLIC_APP_URL="https://example.com"
ただし、安全性を確保するために、クライアントサイドで扱う必要がない環境変数は、接頭辞「NEXT_PUBLIC_」を付けずに設定することが推奨されます。
サーバーサイドのコードからのみ利用する環境変数は、直接設定することができます。
環境変数の設定は、Next.jsの設定ファイルである「next.config.js」で行うことができます。
「next.config.js」を使用することで、ビルド時に環境変数を設定することができます。
// next.config.js module.exports = { // 環境変数を設定する env: { MY_VAR: 'Hello World', ANOTHER_VAR: process.env.ANOTHER_VAR, // 環境変数を参照する }, // Webpackの設定を変更する webpack: (config, { isServer }) => { // サーバーサイドの場合 if (isServer) { // Node.jsのprocess.envに環境変数を設定する process.env.MY_SERVER_VAR = 'This is a server-side variable'; } return config; }, };
上記の例では、以下のようなことが行われています。
・「env」オブジェクトにより、クライアントサイドのJavaScriptからアクセス可能な「MY_VAR」と「ANOTHER_VAR」の環境変数を設定しています。
・「process.env.ANOTHER_VAR」により、環境変数を参照しています。
・「webpack」関数により、サーバーサイドでのみ利用可能な「MY_SERVER_VAR」の環境変数を設定しています。
・「process.env.MY_SERVER_VAR」により、Node.jsの「process.env」に環境変数を設定しています。
これらの環境変数は、アプリケーションの任意の場所で使用することができます。
また、環境変数を使用するためには、「dotenv」というパッケージを使用することができます。
環境変数は、アプリケーションごとに適切に設定する必要があります。
適切に設定された環境変数は、アプリケーションの動作に必要な情報を安全に保持することができます。
最後に
Next.jsのフォルダ構造には、レイヤー間でインポートする際に規則があります。特に、「core」レイヤーからは、「lib」や「components」レイヤーをインポートすることはできません。
これにより、依存関係を回避し、アーキテクチャを明確に分離することができます。
フォルダ構造は、ユーザーやユースケースに合わせて適切に設計する必要があります。
この規則に従うことで、フォルダ構造が柔軟性を持ち、ファイルの場所を予測しやすくなります。
また、抽象化やモジュール化のルールに従って、クラスやコンポーネントの単一責任を実現することが重要です。
技術的な理解が必要ですが、この規則は重要であり、混在させないように注意することが必要です。
本日は以上となります。
最後まで読んで頂きありがとうございました。
当ブログの記事があなたのこれからの学習に役立つ事を願っております。