JavaScript 動的モジュール
1. JavaScript Dynamic Import
Dynamic Import(動的インポート)は、以下の構文を使用します:
import(module);Dynamic Import は ECMAScript 2020 (ES11) で導入されました。
これは、プログラムの開始時ではなく、ランタイム(実行時)にJavaScriptモジュールをロードするための手法です。
2. モダンなソフトウェア開発
モダンなソフトウェア開発では、インポートするコードを別々の「チャンク(Chunks)」に分割します。
モジュールが必要な時だけダウンロードされるこの手法には、以下のような多くの呼び名があります:
- Dynamic Import(動的インポート)
- Code Splitting(コード分割 / コードスプリッティング)
- Lazy Loading(遅延読み込み / レイジーローディング)
- Conditional Loading(条件付きロード)
Dynamic Import は、モジュール化された効率的なコードを実現するための最も強力な機能の一つです。
ファイルの上部に記述しなければならない Static Import(静的インポート) とは異なり、Dynamic Import は関数の中、条件分岐、イベントハンドラーなど、コード内のどこでも使用できます。
3. 構文 (Syntax)
import("./module.js")- 引数は、パスを解決するための文字列または式である必要があります。
- インポートはモジュールスクリプト (
<script type="module">) 内で実行する必要があります。
| タイプ | 例 | ロードされるタイミング |
|---|---|---|
| Static | import { add } from './math.js'; | ロード時(起動時) |
| Dynamic | const math = await import('./math.js'); | 必要な時(実行時) |
4. パフォーマンスの向上 (Improved Performance)
モジュールを使用することで、ツールによる「コード分割(Code Splitting)」の実装が可能になり、パフォーマンスが向上します。これにより、ユーザーのブラウザはアプリケーション全体のコードを一度にロードするのではなく、その瞬間に使用している特定の機能に必要なJavaScriptモジュールのみをロードすればよくなります。
モジュール自体は言語機能ですが、Webpack や Rollup、Vite といったバンドラーと組み合わせることで、Tree-shaking(未使用コードの削除)、コードスプリッティング、Minification(最小化 / モニフィケーション)などの最適化を通じて、劇的なパフォーマンス改善をもたらします。
5. Dynamic Import の仕組み
動的モジュールは、モダンな async/await 構文を利用します。
実装例:
async function run() {
const module = await import("./math.js");
let result = module.add(2, 3);
console.log(result);
}
run();math.js:
// "add" 関数をエクスポート
export function add(a, b) {
return a + b;
}5.1 コード例の解説
このスクリプトの動作フローは以下の通りです:
- スクリプトの実行が開始される。
run()関数が定義され、呼び出される。run()内で、math.jsを動的にロードする。- ロードが完了すると、エクスポートされた
add()関数へのアクセス権を取得する。 add(2, 3)を呼び出し、結果 5 を得る。- 結果を表示する。
| ステップ | コード | 解説 |
|---|---|---|
| 1 | async function run() | await を使用可能な関数を定義 |
| 2 | await import("./math.js") | 必要な時だけモジュールファイルをロード |
| 3 | module.add(2, 3) | モジュールからエクスポートされた関数を使用 |
| 4 | run() | プロセスを開始 |
5.2 各ステップの詳細
ステップ 1. await を使用可能な関数を定義する
async function run() {run()という名前の非同期関数(Asynchronous function)を定義します。asyncキーワードは、その関数内でawaitが使用可能であることを示します。awaitキーワードは、Promise(プロミス)が解決されるまで関数の実行を一時停止します。- このケースでは、モジュールのインポートが完了するのを待ちます。
ステップ 2. 必要な時だけモジュールファイルをロードする
const module = await import("./math.js");import("./math.js")が Dynamic Import を定義します。math.jsモジュールはオンデマンド(必要に応じて)ロードされます。math.jsは、エクスポートされたコンテンツを含む Promise を返します。awaitキーワードは、モジュールが完全にロードされるまで待機します。- ロードが完了すると、変数
moduleにmath.jsからエクスポートされたデータが格納されます。
ステップ 3. モジュールのエクスポート関数を使用する
let result = module.add(2, 3);- インポートされたモジュールから、エクスポートされている
add()関数を呼び出します。 - 引数として
2と3を渡します。 - 関数はそれらを加算し、
5を返します。 - 結果は
result変数に保存されます。
ステップ 4. プロセスを開始する(関数の呼び出し)
run();実行時の挙動:
math.jsモジュールを動的にロードする。- モジュールのロード完了を待機する。
- モジュールの
add()関数を実行する。 - 結果を表示する。
6. もう一つの実例:温度変換
実装例:
async function run(x) {
const module = await import("./temperatures.js");
let celsius = module.toCelsius(x);
document.getElementById("demo").textContent = celsius + " Celsius";
}
run(50);temperatures.js:
// 華氏(Fahrenheit)を摂氏(Celsius)に変換
export function toCelsius(farenheit) {
return (farenheit - 32) * 5 / 9;
}
// 摂氏(Celsius)を華氏(Fahrenheit)に変換
export function toFahrenheit(celsius) {
return (celsius * 9 / 5) + 32;
}7. Dynamic Import の主要機能
- Lazy Loading(遅延読み込み): コードが必要になった瞬間にだけロードします。
- パフォーマンスの最適化: 初期ロード時のサイズを削減し、ページ表示速度を高速化します。
- 条件付きインポート (Conditional Imports): 条件に基づいて異なるモジュールをインポートできます。
7.1 条件付きロード (Conditional Loading)
ユーザーの権限に応じて特定の管理ツールをロードする例:
if (user.isAdmin) {
const adminTools = await import("./admin-tools.js");
adminTools.init();
}