Импорт модулей в JavaScript: синтаксис, примеры и особенности

Раздел: Веб-разработка -> Подключение скриптов и модули

Основы импорта модулей в JavaScript

Модульная система ES6 (ECMAScript 2015) позволяет разбивать код на отдельные файлы и импортировать только необходимые части. Основной способ - статический импорт с ключевым словом import. Он выполняется на этапе анализа кода до его выполнения, что позволяет сборщикам оптимизировать бандлы.

Как сделать статический импорт по стандарту ES6?

Создайте модуль math.js, который экспортирует функции:

// math.js
export function add(a, b) { return a + b; }
export const PI = 3.14159;

Js import (импорт модулей в javascript)

Затем импортируйте их в main.js:

// main.js
import { add, PI } from './math.js';
console.log(add(2, 3));      // 5
console.log(PI);             // 3.14159

Для использования модулей в браузере добавьте атрибут type="module" к тегу <script>:

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

Проблема: Ошибка "Cannot use import statement outside a module" в браузере.

Решение: Убедитесь, что в HTML тег <script> содержит type="module".

Как импортировать только одну сущность, переименовав её?

Используйте псевдоним (as). Пример из того же модуля:

import { add as sum } from './math.js';
console.log(sum(4, 5)); // 9

Позволяет избежать конфликта имён.

Как импортировать все экспорты модуля в один объект?

Используйте import * as:

import * as math from './math.js';
console.log(math.add(1, 2)); // 3
console.log(math.PI);        // 3.14159

Удобно, когда нужно много функций из одного модуля.

Как загрузить модуль только при необходимости (динамический импорт)?

Функция import() возвращает Promise и позволяет загружать код асинхронно:

// main.js
const module = await import('./math.js');
console.log(module.add(10, 20)); // 30

Используется для ленивой загрузки, например, при нажатии кнопки.

Проблема: Ошибка при динамическом импорте из-за неправильного пути.

Решение: Проверьте относительный путь от расположения вызывающего скрипта. В браузере путь указывается относительно HTML-документа, если используется type="module" без указания src.

Как повторно экспортировать импортированные сущности (реэкспорт)?

В промежуточном модуле можно объединить экспорты:

// index.js
export { add, PI } from './math.js';
// или с псевдонимом
export { add as sum } from './math.js';

Позволяет создавать «баррель» (barrel) файлы.

Как импортировать модуль с дефолтным экспортом?

Модуль может иметь один дефолтный экспорт:

// greet.js
export default function(name) { return `Привет, ${name}!`; }

Импорт без фигурных скобок:

import greet from './greet.js';
console.log(greet('Мир')); // Привет, Мир!

Проблема: Ошибка при попытке импортировать дефолтный экспорт в фигурных скобках.

Решение: Для дефолтного экспорта используйте import anyName from 'module' без фигурных скобок.

Цели и случаи использования

  • Статический импорт - основной способ для зависимостей, известных на этапе сборки.
  • Динамический импорт - для ленивой загрузки больших фрагментов, роутинга, условной загрузки.
  • Псевдонимы - устраняют конфликты имён и дают более короткие имена.
  • Import * as - когда нужен доступ ко всем экспортам модуля без явного перечисления.
  • Реэкспорт - упрощает публичный API библиотеки или приложения.

Расширенные примеры импорта модулей с пояснениями

Пример 1: Статический импорт с использованием псевдонимов и комбинированных экспортов

Пример
// utils.js
export function toUpperCase(str) { return str.toUpperCase(); }
export const version = '1.0';
export default class Logger {
  log(msg) { console.log(msg); }
}
Пример
// app.js
import Logger, { toUpperCase as upper, version } from './utils.js';

const logger = new Logger();
logger.log(upper('hello'));        // HELLO
console.log('Версия', version);    // Версия 1.0
// Вывод в консоль:
// HELLO
// Версия 1.0

Пример 2: Динамический импорт с обработкой ошибок

Пример
// config.js (удалённый модуль)
export const apiUrl = 'https://api.example.com';

// main.js
document.getElementById('loadBtn').addEventListener('click', async () => {
  try {
    const config = await import('./config.js');
    console.log('URL:', config.apiUrl);
  } catch (err) {
    console.error('Не удалось загрузить модуль:', err);
  }
});
// После клика на кнопку:
// URL: https://api.example.com

Пример 3: Импорт всех экспортов как объект и деструктуризация

Пример
// shapes.js
export function circleArea(r) { return Math.PI * r * r; }
export function squareArea(s) { return s * s; }
export const shapeNames = ['circle', 'square'];
Пример
// calc.js
import * as shapes from './shapes.js';

const { circleArea, squareArea } = shapes;
console.log(circleArea(5).toFixed(2));  // 78.54
console.log(squareArea(4));             // 16
// Вывод:
// 78.54
// 16

Пример 4: Реэкспорт и создание «баррель» файла

Пример
// db/tables.js
export function createUsersTable() { /* ... */ }
export function createPostsTable() { /* ... */ }

// db/index.js (реэкспорт)
export { createUsersTable, createPostsTable } from './tables.js';

// app.js
import { createUsersTable } from './db/index.js';
createUsersTable();

Такой подход скрывает структуру папок и упрощает импорты.

Пример 5: Импорт модуля с другим именем дефолтного экспорта

Пример
// myModule.js
export default function sayHello(name) {
  return `Привет, ${name}!`;
}

// other.js
import hello from './myModule.js';
console.log(hello('Вася')); // Привет, Вася!
// Привет, Вася!

Пример 6: Типичная ошибка - несоответствие между импортом и экспортом

Пример
// bad.js
export const value = 42;

// main.js
import { Value } from './bad.js'; // Ошибка! Value не экспортируется (регистр)

Ошибка: Модуль './bad.js' не экспортирует 'Value'. Решение: проверьте регистр и имя экспорта.

Пример 7: Использование import.meta.url для получения пути текущего модуля

Пример
// utils.js
console.log('Текущий файл:', import.meta.url);

// main.js
import './utils.js';
// В консоли (при запуске через сервер):
// Текущий файл: http://localhost:3000/utils.js

Полезно для построения динамических путей к ресурсам.

Импорт модулей в JavaScript - comments

En
Js import (javascript)