import

Инструкция import используется для импорта ссылок на значения, экспортированные из внешнего модуля. Импортированные модули находятся в строгом режиме независимо от того, объявляете ли вы их как таковые или нет. Для работы инструкции во встроенных скриптах нужно прописать у тэга script type="module".

Существует также function-like динамический import(), который не требует скриптов с типом "module".

Обратная совместимость может быть обеспечена с помощью атрибута nomodule тега script.

Динамический импорт полезен в ситуациях, когда вы хотите загрузить модуль условно или по требованию. Статическая форма предпочтительна для загрузки начальных зависимостей и может быть более полезна для инструментов статического анализа и tree shaking.

Внимание: На данный момент эта функциональность только начинает поддерживаться браузерами. Полноценная реализация присутствует во многих транспайлерах, таких как TypeScript и Babel, а также в сборщиках, например, в Rollup и Webpack.

Синтаксис

import defaultExport from "module-name"; 
import * as name from "module-name"; 
import { export } from "module-name"; 
import { export as alias } from "module-name"; 
import { export1 , export2 } from "module-name"; 
import { export1 , export2 as alias2 , […] } from "module-name"; 
import defaultExport, { export [ , […] ] } from "module-name"; 
import defaultExport, * as name from "module-name"; 
import "module-name";
import("/module-name.js").then(module => {…}) // Динамический импорт
defaultExport
Имя объекта, который будет ссылаться на значение экспорта по умолчанию (дефолтный экспорт) из модуля.
module-name
Имя модуля для импорта. Это зачастую относительный или абсолютный путь к .js файлу модуля без указания расширения .js. Некоторые сборщики могут разрешать или даже требовать использования расширения; проверяйте своё рабочее окружение. Допускаются только строки с одиночными или двойными кавычками.
name
Имя локального обьекта, который будет использован как своего рода пространство имен, ссылающееся на импортируемые значения.
export, exportN
Имена значений, которые будут импортированы.
alias, 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';

Импорт нескольких единичных значений

Этот код  вставляет оба значения foo и bar в текущую область видимости.

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';

Импорт значения по умолчанию

Есть возможность задать дефолтный 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';
// именованный импорт конкретных значений

Импорт переменных

Если вы импортируете переменные, то в данной области видимости они ведут себя как константы.

Такой код выведет ошибку:

my-module.js
export let a = 2;
export let b = 3;
main.js
import {a, b} from '/modules/my-module.js';
a = 5;
b = 6;
// Uncaught TypeError: Assignment to constant variable.

Для импорта можно воспользоваться объектом в котором хранятся эти переменные.

Такой код будет рабочим:

my-module.js
export let obj = {a:2, b:4};
main.js
import {obj} from '/modules/my-module.js';

obj.a = 1;
obj.b = 4;

Учитывая, что import хранит именно ссылки на значения, экспортированные из внешнего модуля, то это можно использовать как замыкания.

Динамический импорт

Ключевое слово import можно использовать как функцию для динамического импорта модулей. Вызов import() возвращает Promise.

import('/modules/my-module.js')
  .then(module => {
    // Делаем что-нибудь с модулем
  })

Как следствие возврата Promise, с динамическим импортом можно использовать ключевое слово await

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

Обратите внимание, что несмотря на то, что динамический импорт выглядит как вызов функции, он им по сути не является, т.е. не наследует от Function.prototype и, как следствие, его невозможно использовать вместе с методами .call, .apply и .bind

Примеры

Импорт из вспомогательного модуля для помощи в обработке запроса 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 2015 (6th Edition, ECMA-262)
Определение 'Imports' в этой спецификации.
Стандарт Начальное определение.
Unknown
Определение 'Imports' в этой спецификации.
Неизвестно
ECMAScript (ECMA-262)
Определение 'Imports' в этой спецификации.
Живой стандарт

Совместимость

Update compatibility data on GitHub
КомпьютерыМобильныеServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome для AndroidFirefox для AndroidOpera для AndroidSafari on iOSSamsung 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 Нет поддержки Нет

Легенда

Полная поддержка  
Полная поддержка
Нет поддержки  
Нет поддержки
Смотрите замечания реализации.
Смотрите замечания реализации.
Пользователь должен сам включить эту возможность.
Пользователь должен сам включить эту возможность.

Смотри также