- PVSM.RU - https://www.pvsm.ru -

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