«Если рабочий хочет хорошо выполнять свою работу, он должен сначала заточить свои инструменты» — Конфуций, «Аналитики Конфуция. Лу Лингун»
титульная страница > программирование > О, CommonJS! Почему ты со мной переписываешься?! Причины отказаться от CommonJS

О, CommonJS! Почему ты со мной переписываешься?! Причины отказаться от CommonJS

Опубликовано 29 июля 2024 г.
Просматривать:344

Это был обычный день установки патчей. Я исправил и обновил свои зависимости npm, не внося изменений в код, и внезапно некоторые из моих модульных тестов провалились.
Oh CommonJS! Why are you mESMing with me?! Reasons to ditch CommonJS

Что за фигня!

Oh CommonJS! Why are you mESMing with me?! Reasons to ditch CommonJS

Мои тесты провалились, поскольку Jest обнаружил неожиданный токен; они потерпели неудачу, потому что Jest не может обрабатывать пакеты только для ESM «из коробки». На самом деле Jest написан на CommonJS.
Но что это значит? Для этого нам нужно понять, почему существуют CommonJS и ESM.

Зачем нам нужны модульные системы?

На заре веб-разработки JavaScript в основном использовался для управления объектной моделью документа (DOM) с помощью таких библиотек, как jQuery. Однако появление Node.js также привело к использованию JavaScript для серверного программирования. Этот сдвиг увеличил сложность и размер баз кода JavaScript. В результате возникла потребность в структурированном методе организации кода JavaScript и управления им. Для удовлетворения этой потребности были введены модульные системы, позволяющие разработчикам разделить свой код на управляемые, повторно используемые блоки1.

Появление CommonJS

CommonJS был создан в 2009 году и первоначально назывался ServerJS2. Он был разработан для серверного JavaScript и предоставляет соглашения для определения модулей. Node.js принял CommonJS в качестве системы модулей по умолчанию, что сделало его широко распространенным среди разработчиков серверной части JavaScript. CommonJS использует require для импорта и модуль.exports для экспорта модулей. Все операции в CommonJS синхронны, то есть каждый модуль загружается индивидуально.

Расцвет ESM (модули ECMAScript)

В 2015 году ECMAScript представил новую систему модулей под названием ECMAScript Modules (ESM), предназначенную в первую очередь для разработки на стороне клиента. ESM использует операторы импорта и экспорта, а его операции являются асинхронными, что позволяет загружать модули параллельно3. Изначально ESM предназначался для браузеров, а CommonJS — для серверов. Он все больше и больше становился стандартом для экосистемы JS. В настоящее время современные среды выполнения JavaScript поддерживают обе системы модулей. Браузеры начали поддерживать ESM изначально в 2017 году. Даже Typescript адаптировал синтаксис ESM, и всякий раз, когда вы его изучаете, вы также изучаете ESM подсознательно.

How Are you not dead.jpg

CommonJS здесь, чтобы остаться

Правда в том, что пакетов, предназначенных только для CommonJS (CJS), гораздо больше, чем пакетов, предназначенных только для ESM4.
Oh CommonJS! Why are you mESMing with me?! Reasons to ditch CommonJS
Однако существует четкая тенденция. Количество пакетов только для ESM или пакетов с двумя модулями растет, в то время как пакетов только для CJS создается все меньше. Эта тенденция подчеркивает растущее предпочтение ESM и поднимает вопрос о том, сколько пакетов, предназначенных только для CJS, активно поддерживается.

Сравнение

Интересное сравнение CommonJS и ESM включает в себя тесты производительности. Благодаря своей синхронной природе CommonJS работает быстрее при непосредственном использовании операторов require и import. Давайте рассмотрим следующий пример:

// CommonJS -> s3-get-files.cjs
const s3 = require('@aws-sdk/client-s3');
new s3.S3Client({ region: 'eu-central-1' });

// ESM -> s3-get-files.mjs
import { S3Client } from '@aws-sdk/client-s3';

new S3Client({ region: 'eu-central-1' });

Я использовал aws-sdk S3-Client, поскольку он поддерживает два модуля. Здесь мы создаем экземпляр клиента, а затем выполняем его с помощью node:

hyperfine --warmup 10 --style color 'node s3-get-files.cjs' 'node s3-get-files.mjs'

Benchmark 1: node s3-get-files.cjs
Time (mean ± σ): 82.6 ms ± 3.7 ms [User: 78.5 ms, System: 16.7 ms]
Range (min … max): 78.0 ms … 93.6 ms 37 runs
Benchmark 2: node s3-get-files.mjs
Time (mean ± σ): 93.9 ms ± 4.0 ms [User: 98.3 ms, System: 18.1 ms]
Range (min … max): 88.1 ms … 104.8 ms 32 runs

Summary
node s3-get-files.cjs ran
  1.14 ± 0.07 times faster than node s3-get-files.mjs

