На самом деле нет одних ES-модулей — есть 3 разных технологий: модули в браузере, в Node.js и в сборщиках. И они не очень совместимы между собой.
Тред про всю правду о ES-модулей ↓
— «с ESM нам не нужны сборщики»
— «с ESM можно использовать npm-пакеты сразу в браузере»
— «ESM уже готовы для использования в npm-пакетах»
Попробую объяснить их текущие ограничения в этом треде.
import { throttle } from 'throttle-debounce'
Модули в браузере загружаются только по прямому пути:
import { throttle } from './node_modules/throttle-debounce/index.mjs'
chromestatus.com/feature/531528…
Ну и HTTP/2 не решает проблему задержки каждого запроса. Если a.js грузит b.js, а b.js — c.js то без <link rel="preload"> будет до 500мс задержки на каждый такой переход вглубь дерева зависимостей.
Поэтому большинство ES-модулей из npm не работают в браузере.
Но CDN убивает многие плюсы HTTP/2, ваше приложение сломается при падении CDN, и не решается проблема 500 мс задержи при запросах.
Плохо для продакшена, но нормально для экспериментов.
В отличии от браузера, позволяют грузить по не прямому пути. Но так же не работает __dirname.
import { dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url))
Есть Conditional Exports, но их применение будет печатать в консоль предупреждение, даже при require().
nodejs.org/api/esm.html#e…
import nanevents from 'nanoevents/index.mjs'
github.com/ai/nanoevents/…
К сожалению, многие JS-разработчики думают, что ESM в сборщиках и есть ESM.
Так же Вебпак разрешает __dirname и деструкторы в импорте CommonJS-модуля, хотя в Node.js ESM их нельзя использовать.
Но это работает только для корневого файла. Если в вашем пакете несколько файлов, то их надо класть в папки и в каждый добавлять package.json со своими main/module.
1. Сейчас нет способа сделать двойной ESM/CommonJS модуль с простым импортом. Для сборщиков хоть есть грязный хак с папками и отдельными package.json, а для Ноды надо добавлять index.mjs. Для браузера всё равно всегда указывать полный путь.
3. Сборщики для ESM будут нужны для генернации Imports Maps, <link rel="preload"> и конвертации CommonJS-пакетов.
github.com/ai/dual-publis…
Он учитывает все особенности как ESM в сборщиках, так и в ESM в Node.js и в браузерах.
Мне не нравится их маркетинг, но они единственные, кто предлагают новые идеи в сборщиках. Хоть ESM не избавляет от сборщика, но позволяет сборщики упростить.