ECMAScript-модули в Node.js: новый план
Текущий статус поддержки ECMAScript-модулей (ESM) в Node.js:
- Экспериментальная поддержка ESM [1] была добавлена в Node.js 8.5.0 [2] 12 сентября 2017 года.
- После этого Технический Руководящий Комитет Node.js сформировал команду, ответственную за модули (Modules Team [3]), чтобы она помогла спроектировать недостающие части для грядущего (не экспериментального) релиза. Эта команда состоит из людей из различных отраслей веб-разработки (фронтенд, бекенд, JS-движки, и т.д.).
В октябре Modules Team опубликовала "План по реализации Новых Модулей" [4]. Этот пост объясняет, что в нем содержится.
Фазы
Процесс разделен на три фазы:
- Фаза 1: создать "минимальное" ядро – основной набор правил и возможностей, минимальных и бесспорных, насколько это возможно.
- Фаза 2 и далее: создание на основе ядра более сложной функциональности.
Минимальное ядро будет основой для последующей работы. Новый дизайн также заменит текущую экспериментальную реализацию, как только обзаведется аналогичными возможностями.
Фаза 1: минимальное ядро поддержки ESM в Node.js
Упрощение идентификаторов модулей
Одна из целей Modules Team это достижение "браузерной эквивалентности" [5]: Node.js должна быть близка по поведению к браузерам, насколько это возможно. Ядро достигает этого путем упрощения разбора идентификаторов модулей (URL-ов, указывающих на модули):
- Каждый идентификатор модуля должен заканчиваться именем файла с расширением. То есть
- Расширения не добавляются автоматически
- Импортирование директорий не поддерживается (ни через перенаправление на
dir/index.mjs
, ни чтение поля main
в package.json
).
- ES modules могут импортировать встроенные Node.js-модули (
path
и подобные). Они являются единственным исключением из предыдущего правила.
- По умолчанию поддерживаются только файлы с расширением
.mjs
(смотрите Фазу 2, если вам интересен статус других расширений). Таким образом, другие виды модулей не смогут быть импортированы через import
: модули CommonJS, JSON-файлы, нативные модули.
Принесение важных возможностей CommonJS в ES-модули
- URL текущего модуля (аналогично
__filename
из CommonJS): import.meta.url [6]
- Динамический импорт ES-модулей (доступен через
require()
в CommonJS): оператор import()
[7]
Совместимость
- ES-модули смогут импортировать CommonJS-модули через
createRequireFromPath()
[8]. Это будет работать следующим образом (есть планы сделать сокращенный способ, например, функцию createRequireFromUrl()
):
import {createRequireFromPath as createRequire} from 'module';
import {fileURLToPath as fromPath} from 'url';
const require = createRequire(fromPath(import.meta.url));
const cjsModule = require('./cjs-module.js');
- CommonJS-модули смогут загружать ES-модули через
import()
.
Фаза 2 и дальнейшие планы
- Во второй фазе нас ждет:
- Поддержка "bare" индентификаторов, таких как
'lodash'
. Скорее всего, это включит в себя некоторый способ маппинга этих идентификаторов на реальные пути.
- Поддержка других расширений файлов, помимо
.mjs
. Это включает в том числе и поддержку ES-модулей в .js
файлах.
- Фаза 3, скорее всего, сосредоточится на загрузчиках модулей с точками расширения, в которых пользователи смогут подключить свою логику.
Когда я смогу пользоваться ES-модулями в Node.js?
- За флагом: доступно уже сейчас [1]
- Внимание: поведение еще не соответствует описанному выше в фазе 1 (по состоянию на Node.js 11.5.0)
- Без флага и в соотвествии с фазой 1: Modules Team старается сделать это возможным как можно скорее. Надеемся, что модули выпустят из под флага в Node.js 14 (апрель 2020 года) и портируют в предыдущие версии, если это будет возможно.
Часто задаваемые вопросы
- Зачем нужно новое расширение файлов
.mjs
?
- Каждое решение по различению форматов ESM и CommonJS имеет свои преимущества и недостатки. Использование отдельного разрешения кажется неплохим вариантом (больше информации [9]).
- Почему поведение Node.js должно быть похожим на браузерное?
- Потому что это делает возможным переиспользование кода. Например, чтобы создавать библиотеки, которые работают одновременно и в браузерах, и в Node.js
- Также это должно облегчить переключение между бекендом и фронтендом во время кодинга.
- К чему все эти ограничения в целях совместимости?
- Между ES и CommonJS-модулями есть довольно сильные отличия в структуре (статическая против динамической) и способе загрузки (асинхронная против синхронной). Ограничения помогают сохранить порядок вещей простым – учитывая, что в долгосрочной перспективе подавляющим большинством будут ES-модули.
- Почему это все тянется так долго?
- Здесь участвует много заинтересованных сторон и вовлечено много разных платформ (Node.js, npm, браузеры, JS-движки, TypeScript, TC39 и другие). Если мы действительно получим ES-модули, способные работать везде, наверное, это стоит ожидания, ИМХО.
Благодарность
Спасибо Майлсу Боринсу за его отзывы об этом посте.
Дополнительные источники для дальнейшего чтения
Автор: justboris
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/303036
Ссылки в тексте:
[1] Экспериментальная поддержка ESM: https://nodejs.org/api/esm.html
[2] Node.js 8.5.0: https://nodejs.org/en/blog/release/v8.5.0/
[3] Modules Team: https://github.com/nodejs/modules
[4] "План по реализации Новых Модулей": https://github.com/nodejs/modules/blob/master/doc/plan-for-new-modules-implementation.md
[5] "браузерной эквивалентности": https://github.com/nodejs/modules/issues/133
[6] import.meta.url: http://2ality.com/2017/11/import-meta.html
[7] оператор import()
: http://2ality.com/2017/01/import-operator.html
[8] createRequireFromPath()
: https://nodejs.org/api/modules.html#modules_module_createrequirefrompath_filename
[9] больше информации: http://2ality.com/2017/05/es-module-specifiers.html#why-new-extension
[10] "Модули": http://exploringjs.com/impatient-js/ch_modules.html
[11] моем предыдущем посте: http://2ality.com/2017/09/native-esm-node.html
[12] Источник: https://habr.com/post/433964/?utm_campaign=433964
Нажмите здесь для печати.