Ми хочемо зробити цей проєкт з відкритим кодом доступним для людей у всьому світі.

Допоможіть перекласти цей підручник вашою мовою!

Динамічні імпорти

Інструкції експорту і імпорту, які ми розглядали в попередньому розділі, називаються “статичними”. Синтаксис у них дуже простий і строгий.

По-перше, ми не можемо динамічно задавати ніякі з параметрів import.

Шлях до модуля має бути рядком і не може бути викликом функції. Ось так працювати не буде:

import ... from getModuleName(); // Помилка, має бути рядок

По-друге, ми не можемо робити імпорт залежно від умов або в процесі виконання:

if(...) { import ...; // Помилка, заборонено } { import ...; // Помилка, ми не можемо ставити імпорт у блок }

Усе це результат того, що мета директив import/export – задати кістяк структури коду. Завдяки ним вона може бути проаналізована, модулі можуть бути зібрані в один файл спеціальними інструментами, а невживані експорти видалені. Це можливо тільки завдяки тому, що все статично.

Але як ми можемо імпортувати модуль динамічно, за запитом?

Вираз import()

Вираз import(module) завантажує модуль і повертає проміс, результатом якого стає об’єкт модуля, що містить усі його експорти.

Ми можемо використати його у будь-якому місці коду, наприклад, так:

let modulePath = prompt("Який модуль завантажити?"); import(modulePath) .then(obj => <об’єкт модуля>) .catch(err => <помилка завантаження, наприклад якщо немає такого модуля>)

Чи якщо усередині асинхронної функції, то можна використати let module = await import(modulePath).

Наприклад, якщо у нас є такий модуль say.js:

// 📁 say.js export function hi() { alert(`Привіт`); } export function bye() { alert(`Бувай`); }

…То динамічний імпорт може виглядати так:

let {hi, bye} = await import('./say.js'); hi(); bye();

А якщо в say.js вказаний типовий експорт:

// 📁 say.js export default function() { alert("Модуль завантажився (export default)!"); }

…То для доступу до нього нам слід узяти властивість default об’єкту модуля:

let obj = await import('./say.js'); let say = obj.default; // або одним рядком: let {default: say} = await import('./say.js'); say();

Ось повний приклад:

Результат
say.js
index.html
export function hi() { alert(`Привіт`); } export function bye() { alert(`Бувай`); } export default function() { alert("Модуль завантажений (export default)!"); }
<!doctype html> <script> async function load() { let say = await import('./say.js'); say.hi(); // Привіт! say.bye(); // Бувай! say.default(); // Модуль завантажений (export default)! } </script> <button onclick="load()">Натисни мене</button>
Будь ласка, зверніть увагу:

Динамічний імпорт працює в звичайних скриптах, він не вимагає вказівки script type="module".

Будь ласка, зверніть увагу:

Хоча import() і виглядає схожим на виклик функції, насправді це спеціальний синтаксис, так само, як, наприклад, super().

Тому ми не можемо скопіювати import в іншу змінну або викликати за допомогою .call/apply. Це не функція.

Навчальна карта

Коментарі

прочитайте це, перш ніж коментувати…
  • Якщо у вас є пропозиції, щодо покращення підручника, будь ласка, створіть обговорення на GitHub або одразу створіть запит на злиття зі змінами.
  • Якщо ви не можете зрозуміти щось у статті, спробуйте покращити її, будь ласка.
  • Щоб вставити код, використовуйте тег <code>, для кількох рядків – обгорніть їх тегом <pre>, для понад 10 рядків – використовуйте пісочницю (plnkr, jsbin, codepen…)