コードのモジュール化 — ファイル分割と構造の整理
このトピックを終えると
コードを複数のファイルに分割する理由を理解し、Node.jsのrequire/module.exportsパターンを使って、自分でファイルを分割できるようになります。
なぜコードを1つのファイルにまとめない方が良いのか
プロジェクトが小さいときは、すべてのコードをapp.jsの1つのファイルに記述しても問題ありません。しかし、コードが500行、1000行を超えると問題が発生します。
- 探しにくい: 「ログインロジックはどこにあったっけ?」→スクロールして探す必要がある
- 競合: 複数の人が同じファイルを修正すると、git merge時の競合が頻繁に発生する
- 再利用不可: Aプロジェクトで作成したユーティリティ関数をBプロジェクトで使用したい場合、コピー&ペーストする必要がある
モジュール化はこの問題を解決します。1つのファイル = 1つの役割として分割することです。
Node.jsでファイルを分割する
Node.jsは、module.exportsでエクスポートし、require()でインポートします。
// math.js — 計算ユーティリティモジュール
function add(a, b) {
return a + b;
}
function multiply(a, b) {
return a * b;
}
module.exports = { add, multiply };// app.js — メインファイルでインポートして使用
const math = require('./math');
console.log(math.add(3, 5)); // 8
console.log(math.multiply(4, 7)); // 28math.jsは計算のみを担当します。app.jsはその関数をインポートして使用するだけで、計算ロジックを知る必要はありません。これが**関心の分離(Separation of Concerns)**の原則です。
実践的なフォルダー構造
規模が大きくなると、フォルダーにまとめて管理します。以下はExpressプロジェクトの典型的な構造です。
project/
├── app.js # エントリーポイント — サーバーの起動
├── routes/
│ ├── users.js # /users関連のルーティング
│ └── posts.js # /posts関連のルーティング
├── controllers/
│ ├── userController.js
│ └── postController.js
├── models/
│ └── db.js # データベースへの接続
└── utils/
└── helpers.js # 共通のユーティリティ関数routes/はURLパスを、controllers/はビジネスロジックを、models/はデータ処理を担当します。各フォルダーが1つの役割を担うため、「ユーザー関連のバグ」が発生した場合、routes/users.jsとcontrollers/userController.jsのみを確認すれば済みます。
ES Modules — 最新の構文
Node.js 14以降、またはブラウザでは、import/export構文(ES Modules)を使用できます。
// math.mjs (またはpackage.jsonに "type": "module"を設定)
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}// app.mjs
import { add, multiply } from './math.mjs';
console.log(add(3, 5)); // 8
console.log(multiply(4, 7)); // 28requireとimportは同じ目的ですが、importは静的解析が可能であるため、バンドラー(Webpack、Vite)が不要なコードを削除(tree-shaking)できます。新しいプロジェクトでは、ES Modulesを推奨します。
重要なまとめ
| 質問 | 答え |
|---|---|
| なぜ分割するのか? | 見つけやすく、再利用可能で、共同作業時の競合を減らす |
| どのように分割するのか? | module.exports + require (CommonJS) または export + import (ESM) |
| 基準は? | 1つのファイル = 1つの役割(関心の分離) |
| フォルダー構造は? | routes / controllers / models / utilsなど、役割ごとに分類 |
ファイルを分割する習慣は、コードが100行のときから始めるのが良いでしょう。後で1000行になってから分割しようとすると、すでに複雑になっていてつらいです。