Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Динамічний імпорт». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**Динамічний імпорт** - це виклик функції `import()`, яка повертає Promise і дозволяє завантажувати модулі під час виконання програми (runtime), а не під час збірки. **Ключове:** замість того щоб тягнути весь застосунок одразу, ти вантажиш тільки те, що потрібно, коли це потрібно.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення## Що таке динамічний імпорт **Динамічний імпорт** - це виклик функції `import()`, яка **повертає Promise** і дозволяє завантажувати модулі **під час виконання програми** (runtime), а не під час збірки. Приклад: ```javascript // Динамічний імпорт const module = await import('./utils.js'); module.sayHello(); ``` Відмінність від статичного імпорту: ```javascript // Статичний імпорт import { sayHello } from './utils.js'; ``` При статичному імпорті весь модуль завантажується одразу під час запуску. При динамічному - тільки коли справді потрібен. --- ## Синтаксис ```javascript import(modulePath) .then(module => { // модуль завантажено module.default(); }) .catch(err => console.error(err)); ``` або з `await`: ```javascript const module = await import('./math.js'); const { sum } = module; console.log(sum(2, 3)); ``` --- ## Що повертає `import()` `import()` повертає **Promise**, який резолвиться об'єктом модуля: ```javascript // math.js export function add(a, b) { return a + b; } export const PI = 3.14; ``` ```javascript const math = await import('./math.js'); console.log(math.add(2, 3)); // 5 console.log(math.PI); // 3.14 ``` --- ## Приклад: умовне завантаження (conditional import) Можна динамічно завантажувати різні модулі залежно від ситуації: ```javascript if (navigator.language.startsWith('fr')) { const messages = await import('./lang/fr.js'); console.log(messages.default.hello); } else { const messages = await import('./lang/en.js'); console.log(messages.default.hello); } ``` Чудово підходить для **багатомовних інтерфейсів**, **плагінів**, **важких залежностей** та **лінивого завантаження сторінок (lazy loading)**. --- ## Приклад: обробка помилок при завантаженні ```javascript try { const module = await import('./missing.js'); } catch (err) { console.error('Помилка при завантаженні модуля:', err); } ``` --- ## Приклад: завантаження за дією користувача ```javascript button.addEventListener('click', async () => { const { openModal } = await import('./modal.js'); openModal(); }); ``` Модуль `modal.js` буде завантажено **тільки при першому кліку**, а не під час запуску сайту - економія трафіку і прискорення старту. --- ## Динамічний імпорт зі змінними Можна використовувати **динамічні шляхи**, чого неможливо зі статичними імпортами: ```javascript const theme = 'dark'; const module = await import(`./themes/${theme}.js`); module.applyTheme(); ``` Важливо: збирач (наприклад, Webpack) все одно повинен уміти **передбачити шаблон шляхів** - інакше він не включить потрібні файли в збірку. --- ## Коли використовувати динамічний імпорт | Сценарій | Чому корисний | |---|---| | **Lazy loading компонентів** | Завантажуємо компонент тільки при переході на потрібну сторінку | | **Переклади / локалізація** | Імпортуємо потрібну мову динамічно | | **Важкі залежності** | Відкладене завантаження великих бібліотек (`chart.js`, `moment`, `three.js`) | | **Плагіни / модульна архітектура** | Підключаємо функціональність за запитом | | **SSR + Code splitting** | У Next.js, Vite, Webpack - автоматичний розрив бандлів | | **Feature flags / A/B тести** | Завантажуємо різні модулі залежно від прапора | --- ## Як це працює під капотом Збирачі (Webpack, Rollup, Vite, ESBuild): 1. Аналізують вирази `import('./path')`. 2. Роблять **code splitting** - розбивають проєкт на чанки. 3. При виклику `import()` завантажують потрібний чанк по мережі. Приклад (Webpack output): ```javascript main.js (основний код) vendors~chart.js (бібліотека) chart.js (завантажиться при кліку) ``` --- ## Відмінність від `require()` | Критерій | `import()` | `require()` | |---|---|---| | Тип | Асинхронний (Promise) | Синхронний | | Працює в | ESM (браузер, Node) | CommonJS (Node) | | Можна використовувати динамічно | Так | Обмежено | | Підтримує tree-shaking | Так | Ні | | Підтримується збирачами (code-splitting) | Так | Ні | --- ## Приклад: у React / Next.js ```javascript import dynamic from 'next/dynamic'; const Chart = dynamic(() => import('../components/Chart'), { ssr: false, loading: () => <p>Завантаження...</p>, }); export default function Page() { return ( <div> <h1>Дані</h1> <Chart /> </div> ); } ``` Компонент `<Chart>` підвантажиться **тільки в браузері**, і **тільки коли користувач відкриє сторінку**. --- ## Підсумок | Що робить | Завантажує модулі асинхронно (за потреби) | |---|---| | Повертає | Promise з об'єктом модуля | | Працює в | ES Modules (Node, браузер) | | Використовується для | Lazy loading, code splitting, A/B тестів, динамічної локалізації | | Синтаксис | `const module = await import('./file.js')` | --- **Головна ідея:** > Динамічний імпорт - це "лінива" завантаження модулів. > Замість того щоб тягнути весь застосунок одразу, ти вантажиш тільки те, що потрібно, коли це потрібно.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.