Модули: import / export
Named или default, динамический импорт, tree shaking и barrel-файлы.
Обновлено
Что такое модуль
Модуль — файл JS со своей областью видимости: переменные и функции в нём приватны, пока вы явно их не экспортируете. Другой файл использует их через import.
Зачем: без модулей весь код жил бы в одном глобальном пространстве — конфликты имён, скрытые зависимости, поддерживать невозможно. С модулями каждый файл ясно объявляет, что он даёт и что ему нужно.
// math.js
const secret = 42 // приватно — не экспортировано
export const sum = (a, b) => a + b // публично
// app.js
import { sum } from './math.js'
sum(1, 2)Виды экспорта
| Вид | Синтаксис экспорта | Синтаксис импорта | Сколько в файле |
|---|---|---|---|
| named | export const sum = ... |
import { sum } from './math' |
сколько угодно |
| default | export default function Page() {} |
import Page from './page' (любое имя) |
один |
| реэкспорт | export { sum } from './math' |
— | — |
import multiply, { sum, avg as average } from './math.js' // default + named + переименование
import * as math from './math.js' // всё сразу, как объектNamed или default — когда
| Named | Default | |
|---|---|---|
| Имя при импорте | фиксированное — везде одинаковое | выбираете сами — может отличаться в каждом файле |
| Рефакторинг, автодополнение, поиск | лучше | хуже |
| Где обязателен | — | page.tsx, layout.tsx, next.config.ts в Next |
Рекомендация: named-экспорты для всего своего кода; default — только там, где требует фреймворк.
Статический и динамический импорт
import x from (статический) |
await import() (динамический) |
|
|---|---|---|
| Когда загружается | при старте, до выполнения кода | по требованию, когда дойдёте до этой строки |
| Где | только вверху файла | где угодно (в функциях, условиях) |
| Для | почти всего | тяжёлого редко используемого кода: редакторы, графики, карты |
button.onclick = async () => {
const { Chart } = await import('./chart.js') // скачивается только по клику
}В Next: next/dynamic делает то же для компонентов — именно так загружается редактор кода в этом приложении.
Tree shaking
Tree shaking = сборщик удаляет из бандла экспорты, которые никто не импортирует. Работает только со статическими import/export.
import { debounce } from 'lodash-es' // ✓ в бандл попадёт только debounce
import _ from 'lodash' // ✗ в бандл попадёт вся библиотекаBarrel-файлы
Barrel — это index.ts, который только реэкспортирует другие файлы (export * from './a'). Кажется удобным, но:
- импорт одной вещи загружает всё, что реэкспортирует barrel;
- замедляет dev-сервер и тесты;
- легко создаёт циклические импорты.
В нашем проекте мы импортируем напрямую из файла — см. Feature-Sliced Design.
ESM и CommonJS
| ES Modules (ESM) | CommonJS (CJS) | |
|---|---|---|
| Синтаксис | import / export |
require() / module.exports |
| Где | браузер, Next, современный Node | старый Node, некоторые библиотеки |
| Статичность (tree shaking) | да | нет |
Пишете на ESM. CJS встретите только в старых конфигурациях.
Коротко
- Модуль = файл со своей областью видимости; экспортируете то, что публично.
- Named-экспорты по умолчанию; default — только где требуется.
- Динамический импорт для тяжёлого кода; tree shaking — только со статическими импортами; избегайте barrel-файлов.