import

import 文は、他のモジュールによってエクスポートされた読み込み専用のライブバインディングをインポートするために使用します。インポートされたモジュールは、宣言するかどうかにかかわらず、Strict モードになります。import 文は、スクリプトに type="module" がない限り、埋め込みスクリプトで使用できません。インポートされたバインディングは、バインディングをエクスポートしたモジュールによって更新されるため、ライブバインディングと呼ばれます。

また、type="module" のスクリプトを必要としない動的 import() という関数のようなものもあります。

<script> タグの nomodule 属性を使用すると、下位互換性を確保できます。

構文

import defaultExport from "module-name";
import * as name from "module-name";
import { export1 } from "module-name";
import { export1 as alias1 } from "module-name";
import { export1 , export2 } from "module-name";
import { foo , bar } from "module-name/path/to/specific/un-exported/file";
import { export1 , export2 as alias2 , [...] } from "module-name";
import defaultExport, { export1 [ , [...] ] } from "module-name";
import defaultExport, * as name from "module-name";
import "module-name";
var promise = import("module-name");
defaultExport
モジュールからのデフォルトのエクスポートを参照する名前。
module-name
インポートするモジュール。モジュールがある .js ファイルへの相対または絶対パス名です。バンドラーによっては、拡張子を加えることが許され、あるいは求められることがあります。環境を確認してください。シングルクォートとダブルクォートだけが使えます。
name
インポートを参照するとき名前空間のように用いられるモジュールオブジェクトの名前。
exportN
インポートするエクスポートの名前。
aliasN
指定されたインポートを参照する名前。

説明

name パラメータは、エクスポートを参照する名前空間のように用いられる「モジュールオブジェクト」の名前です。export パラメータは名前がつけられたエクスポートをそれぞれ指定します。それに対して、import * as name 構文はすべてをインポートします。構文の意味を明らかにするため、下記に例を示します。

モジュールのコンテンツすべてをインポートする

下記のコードは、myModule を現在のスコープに加え、/modules/my-module.js のファイルのモジュールからのエクスポートすべてを含めます。

import * as myModule from '/modules/my-module.js';

エクスポートにアクセスするには、モジュール名(ここでは「myModule」)を名前空間として用いることになります。たとえば、上記でインポートされたモジュールがエクスポートに doAllTheAmazingThings() を含む場合は、下記のように呼び出します。

myModule.doAllTheAmazingThings();

モジュールからエクスポートをひとつインポートする

myExport という名前のオブジェクトまたは値が、my-module から暗黙的 (モジュール全体がエクスポートされた場合) あるいは export 文を用いて明示的にエクスポートされると、myExport が現在のスコープに加えられます。

import {myExport} from '/modules/my-module.js';

モジュールから複数のエクスポートをインポートする

下記のコードは、foobar を現在のスコープに加えます。

import {foo, bar} from '/modules/my-module.js';

エクスポートを扱いやすいエイリアスにしてインポートする

インポートするときエクスポートの名前を変えることができます。例えば下記のコードは、エクスポートを shortName として現在のスコープに加えます。

import {reallyReallyLongModuleExportName as shortName}
  from '/modules/my-module.js';

インポートする際に複数のエクスポートの名前を変える

下記のコードは、複数のエクスポートを扱いやすいエイリアスにしてモジュールからインポートします。

import {
  reallyReallyLongModuleExportName as shortName,
  anotherLongModuleName as short
} from '/modules/my-module.js';

副作用のためだけにモジュールをインポートする

副作用だけのためにモジュール全体をインポートしたときは、何もインポートされません。モジュールのグローバルコードが実行されるだけで、実際の値はインポートされないのです。

import '/modules/my-module.js';

これは動的インポートにも対応しています。

(async () => {
  if (somethingIsTrue) {
    // 副作用のためのインポートモジュール
    await import('/modules/my-module.js');
  }
})();

プロジェクトで ESM をエクスポートするパッケージを使用している場合は、副作用のためだけにインポートすることもできます。これにより、パッケージエントリーポイントファイル(およびインポートするすべてのファイル)のコードのみが実行されます。

