概要
今回のブログポストではモノレポを理解するための基本知識として、NodeJS
がモジュールを読み込む方法について説明します。
ブログシリーズ
このブログはシリーズで制作されています。次のリンクを通じて他のブログポストも確認してください。
- [プロジェクト管理] リポジトリ戦略
- [JavaScript] モノレポ(Monorepo)のためのツール
- [Monorepo] NodeJS のモジュールの読み込み
- [Monorepo] Symlink
- [Monoepo] Yarn Workspaces
- [Monoepo] Yarn Workspaces の依存性の Hoisting
- [Monoepo] Yarn Workspaces のコマンド
- [Monoepo] pnpm を使ってモノレポを作る方法
モジュール
JavaScript でモジュールはコードを構成し、再利用可能な単位に分離するために使用される機能です。モジュールを使用するとコードをより簡単にメンテナンスすることができるし、拡張することができます。ECMAScript 2015(ES6)から JavaScript に元々なかったモジュールシステムが導入されました。
モジュールはファイルレベルでコードをカプセル化し、必要な機能を他のファイルから取り込んで使用することができます。モジュールを使用するとグローバルスコープのコンフリクトを防ぐことができ、コードの依存関係を明確に管理することができます。
JavaScript でモジュールを使用するためには、次のキーワードを使用します。
import
: 他のモジュールからエクスポートされた機能を現在のモジュールに取り込みます。export
: 現在のモジュールから外部にエクスポートする関数、変数、クラスなどを指定します。
JavaScript で次のようにモジュールを作成することができます。
// math.js
export function add(a, b) {
return a + b;
}
export function subtract(a, b) {
return a - b;
}
このように作成したモジュールは次のように使用することができます。
// main.js
import { add, subtract } from './math';
console.log(add(5, 3)); // 8
console.log(subtract(7, 2)); // 5
モジュールの読み込み
JavaScript でモジュールを読み込む方法は大きく分けて次の 2 つがあります。
File path
を使用する方法Package name
を使用する方法
File path
File path
を使用してモジュールを読み込む場合、相対パス(Relative path)と絶対パス(Absolute path)の両方を使用することができます。
// Relative path
import { add, subtract } from '../some/file/path/math';
// Absolute path
import { add, subtract } from '/src/math';
Package name
node_modules
フォルダーにあるモジュールはPackage name
を使用して読み込むことができます。
// react module exists in node_modules
import React from 'react';
モジュールの読み込み優先順位
NodeJS
はモジュールを読み込む際に、まずは同じフォルダーにモジュールが存在するか、同じフォルダーのnode_modules
にモジュールが存在するかを確認します。もし同じフォルダーにモジュールが存在しない場合、親フォルダーのnode_modules
フォルダーを確認し、親フォルダーのnode_modules
にも存在しない場合、親フォルダーの親フォルダーのnode_modules
からモジュールを探します。
例題
NodeJS
がモジュールを読み込む方法を確認するために、次のようなフォルダー構造を作成してみます。
.
└── src/
├── module-a/
│ ├── index.js
│ └── package.json
└── module-b/
├── index.js
└── package.json
module-a
のpackage.json
は次のようです。
// src/module-a/package.json
{
"name": "module-a",
"version": "1.0.0",
"main": "index.js"
}
module-b
のpackage.json
は次のようです。
// src/module-b/package.json
{
"name": "module-b",
"version": "1.0.0",
"main": "index.js"
}
そしてmodule-b
のindex.js
は次のようです。
// src/module-b/index.js
console.log('module-b');
最後にmodule-a
のindex.js
は次のようです。
// src/module-a/index.js
console.log('module-a');
require('module-b');
このようにファイルを構成した後、次のコマンドを実行してモジュールを読み込むことができるか確認します。
node src/module-a/index.js
そしたら次のようなエラーが発生することが確認できます。
module-a
node:internal/modules/cjs/loader:1073
throw err;
^
Error: Cannot find module 'module-b'
Require stack:
- /Users/deku/temp/temp/src/module-a/index.js
at Module._resolveFilename (node:internal/modules/cjs/loader:1070:15)
at Module._load (node:internal/modules/cjs/loader:923:27)
at Module.require (node:internal/modules/cjs/loader:1137:19)
at require (node:internal/modules/helpers:121:18)
at Object.<anonymous> (/Users/deku/temp/temp/src/module-a/index.js:3:1)
at Module._compile (node:internal/modules/cjs/loader:1255:14)
at Module._extensions..js (node:internal/modules/cjs/loader:1309:10)
at Module.load (node:internal/modules/cjs/loader:1113:32)
at Module._load (node:internal/modules/cjs/loader:960:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12) {
code: 'MODULE_NOT_FOUND',
requireStack: [ '/Users/deku/temp/temp/src/module-a/index.js' ]
}
次はsrc
フォルダ名をnode_modules
で変更して次のコマンドを実行してみます。
node node_modules/module-a/index.js
そしたら次のように問題なく実行されることが確認できます。
module-a
module-b
フォルダー名がsrc
の場合、module-a
からrequire('module-b');
を通じてmodule-b
を読み込むと、ファイルパスではないため、同じフォルダーのnode_modules
からmodule-b
を探すことになります。node_modules
が現在のフォルダーに存在しないため、親フォルダーのnode_modules
を確認します。親フォルダーにもnode_modules
が存在しないため、MODULE_NOT_FOUND
エラーが発生することが確認できます。
フォルダー名をnode_modules
に変更した後、同じコードを実行すると、module-a
フォルダーにnode_modules
が存在しないため、親フォルダーからnode_modules
を探すことになります。親フォルダーにはフォルダー名を変更したnode_modules
が存在し、そのフォルダーにmodule-b
が存在するため、問題なく実行されることが確認できます。
完了
これでNodeJS
がモジュールを読み込む方法について説明しました。NodeJS
がモジュールを読み込む方法はモノレポでプロジェクトを構成するのに役立つ知識なので、今回のブログポストで紹介しました。皆さんもこの機会にNodeJS
がモジュールを読み込む方法についてもう一度理解してみてください。
私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!
アプリ広報
Deku
が開発したアプリを使ってみてください。Deku
が開発したアプリはFlutterで開発されています。興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。