В ES2015 (он же ES6) впервые была добавлена ​​собственная модульная система JS, но основная проблема заключается в том, что это статический импорт, что означает, что он не может быть изменен во время выполнения, а также весь импорт должен быть разрешен до того, как JS сможет выполнить любой код, который мне кажется отстойным.

В ES2020 TC39 утверждает предложение по динамическому импорту модулей. Итак, теперь вместо того, чтобы иметь весь импорт в верхней части файла, вы можете импортировать модули, когда это необходимо. Однако эта функция была поддержана веб-пакетом.

Основное преимущество, которое мы можем получить от динамического импорта, состоит в том, что у нас может быть более быстрое время загрузки. Также, если некоторые модули не существуют во время загрузки, они могут быть динамически загружены позже. Мы можем разделить код и загрузить только то, что важно в текущий момент времени. Это может сделать приложение более надежным, поскольку при начальной загрузке не будут загружены все необходимые модули.

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

Как?

Для динамического импорта ключевое слово import должно вызываться как функция, возвращающая обещание. Предположим, у нас есть util.js, у которого есть несколько именованных экспортов по умолчанию.

// util.js
export function doSomthing() {
   console.log("Named Export");
}
export default function doSomethingDefault() {
console.log("Default Export");
}

Теперь мы можем динамически импортировать его как

const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
// loads named export
import("./util.js").then(({ doSomething}) => {
doSomething();
});
// loads entire module
// runs default export
import("./util.js").then((module) => {
module.default();
});
});

Другой способ извлечения логики импорта наверх - это файл, который можно выполнить следующим образом, здесь метод loadUtil возвращает обещание, которое можно связать.

const loadUtil = () => import("./util.js");
const btn = document.getElementById("btn");
btn.addEventListener("click", () => {
loadUtil().then(module => {
module.doSomething();
module.default();
}); });

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

В модулях ES хорошо то, что, в отличие от CommonJS и AMD, модули ES могут быть любой строкой объекта JS, JSON, конструктором, функциями и т. Д.

const loadConfig = () => import("./config.json")

Файлы JSON имеют только экспорт по умолчанию, поэтому вы можете получить доступ к объекту с помощью module.default и деструктурировать его.

Динамический импорт с асинхронным / ожиданием

Как мы уже выяснили, import () возвращает обещание, что означает, что мы можем выполнить его async / await.

const loadConfig = () => import("./config.js");
const btn = document.getElementById("btn");
btn.addEventListener("click", async () => {
const ConfigModule = await loadConfig();
configModule.doSomthing();
configModule.default();
});

import () похож на функцию, но не на функцию

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

Пожалуйста, найдите официальный MDN Link для дальнейшего изучения.

Удачного обучения!