Модули: введение

Модули: введение #

Модуль — отдельный файл JavaScript со своей областью видимости. Другие файлы подключают его через import и получают только то, что модуль явно экспортировал. Так код делят на независимые части без глобальных конфликтов имён.


Зачем модули #

Без модулейС модулями
Всё в глобальной области windowПеременные по умолчанию локальны для файла
Порядок <script> критиченЗависимости описаны в import
Сложно переиспользовать в проектеФайл = единица публикации API
Риск коллизий utils, configИмена экспорта контролируются явно
// cart.js — только экспорт виден снаружи
const taxRate = 0.2

export function lineTotal(price, qty) {
  return price * qty * (1 + taxRate)
}

taxRate снаружи cart.js недоступен — не засоряет глобальную область.


ES-модули (ESM) #

Современный стандарт — ECMAScript modules (ключевые слова import / export). Старые форматы (CommonJS require в Node, IIFE-бандлы) встречаются в legacy-проектах; в JSFlow опираемся на ESM.

Особенности ESM:

  • Строгий режим включён всегда ("use strict" не нужен).
  • Импорты и экспорты разрешены только на верхнем уровне файла (не внутри if на верхнем уровне — для ветвления есть import()).
  • Модули defer: в браузере выполняются после разбора HTML, в предсказуемом порядке графа зависимостей.
  • Повторный импорт одного URL кэшируется — модуль выполняется один раз.

type=“module” в браузере #

Подключение ES-модуля в HTML:

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

Отличия от обычного <script>:

Атрибут / поведениеtype="module"классический script
deferда, по умолчаниютолько с атрибутом defer
import / exportдасинтаксическая ошибка
областьмодульнаяглобальная (если не IIFE)
CORSда, для файлов с другого originзависит от сценария

Точка входа приложения — один main.js, который импортирует остальное:

// main.js
import { initCheckout } from './checkout.js'
import { bindPlaylistUI } from './playlist-panel.js'

initCheckout()
bindPlaylistUI()

Пути в import должны быть относительными (./, ../) или полными URL; голое имя 'lodash' не резолвится браузером без import map (отдельная тема).


Модуль vs обычный скрипт #

<!-- глобальный побочный эффект -->
<script src="/legacy/analytics.js"></script>

<!-- модульная точка входа -->
<script type="module" src="/js/app.js"></script>

Сторонние библиотеки без ESM часто подключают бандлером (Vite, webpack) или через CDN с готовым export.


Node.js #

В Node файлы с расширением .mjs или "type": "module" в package.json трактуются как ESM. Синтаксис import/export тот же; отличия в резолве путей и взаимодействии с CommonJS — см. документацию Node для смешанных проектов.


Итог #

  • Модуль инкапсулирует код и отдаёт наружу только export.
  • ESM — стандарт для новых браузерных и многих Node-проектов.
  • В HTML модули подключают через <script type="module">.
  • Зависимости между файлами задаются явно, а не порядком тегов <script>.

См. также #