Как видите, s3-get-files.cjs и, следовательно, CommonJS работают быстрее.
Меня вдохновила публикация в блоге Buns.

Однако, если вы хотите создать свою JS-библиотеку, вам необходимо объединить ее. В противном случае вы отправите все node_modules. Используется esbuild, поскольку его можно связывать с CJS и ESM. Теперь давайте проведем тот же тест для встроенной версии.

hyperfine --warmup 10 --style color 'node s3-bundle.cjs' 'node s3-bundle.mjs'

Benchmark 1: node s3-bundle.cjs
Time (mean ± σ): 62.1 ms ± 2.5 ms [User: 53.8 ms, System: 6.7 ms]
Range (min … max): 59.5 ms … 74.5 ms 45 runs

Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.

Benchmark 2: node s3-bundle.mjs
Time (mean ± σ): 45.3 ms ± 2.2 ms [User: 38.1 ms, System: 5.6 ms]
Range (min … max): 43.0 ms … 59.2 ms 62 runs

Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.

Summary

  node s3-bundle.mjs ran
    1.37 ± 0.09 times faster than node s3-bundle.cjs

Как видите, s3-bundle.mjs теперь быстрее, чем s3-bundle.cjs. Файл ESM теперь работает даже быстрее, чем отдельный файл CommonJS, поскольку он приводит к меньшему размеру файла и более быстрому времени загрузки благодаря эффективному встряхиванию дерева — процессу, который удаляет неиспользуемый код.

Примите ЕСМ!

Будущее модулей JavaScript, несомненно, склоняется к ESM. Это начинается при создании нового проекта NodeJS или даже проекта React. В каждом учебнике и статье используется оператор импорта, который, таким образом, является ESM. Несмотря на множество существующих пакетов CommonJS, тенденция меняется по мере того, как все больше разработчиков и сопровождающих принимают ESM из-за его преимуществ в производительности и современного синтаксиса. Другой вопрос также в том, сколько из этих проектов, предназначенных только для CJS, все еще поддерживаются.

ESM — это стандарт, который работает в любой среде выполнения, например NodeJS, Bun или Deno, а также в браузере без запуска на сервере. Нет необходимости конвертировать через Babel в CommonJS, поскольку браузер понимает ESM. Вы по-прежнему можете использовать Babel для преобразования в другую версию ECMAScript, но не следует конвертировать в CJS.

Вам следует разрабатывать только с использованием ESM, потому что каждая среда выполнения и браузер новее 2017 года понимают ESM.

Если ваш код не работает, возможно, у вас проблемы с устаревшими версиями. Рассмотрите возможность использования других инструментов или пакетов. Например, вы можете перейти с Jest на vitest или с ExpressJS на h3. Синтаксис остается прежним; единственная разница — это оператор импорта.

Основные выводы:

  • Меньшие пакеты: ESM создает меньшие пакеты посредством встряхивания дерева, что приводит к более быстрой загрузке.
  • Универсальная поддержка: ESM изначально поддерживается браузерами и средами выполнения JavaScript (Node.js, Bun, Deno).
  • Готовность к будущему: благодаря постоянному внедрению ESM позиционируется как стандарт для современных модулей JavaScript.

Чтобы начать, вы можете следовать этой Gist или получить вдохновляющую информацию здесь.

Для лучшего будущего JavaScript используйте ESM!

Презентация

Дополнительные ресурсы

  • https://dev.to/logto/migrate-a-60k-loc-typescript-nodejs-repo-to-esm-and-testing-become-4x-faster-22-4a4k
  • https://jakearchibald.com/2017/es-modules-in-browsers/
  • https://gist.github.com/joepie91/bca2fda868c1e8b2c2caf76af7dfcad3
  • https://gist.github.com/joepie91/bca2fda868c1e8b2c2caf76af7dfcad3

  1. https://www.freecodecamp.org/news/javascript-es-modules-and-module-bundlers/#why-use-modules ↩

  2. https://deno.com/blog/commonjs-is-hurting-javascript ↩

  3. https://tc39.es/ecma262/#sec-overview ↩

  4. https://twitter.com/wooorm/status/1759918205928194443 ↩

Заявление о выпуске Эта статья воспроизведена по адресу: https://dev.to/jolodev/oh-commonjs-why-are-you-mesming-with-me-reasons-to-ditch-commonjs-enh?1 Если есть какие-либо нарушения, пожалуйста, свяжитесь с Study_golang@163 .comdelete
Последний учебник Более>

Изучайте китайский

Отказ от ответственности: Все предоставленные ресурсы частично взяты из Интернета. В случае нарушения ваших авторских прав или других прав и интересов, пожалуйста, объясните подробные причины и предоставьте доказательства авторских прав или прав и интересов, а затем отправьте их по электронной почте: [email protected]. Мы сделаем это за вас как можно скорее.

Copyright© 2022 湘ICP备2022001581号-3