The static import statement is used to import features into JavaScript modules that have been exported by another module. Imported modules are implicitly in strict mode whether you declare them as such or not.

There is also a function-like dynamic import(), which allows modules to be imported dynamically when needed, rather than at the start of the module.

Dynamic imports are useful in situations where you wish to load a module conditionally, or on demand. The static form is preferable for loading initial dependencies, and can benefit more readily from static analysis tools and tree shaking.

Syntax

// Import individual features
import { export } from "module-name";
import { export1 , export2 } from "module-name";

// Import default export
import defaultExport from "module-name";

// Import all of a module's exports as a module object
import * as name from "module-name";

// Import renamed exports 
import { export as alias } from "module-name";

// Import a module for side effects only
import "module-name";

// Combinations
import { export1 , export2 as alias2 , [...] } from "module-name";
import defaultExport, { export [ , [...] ] } from "module-name";
import defaultExport, * as name from "module-name";

// Dynamic module import
var promise = import("module-name"); // This is a stage 3 proposal.
defaultExport
Name that will refer to the default export from the module.
module-name
Path to the module to import from. This is often a relative or absolute path name to the .js file containing the module. Certain bundlers may allow you to omit the .js extension, but native JS modules require it.
name
When a module's exports are imported as a module, this is the name of the module object, which will act as a namespace when referring to the imports.
export, exportN
Name of the exports to be imported.
alias, aliasN
Alternative names that will be used when exports are renamed.

Description

Import a single export from a module

Given an object or value named myExport which has been exported from the module my-module either implicitly (because the entire module is exported) or explicitly (using the export statement), this inserts myExport into the current scope.

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

Import multiple exports from module

This inserts both foo and bar into the current scope.

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

Import an entire module's contents

This inserts myModule into the current scope, containing all the exports from the module in the file located in /modules/my-module.js.

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

Here, accessing the exports means using the module name ("myModule" in this case) as a namespace. For example, if the module imported above includes an export doAllTheAmazingThings(), you would call it like this:

myModule.doAllTheAmazingThings();

Rename an export with a more convenient alias

You can rename an export when importing it. For example, this inserts shortName into the current scope.

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

Rename multiple exports during import

Import multiple exports from a module with convenient aliases.

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

Import a module for its side effects only

Import an entire module for side effects only, without importing anything. This runs the module's global code, but doesn't actually import any values.

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

Importing defaults

It is possible to have a default export (whether it is an object, a function, a class, etc.). The import statement may then be used to import such defaults.

The simplest version directly imports the default:

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

It is also possible to use the default syntax with the ones seen above (namespace imports or named imports). In such cases, the default import will have to be declared first. For instance:

import myDefault, * as myModule from '/modules/my-module.js';
// myModule used as a namespace

or

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

Dynamic imports

The import keyword may be called as a function to dynamically import a module. When used this way, it returns a promise.

import('/modules/my-module.js')
  .then((module) => {
    // Do something with the module.
  });

This form also supports the await keyword.

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

Applying modules to HTML

To apply a module script to an HTML document, you need to use a <script> of type="module". The import statement cannot be used in non-module scripts. for example:

<script type="module" src="main.js"></script>

Backwards compatibility

Backward compatibility can be put in place by using your type="module" <script> element along with a fallback <script> element containing the nomodule attribute.

<script type="module" src="main.js"></script>
<script nomodule src="fallback.js"></script>

This works because browsers that support JavaScript modules ignore scripts with nomodule set on them, whereas non-supporting browsers will not load the module script and load the fallback instead.

Examples

Standard Import

The code below shows how to import from a secondary module to assist in processing an AJAX JSON request.

The module: 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)));
}

The main program: main.js

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

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

Dynamic Import

This example shows how to load functionality on to a page based on a user action, in this case a button click, and then call a function within that module. This is not the only way to implement this functionality. The import() function also supports 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;
      });
  });
}

Specifications

Specification Status Comment
"function-like" dynamic import() proposal Stage 3  
ECMAScript Latest Draft (ECMA-262)
The definition of 'Imports' in that specification.
Draft  
ECMAScript 2018 (ECMA-262)
The definition of 'Imports' in that specification.
Standard  
ECMAScript 2017 (ECMA-262)
The definition of 'Imports' in that specification.
Standard  
ECMAScript 2016 (ECMA-262)
The definition of 'Imports' in that specification.
Standard  
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Imports' in that specification.
Standard Initial definition.

Browser compatibility

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidEdge MobileFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
importChrome Full support 61Edge Full support 16
Full support 16
Full support 15
Disabled
Disabled From version 15: this feature is behind the Experimental JavaScript Features preference.
Firefox Full support 60
Full support 60
No support 54 — 60
Disabled
Disabled 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 No support NoOpera Full support 47Safari Full support 10.1WebView Android Full support 61Chrome Android Full support 61Edge Mobile Full support YesFirefox Android Full support 60
Full support 60
No support 54 — 60
Disabled
Disabled 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 Full support 44Safari iOS Full support 10.1Samsung Internet Android No support Nonodejs Full support 8.5.0
Notes Disabled
Full support 8.5.0
Notes Disabled
Notes files must have suffix .mjs, not .js
Disabled From version 8.5.0: this feature is behind the --experimental-modules runtime flag.
Dynamic importChrome Full support 63Edge No support No
Notes
No support No
Notes
Notes See development status.
Firefox Full support 67
Full support 67
No support 66 — 67
Disabled
Disabled 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 No support NoOpera Full support 50Safari Full support 11.1WebView Android Full support 63Chrome Android Full support 63Edge Mobile No support NoFirefox Android Full support 67
Full support 67
No support 66 — 67
Disabled
Disabled 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 Full support 46Safari iOS Full support 11.1Samsung Internet Android No support Nonodejs ?

Legend

Full support  
Full support
No support  
No support
Compatibility unknown  
Compatibility unknown
See implementation notes.
See implementation notes.
User must explicitly enable this feature.
User must explicitly enable this feature.

See also