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');
  }
})();

If your project uses packages that export ESM, you can also import them for side effects only. This will run the code in the package entry point file (and any files it imports) only. 

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

デフォルトの 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 の定義

ブラウザー実装状況

Update compatibility data on GitHub
デスクトップモバイルサーバー
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeAndroid 版 FirefoxAndroid 版 OperaiOSのSafariSamsung InternetNode.js
importChrome 完全対応 61Edge 完全対応 16
完全対応 16
完全対応 15
無効
無効 From version 15: this feature is behind the Experimental JavaScript Features preference.
Firefox 完全対応 60
完全対応 60
未対応 54 — 60
無効
無効 From version 54 until version 60 (exclusive): this feature is behind the dom.moduleScripts.enabled preference. To change preferences in Firefox, visit about:config.
IE 未対応 なしOpera 完全対応 48Safari 完全対応 10.1WebView Android 完全対応 61Chrome Android 完全対応 61Firefox Android 完全対応 60
完全対応 60
未対応 54 — 60
無効
無効 From version 54 until version 60 (exclusive): this feature is behind the dom.moduleScripts.enabled preference. To change preferences in Firefox, visit about:config.
Opera Android 完全対応 45Safari iOS 完全対応 10.3Samsung Internet Android 完全対応 8.0nodejs 完全対応 13.2.0
補足
完全対応 13.2.0
補足
補足 Modules must either have a filename ending in .mjs, or the nearest parent package.json file must contain "type": "module". See Node's ECMAScript Modules documentation for more details.
完全対応 12.0.0
補足 無効
補足 Modules must either have a filename ending in .mjs, or the nearest parent package.json file must contain "type": "module". See Node's ECMAScript Modules documentation for more details.
無効 From version 12.0.0: this feature is behind the --experimental-modules runtime flag.
完全対応 8.5.0
補足 無効
補足 Module filenames must end with .mjs, not .js. See Node's ECMAScript Modules documentation for more details.
無効 From version 8.5.0: this feature is behind the --experimental-modules runtime flag.
Dynamic importChrome 完全対応 63Edge 完全対応 79Firefox 完全対応 67
完全対応 67
未対応 66 — 67
無効
無効 From version 66 until version 67 (exclusive): this feature is behind the javascript.options.dynamicImport preference (needs to be set to true). To change preferences in Firefox, visit about:config.
IE 未対応 なしOpera 完全対応 50Safari 完全対応 11.1WebView Android 完全対応 63Chrome Android 完全対応 63Firefox Android 完全対応 67
完全対応 67
未対応 66 — 67
無効
無効 From version 66 until version 67 (exclusive): this feature is behind the javascript.options.dynamicImport preference (needs to be set to true). To change preferences in Firefox, visit about:config.
Opera Android 完全対応 46Safari iOS 完全対応 11.3Samsung Internet Android 完全対応 8.0nodejs 完全対応 13.2.0
補足
完全対応 13.2.0
補足
補足 Dynamic import can be used in either CommonJS or ES module files, to import either CommonJS or ES module files. See Node's ECMAScript Modules documentation for more details.
完全対応 12.0.0
補足 無効
補足 Dynamic import can be used in either CommonJS or ES module files, to import either CommonJS or ES module files. See Node's ECMAScript Modules documentation for more details.
無効 From version 12.0.0: this feature is behind the --experimental-modules runtime flag.
Available in workersChrome 完全対応 80
完全対応 80
完全対応 67
無効
無効 From version 67: this feature is behind the Experimental Web Platform Features preference. To change preferences in Chrome, visit chrome://flags.
Edge 完全対応 80
完全対応 80
完全対応 79
無効
無効 From version 79: this feature is behind the Experimental Web Platform Features preference.
Firefox 未対応 なしIE 未対応 なしOpera 未対応 なしSafari 未対応 なしWebView Android 完全対応 80Chrome Android 完全対応 80
完全対応 80
完全対応 67
無効
無効 From version 67: this feature is behind the Experimental Web Platform Features preference. To change preferences in Chrome, visit chrome://flags.
Firefox Android 未対応 なしOpera Android 未対応 なしSafari iOS 未対応 なしSamsung Internet Android 未対応 なしnodejs 未対応 なし

凡例

完全対応  
完全対応
未対応  
未対応
実装ノートを参照してください。
実装ノートを参照してください。
ユーザーが明示的にこの機能を有効にしなければなりません。
ユーザーが明示的にこの機能を有効にしなければなりません。

実装の進捗状況

この機能はまだブラウザー間の安定性に達していないため、以下の表で、この機能の毎日の実装状況を示しています。このデータは、JavaScript の標準テストスイートである Test262 で、ナイトリービルド、または各ブラウザーの JavaScript エンジンの最新リリースで、関連する機能テストを実行することで生成されます。

関連情報