"Se um trabalhador quiser fazer bem o seu trabalho, ele deve primeiro afiar suas ferramentas." - Confúcio, "Os Analectos de Confúcio. Lu Linggong"
Primeira página > Programação > Ah, CommonJS! Por que você está mesMando comigo?! Razões para abandonar o CommonJS

Ah, CommonJS! Por que você está mesMando comigo?! Razões para abandonar o CommonJS

Publicado em 2024-07-29
Navegar:991

Foi um dia normal de patch. Corrigi e atualizei minhas dependências npm sem fazer alterações no código e, de repente, alguns de meus testes de unidade falharam.
Oh CommonJS! Why are you mESMing with me?! Reasons to ditch CommonJS

Que merda!

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

Meus testes falharam porque Jest encontrou um token inesperado; eles falharam porque Jest não consegue lidar com pacotes somente ESM prontos para uso. Na verdade, Jest está escrito em CommonJS.
Mas o que isso significa? Para fazer isso, precisamos entender por que existem CommonJS e ESM.

Por que precisamos de sistemas modulares?

Nos primeiros dias do desenvolvimento web, JavaScript era usado principalmente para manipular o Document Object Model (DOM) com bibliotecas como jQuery. No entanto, a introdução do Node.js também fez com que o JavaScript fosse usado para programação no lado do servidor. Essa mudança aumentou a complexidade e o tamanho das bases de código JavaScript. Como resultado, surgiu a necessidade de um método estruturado para organizar e gerenciar o código JavaScript. Sistemas de módulos foram introduzidos para atender a essa necessidade, permitindo que os desenvolvedores dividissem seu código em unidades gerenciáveis ​​e reutilizáveis1.

O surgimento do CommonJS

CommonJS foi criado em 2009, originalmente denominado ServerJS2. Ele foi projetado para JavaScript do lado do servidor, fornecendo convenções para definição de módulos. O Node.js adotou o CommonJS como seu sistema de módulos padrão, tornando-o predominante entre os desenvolvedores back-end de JavaScript. CommonJS usa require para importar e module.exports para exportar módulos. Todas as operações em CommonJS são síncronas, o que significa que cada módulo é carregado individualmente.

A ascensão do ESM (módulos ECMAScript)

Em 2015, ECMAScript introduziu um novo sistema de módulos chamado ECMAScript Modules (ESM), visando principalmente o desenvolvimento do lado do cliente. O ESM usa instruções de importação e exportação e suas operações são assíncronas, permitindo que os módulos sejam carregados em paralelo3. Inicialmente, o ESM foi projetado para navegadores, enquanto o CommonJS foi projetado para servidores. Tornou-se cada vez mais um padrão para o ecossistema JS. Hoje em dia, os tempos de execução modernos de JavaScript suportam ambos os sistemas de módulos. Os navegadores começaram a oferecer suporte nativo ao ESM em 2017. Até o Typescript adaptou a sintaxe do ESM e, sempre que você a aprende, também aprende o ESM inconscientemente.

How Are you not dead.jpg

CommonJS veio para ficar

A verdade é que existem muito mais pacotes somente CommonJS (CJS) do que pacotes somente ESM4.
Oh CommonJS! Why are you mESMing with me?! Reasons to ditch CommonJS
No entanto, há uma tendência clara. O número de pacotes somente ESM ou de módulo duplo está aumentando, enquanto menos pacotes somente CJS estão sendo criados. Esta tendência sublinha a preferência crescente pelo ESM e levanta a questão de quantos pacotes exclusivos do CJS são ativamente mantidos.

Comparação

Uma comparação interessante entre CommonJS e ESM envolve benchmarks de desempenho. Devido à sua natureza síncrona, o CommonJS é mais rápido ao usar diretamente instruções require e import. Vamos considerar o seguinte exemplo:

// 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' });

Eu usei o aws-sdk S3-Client porque ele tem suporte para módulo duplo. Aqui instanciamos o cliente e depois o executamos com 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

Como você pode ver, o s3-get-files.cjs e, portanto, o CommonJS rodam mais rápido.
Me inspirei no Buns Blogpost.

No entanto, quando você deseja produzir sua biblioteca JS, você precisa agrupá-la. Caso contrário, você enviará todos os node_modules. É usado esbuild porque é capaz de agrupar CJS e ESM. Agora, vamos executar o mesmo benchmark com a versão incluída.

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

Como você pode ver, o s3-bundle.mjs agora é mais rápido que o s3-bundle.cjs. O arquivo ESM agora é ainda mais rápido do que o arquivo CommonJS desagregado porque resulta em tamanhos de arquivo menores e tempos de carregamento mais rápidos devido à agitação eficiente da árvore – um processo que remove o código não utilizado.

Abrace a ESM!

O futuro dos módulos JavaScript está, sem dúvida, inclinado para o ESM. Isso começa ao criar um novo projeto NodeJS ou mesmo um projeto React. Cada tutorial e artigo usa a instrução import—, que é, portanto, ESM. Apesar de muitos pacotes CommonJS existentes, a tendência está mudando à medida que mais desenvolvedores e mantenedores adotam o ESM por seus benefícios de desempenho e sintaxe moderna. Outra questão é também quantos desses projetos exclusivos do CJS ainda são mantidos.

ESM é um padrão que funciona em qualquer tempo de execução, como NodeJS, Bun ou Deno, e no navegador sem rodar em um servidor. Não é necessário converter via Babel para CommonJS porque o navegador entende ESM. Você ainda pode usar o Babel para converter para uma versão diferente do ECMAScript, mas não deve converter para CJS.

Você deve desenvolver apenas em ESM porque todos os tempos de execução atuais e navegadores mais recentes que 2017 entendem ESM.

Se o seu código quebrar, você pode ter problemas legados. Considere usar ferramentas ou pacotes diferentes. Por exemplo, você pode migrar de Jest para vitest ou de ExpressJS para h3. A sintaxe permanece a mesma; a única diferença é a instrução de importação.

Principais conclusões:

  • Pacotes menores: o ESM produz pacotes menores por meio de agitação de árvore, levando a tempos de carregamento mais rápidos.
  • Suporte universal: ESM é suportado nativamente por navegadores e tempos de execução JavaScript (Node.js, Bun, Deno).
  • Prova para o futuro: Com adoção contínua, o ESM está posicionado como o padrão para módulos JavaScript modernos.

Para começar, você pode seguir este Gist ou obter um aprendizado inspirador aqui.

Para um futuro JavaScript melhor, adote o ESM!

A apresentação

Mais recursos

  • 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 ↩

Declaração de lançamento Este artigo foi reproduzido em: https://dev.to/jolodev/oh-commonjs-why-are-you-mesming-with-me-reasons-to-ditch-commonjs-enh?1 Se houver alguma violação, por favor entre em contato com study_golang@163 .comdelete
Tutorial mais recente Mais>

Isenção de responsabilidade: Todos os recursos fornecidos são parcialmente provenientes da Internet. Se houver qualquer violação de seus direitos autorais ou outros direitos e interesses, explique os motivos detalhados e forneça prova de direitos autorais ou direitos e interesses e envie-a para o e-mail: [email protected]. Nós cuidaremos disso para você o mais rápido possível.

Copyright© 2022 湘ICP备2022001581号-3