動的インポート(Dynamic Import)

import() 関数を使うと、モジュールを動的に(実行時に)読み込むことができます。通常の import 文と異なり、条件分岐の中やイベントハンドラ内でも使用できます。

基本的な使い方

import() は Promise を返すため、async/await または .then() で結果を受け取ります。

// async/await を使用
async function loadModule() {
  const module = await import('./utils.js');
  module.doSomething();
}

// .then() を使用
import('./utils.js').then(module => {
  module.doSomething();
});

静的インポートとの違い

静的インポート(import 文)

ファイルの先頭でのみ使用可能。実行前に依存関係が解析される。常に読み込まれる。

動的インポート(import 関数)

どこでも使用可能。実行時に読み込まれる。条件付きで読み込める。

条件付きインポート

特定の条件を満たした場合のみモジュールを読み込むことができます。

async function setupEditor() {
  if (isAdvancedMode) {
    const { AdvancedEditor } = await import('./AdvancedEditor.js');
    return new AdvancedEditor();
  } else {
    const { BasicEditor } = await import('./BasicEditor.js');
    return new BasicEditor();
  }
}

イベント駆動でのインポート

ユーザーのアクションに応じてモジュールを読み込むパターンです。

document.getElementById('chart-btn').addEventListener('click', async () => {
  // ボタンがクリックされた時だけチャートライブラリを読み込む
  const { Chart } = await import('./chart.js');
  const chart = new Chart('#container');
  chart.render(data);
});

名前付きエクスポートとデフォルトエクスポート

動的インポートの結果はモジュールオブジェクトです。名前付きエクスポートはプロパティとして、デフォルトエクスポートは default プロパティでアクセスします。

// utils.js
export const VERSION = "1.0";
export function helper() { /* ... */ }
export default function main() { /* ... */ }
// 名前付きエクスポートを取得
const { VERSION, helper } = await import('./utils.js');

// デフォルトエクスポートを取得
const module = await import('./utils.js');
const main = module.default;

// 分割代入でまとめて取得
const { default: main, VERSION, helper } = await import('./utils.js');

コード分割(Code Splitting)

動的インポートは、バンドラーによるコード分割のヒントになります。大きなアプリケーションを複数のチャンクに分割し、必要なタイミングで読み込むことができます。

// ルートに応じてコンポーネントを遅延読み込み
const routes = {
  '/': () => import('./pages/Home.js'),
  '/about': () => import('./pages/About.js'),
  '/contact': () => import('./pages/Contact.js')
};

async function navigate(path) {
  const loadPage = routes[path];
  if (loadPage) {
    const { default: Page } = await loadPage();
    renderPage(Page);
  }
}

エラーハンドリング

モジュールの読み込みに失敗する可能性があるため、エラー処理が重要です。

async function loadFeature() {
  try {
    const module = await import('./feature.js');
    module.initialize();
  } catch (error) {
    console.error('モジュールの読み込みに失敗しました:', error);
    // フォールバック処理
    showBasicFeature();
  }
}

変数によるパス指定

動的インポートでは、変数を使ってパスを指定することもできます。

async function loadLocale(lang) {
  const module = await import(`./locales/${lang}.js`);
  return module.messages;
}

const messages = await loadLocale('ja');
注意点

バンドラーは変数を含むパスを静的に解析できないため、ワイルドカードでマッチするファイルをすべてバンドルに含める場合があります。パスのパターンは慎重に設計してください。

動的インポートを活用することで、初期読み込みを高速化し、ユーザー体験を向上させることができます。