デフォルトをインポートする

デフォルトの export(オブジェクト、関数、クラスなど)にも対応できます。import 文を用いて、そのようなデフォルトをインポートします。

もっとも単純なやり方は、デフォルトを直接インポートすることです。

import myDefault from '/modules/my-module.js';

また、デフォルトの構文とともに上記のエイリアス(名前空間または名前つきのインポート)を用いることもできます。その場合は下記のように、デフォルトのインポートを先に宣言しなければなりません。

import myDefault, * as myModule from '/modules/my-module.js';
// myModule は名前空間として使う

あるいは、次のような書き方もできます。

import myDefault, {foo, bar} from '/modules/my-module.js';
// 特定の名前つきのインポート

動的インポートを使用してデフォルトのエクスポートをインポートする場合、動作が少し異なります。返されたオブジェクトから "default" キーを破棄して名前を変更する必要があります。

(async () => {
  if (somethingIsTrue) {
    const { default: myDefault, foo, bar } = await import('/modules/my-module.js');
  }
})();

動的インポート

標準のインポート構文は静的で、インポートされたモジュールのすべてのコードは、ロード時に常に評価されます。条件付きまたはオンデマンドでモジュールをロードしたい状況では、代わりに動的インポートを使用できます。以下に、動的インポートの使用を検討する必要がある理由をいくつか述べます。

  • 静的にインポートすると、コードの読み込みが大幅に遅くなり、インポートするコードが必要になる可能性が低くなるか、後で必要になる可能性が低くなります。
  • 静的にインポートすると、プログラムのメモリー使用量が大幅に増加し、インポートするコードが必要になる可能性が低くなります。
  • ロード時にインポートするモジュールが存在しない場合。
  • インポート指定子の文字列を動的に作成する必要がある場合。(静的インポートは静的指定子のみをサポートします。)
  • インポートするモジュールに副作用があり、何らかの条件が真でない限り、それらの副作用を望まない場合。(モジュールに副作用がないことを推奨しますが、モジュールの依存関係でこれを制御できない場合があります。)

動的インポートは必要な場合にのみ使用してください。初期の依存関係をロードするには静的な形式が適していて、静的解析ツールやツリーシェイクの恩恵をよりよく受けることができます。

モジュールを動的にインポートするために、import キーワードを関数として呼び出すことができます。この方法で使用すると、promise が返されます。

import('/modules/my-module.js')
  .then((module) => {
    // module を使った何らかの処理
  });

この方法は await キーワードを使えます。

let module = await import('/modules/my-module.js');

標準的なインポート

以下のコードは AJAX JSON リクエストの処理を支援する補助モジュールからインポートする方法を示しています。

モジュール: file.js

function getJSON(url, callback) {
  let xhr = new XMLHttpRequest();
  xhr.onload = function () {
    callback(this.responseText)
  };
  xhr.open('GET', url, true);
  xhr.send();
}

export function getUsefulContents(url, callback) {
  getJSON(url, data => callback(JSON.parse(data)));
}

メインプログラム: main.js

import { getUsefulContents } from '/modules/file.js';

getUsefulContents('http://www.example.com',
    data => { doSomethingUseful(data); });

動的インポート

この例は、ユーザーのアクション(この場合はボタンクリック)に基づいて機能をページにロードし、そのモジュール内で関数を呼び出す方法を示しています。この機能を実装する方法はこれだけではありません。import() 関数は await もサポートしています。

const main = document.querySelector("main");
for (const link of document.querySelectorAll("nav > a")) {
  link.addEventListener("click", e => {
    e.preventDefault();

    import('/modules/my-module.js')
      .then(module => {
        module.loadPageInto(main);
      })
      .catch(err => {
        main.textContent = err.message;
      });
  });
}

仕様

仕様書
ECMAScript (ECMA-262)
Imports の定義
ECMAScript (ECMA-262)
Import Calls の定義

ブラウザー実装状況

BCD tables only load in the browser

関連情報