Kodokon kodokon.com

ES-модули: import/export, структура проекта

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

8 мин · 3 вопросов

Открыть этот урок в Kodokon

ES-модули статичны: инструкции import и export разрешаются при разборе файла, ещё до запуска кода. Именно это делает возможным tree-shaking (удаление кода, который никогда не импортируется) и отлов ошибок в именах на этапе сборки. Именованные экспорты или экспорт по умолчанию? Именованные выигрывают почти по всем фронтам: удобное переименование при рефакторинге, надёжное автодополнение и никакой возможности импортировать одно и то же под десятью разными именами. Прибереги default для случая, когда модуль экспортирует одну очевидную вещь.

JAVASCRIPT
export const TAX_RATE = 0.2;

export function applyTax(price) {
  return price * (1 + TAX_RATE);
}

export default class Cart {
  items = [];
  add(item) {
    this.items.push(item);
    return this;
  }
}
cart.js: именованные экспорты для утилит, default для центрального класса.

На стороне потребителя четыре формы: именованный импорт (с необязательным псевдонимом через as), импорт по умолчанию, импорт пространства имён (* as) и динамический импорт import(), который возвращает промис с пространством имён. Последний - строительный блок разделения кода: тяжёлый модуль (редактор, график, PDF) загружается только в тот момент, когда он реально нужен пользователю.

JAVASCRIPT
import Cart, { applyTax, TAX_RATE } from "./cart.js";
import * as cartModule from "./cart.js";

console.log(applyTax(100), TAX_RATE); // 120 0.2
console.log(cartModule.TAX_RATE); // 0.2

const lazy = await import("./cart.js");
const cart = new lazy.default();
console.log(cart instanceof Cart); // true
Статические формы и динамический импорт одного и того же модуля.

Для организации предпочитай деление по функциональности (features/cart/, features/auth/), а не по техническому типу (controllers/, helpers/): код, который меняется вместе, лежит вместе, и удалить функциональность - это удалить одну папку. Открывай каждую функциональность через узкую точку входа и считай любой импорт в обход этой точки нарушением границы.

Проверка знаний

Убедись, что запомнил ключевые моменты этого урока.

  1. Что делает tree-shaking возможным с ES-модулями?
    • Сборщики выполняют код, чтобы увидеть, что используется
    • Импорты и экспорты статичны и анализируются без запуска кода
    • ES-модули автоматически сжимают мёртвый код
  2. Что возвращает выражение import("./module.js")?
    • Пространство имён модуля, синхронно
    • Промис, разрешённый пространством имён модуля
    • Функцию, которая загружает модуль при вызове
    • Только экспорт по умолчанию из модуля
  3. В чём главный риск файлов-бочек (index, который переэкспортирует целую папку)?
    • Они делают именованные экспорты невозможными
    • Они могут загрузить всю папку ради одного импорта и мешают tree-shaking
    • Они не дают динамически импортировать папку