Файлы с расширением .mjs для модулей JavaScript

Они идут! Вы можете увидеть их в документации по Node.js, а также в Webpack 4 нового бренда. Но ... для чего вы сказали эти файлы .mjs?

.mjs расширение для модулей EcmaScript

Модули - это способ, которым мы пользуемся в JavaScript для разделения кода на разные файлы, сохраняя при этом краткость и хорошо организованный код. Модули могут быть «обязательными» или «импортированными» из других модулей, чтобы мы могли повторно использовать их функции и составлять наши приложения и библиотеки.

require и import - ключевые термины, когда мы говорим о модулях, они определяют два самых популярных способа использования модулей JavaScript в настоящее время.

Требование используется для загрузки модулей CommonJS. Модули CommonJS использовались Node.js с первых дней своего существования, и это очень известный способ инкапсулировать ваш код в файлы. Пример определения модуля CommonJS:

function hi(){ console.log('Hi') };
module.exports = hi;

Вы видите это module.exports = hi? Это то, что наш модуль публично предоставляет для использования. Мы можем сохранить его в файле с именем hi.js, а затем получить доступ к функции hi из других модулей, используя var hi = require('./hi.js').

Импорт - это способ загрузки модулей EcmaScript. Они намного новее, чем CommonJS, но являются стандартом, начиная с ES6, поэтому мы должны привыкнуть к созданию такого рода модулей. Они выглядят так:

function hi(){ console.log('Hi') }
export default hi;

В этом случае функция hi становится общедоступной с помощью export default hi. Модули ES являются целью для файлов с расширением .mjs. Таким образом, мы можем сохранить наш модуль в файле с именем hi.mjs и использовать функцию hi, набрав import hi from './hi.js' из любого другого модуля.

Нужны ли вообще файлы .mjs?

Вы могли подумать, что мы могли бы сохранить модуль ES в файле с именем hi.js и импортировать его в стиле ES, без необходимости в новом расширении.

Вы правы, все так делают. Но мы можем это сделать только потому, что есть хорошие сборщики, такие как webpack, которые вы можете настроить для загрузки модулей ES по умолчанию, поэтому независимо от того, какое расширение имеет файл, вы все равно получите свою hi функцию.

Webpack спасает наши задницы. Благодаря этому мы можем смешивать библиотеки, написанные на модулях CommonJS, с нашим красивым приложением, написанным с использованием классных модулей ES. Однако возможность загрузки обоих типов модулей также вызывает затруднения. Трудно увидеть линию, разделяющую оба типа модулей, иногда просто сбивает с толку использование var hi = require('./hi') для загрузки модуля ES, а затем нам нужно сделать что-то вроде hi.default(), чтобы его вызвать. Мы должны просто остановиться на единственном способе определения модулей.

.mjs файлы - хороший инструмент, чтобы понять, с каким модулем мы работаем. Сейчас они представляют собой нечто большее, чем просто своего рода соглашение: присвоение нашим файлам имен .mjs вместо .js фактически меняет способ обработки файлов интерпретаторами, они ощущаются как новый тип контента.

В Webpack 4 представлены типы модулей, а также тип javascript/esm, активный по умолчанию для .mjs файлов. При загрузке javascript/esm модулей жизнь webpack упрощается, ему больше не нужно угадывать, какой модуль загружается.

Помимо мира сборщиков, использование специального расширения для модулей ES также может иметь последствия:

  • В Node.js загрузчики в настоящее время получают format: 'esm' от перехвата разрешения для .mjs файлов, поэтому они могут обрабатывать эти файлы по-другому.
  • В настоящее время мы можем использовать <script type="module" src="hi.js"> для загрузки модулей ES в современные браузеры. Мы загружаем контент типа модуль, поэтому было бы неплохо, если бы мы просто могли написать <script src="hi.mjs"> и получить то же самое? Однако пока этого не происходит.

Стоит ли нам использовать файлы .mjs?

Это должно быть темой статьи, в которой мы сказали: «Будущее наступило! Не упустите шанс воспользоваться передовыми технологиями! » (Я не совсем уверен, можно ли назвать расширение файла технологией).

Но не все так просто. Как мы видели ранее, изменение расширения ваших .js файлов на .mjs может изменить поведение интерпретатора файлов (веб-пакет, узел, браузер ...), поэтому у нас есть будьте осторожны с этим.

Эта статья началась, потому что я проводил несколько тестов с Inferno.js для проекта PassPill и не мог заставить его работать с webpack 4. Причина в том, что Inferno.js использовал .mjs файлы для упаковки своих модулей, и они смешивали их каким-то образом с другими CommonJS, поэтому webpack просто потерпел неудачу с множеством ошибок:

Can't import the named export 'render' from non EcmaScript module

Or

Can't reexport the named export 'Component' from non EcmaScript module

Inferno.js готовит выпуск новой основной версии, и он больше не будет использовать .mjs файлы.

Но проблема возникла не только для inferno.js. После небольшого поиска я обнаружил множество больших библиотек, у которых есть проблемы с .mjs файлами. Проблема всегда заключается в попытке получить от них доступ к модулям, отличным от ES. Некоторыми примерами таких библиотек являются create-react-app, react-apollo или graphql-js.

Если мы решим использовать расширение .mjs прямо сейчас, нам нужно иметь в виду, что, изменив расширение, мы можем изменить способ компиляции модуля и, если у нас есть зависимости, которые не определены как модули ES, мы столкнемся с проблемами.

В случае, если наш проект не имеет зависимостей CommonJS и мы можем построить его, используя только модули ES, дерзайте! Они будут изначально понятны новейшим Node.js, Webpack объединит их намного быстрее и, возможно, в будущем браузер будет загружать их автоматически как модули.

.mjs оказался чем-то большим, чем расширение, поэтому нам нужно быть внимательными, прежде чем начинать изменять имена наших файлов.

Эта статья является частью Проекта PassPill, который хочет поделиться всей разработкой веб-приложения. Фактически, это первая статья, которая не имеет прямого отношения к проекту или разработке приложения, но всегда приятно писать на интересные темы JavaScript. Таких еще будет.

Если вам понравился пост, не забудьте следить за нашей публикацией и @passpillio в твиттере, чтобы не пропустить ни одного обновления!