<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: coin_guy</title>
    <description>The latest articles on DEV Community by coin_guy (@gui_md_03d69380d4d21dee00).</description>
    <link>https://dev.to/gui_md_03d69380d4d21dee00</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2696815%2F6c4df39d-98e6-417b-af3f-2265bd31eeff.webp</url>
      <title>DEV Community: coin_guy</title>
      <link>https://dev.to/gui_md_03d69380d4d21dee00</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/gui_md_03d69380d4d21dee00"/>
    <language>en</language>
    <item>
      <title>Do package.json ao runtime: como o npm resolve, instala e entrega dependências</title>
      <dc:creator>coin_guy</dc:creator>
      <pubDate>Sun, 24 Aug 2025 23:12:29 +0000</pubDate>
      <link>https://dev.to/gui_md_03d69380d4d21dee00/do-packagejson-ao-runtime-como-o-npm-resolve-instala-e-entrega-dependencias-bfj</link>
      <guid>https://dev.to/gui_md_03d69380d4d21dee00/do-packagejson-ao-runtime-como-o-npm-resolve-instala-e-entrega-dependencias-bfj</guid>
      <description>&lt;p&gt;Às vezes me pego pensando o quanto o package.json é subestimado no meio do desenvolvimento Node/Web.&lt;/p&gt;

&lt;p&gt;O senso comum trata ele quase como uma lista de compras: “nomes de pacotes com uma numeração na frente”, e quando essa lista está pronta a gente cruza os dedos e roda um npm i (na maioria das vezes npm i -f, aquele jeitinho pra não ter que lidar com peerDependencies 😀) e ficamos esperando o download das nossas dependências.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0eg275z3pfobsvo9kxgq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0eg275z3pfobsvo9kxgq.png" alt=" " width="569" height="23"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;E quando dá um problema inexplicável na sua aplicação? Sempre aparece alguém com o mantra clássico:&lt;/p&gt;

&lt;p&gt;“Apaga a node_modules, deleta o package-lock.json e roda um install de novo.”&lt;/p&gt;

&lt;p&gt;É praticamente o “desliga o modem, espera 5 segundos e liga de novo” das nossas aplicações.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9mefbnr7tir2ftes6hw6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9mefbnr7tir2ftes6hw6.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mas será que o package.json é só isso? Ou será que ele é, de fato, o core da sua aplicação e deveria receber mais atenção? 🔍.&lt;/p&gt;

&lt;h3&gt;
  
  
  Package.json como contrato
&lt;/h3&gt;

&lt;p&gt;A documentação do &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;NPM&lt;/a&gt; tem uma longa e extensa definição sobre o que o &lt;a href="https://docs.npmjs.com/cli/v11/configuring-npm/package-json" rel="noopener noreferrer"&gt;package.json representa&lt;/a&gt; e logo nos primeiros momentos de leitura já percebemos de que não se trata apenas de um arquivo ou um "simples objeto JavaScript". Podemos listar algumas das responsabilidades que esse arquivo tem segundo a documentação que acabamos de ver:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;É o Manifesto do seu projeto: define a identidade da sua aplicação: nome, versão e outros metadados. É essencial para qualquer aplicação conseguir consumir demais pacotes npm (e no caso de libs a importância se estende para conseguirmos publicar e disponibilizar essa lib para demais desenvolvedores)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Campos obrigatórios e complementares: &lt;code&gt;name&lt;/code&gt; e &lt;code&gt;version&lt;/code&gt; são obrigatórios apenas se você pretende publicar o pacote no npm (version deve seguir o padrão do semanticVersion: major.minor.patch). Para projetos internos (apps que não vão pro registry), tecnicamente você consegue rodar sem version, mas a boa prática é sempre manter. Como campos complementares podemos ter: description, author, license, repository, keywords, homepage e entre outros (úteis para documentação, publicação e identificação).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Dependencies: é onde definimos os pacotes essenciais para que a nossa aplicação funcione (exemplo: no caso de uma aplicação Angular, aqui vamos encontrar os pacotes vitais &lt;code&gt;@angular&lt;/code&gt;). Dependências vão para o bundle final(prod) da aplicação ao contrario de dependências de desenvolvimento.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;DevDependencies: pacotes que são usados apenas no ambiente de desenvolvimento: jest, eslint, cypress, bundlers, TypeScript e entre outros. &lt;br&gt;&lt;br&gt;
&lt;u&gt;&lt;em&gt;Um ponto importante sobre Dependencies e DevDependencies: elas seguem um padrão de versionamento baseado no &lt;a href="https://docs.npmjs.com/about-semantic-versioning" rel="noopener noreferrer"&gt;semVer&lt;/a&gt;: (^, ~, 1.0.0), que é importante para controle de compatibilidade e atualizações previsíveis dos nossos pacotes&lt;/em&gt;&lt;/u&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scripts automatizados: esse campo do arquivo é responsável por adicionar scripts personalizados para executarmos alguma rotina que precisamos através do comando &lt;code&gt;npm run &amp;lt;nome_do_comando&amp;gt;&lt;/code&gt;. Aqui também temos acesso a hooks que podem ser disparados de maneira &lt;code&gt;pre&amp;lt;nome_comando&amp;gt;&lt;/code&gt; ou &lt;code&gt;post&amp;lt;nome_do_comando&amp;gt;&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo '🔨 Construindo app...'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"prebuild"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo '📦 Limpando dist antes do build...'"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"postbuild"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"echo '✅ Build finalizado com sucesso!'"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Na ordem de execução ficaria =&amp;gt; prebuild, build, postbuild.&lt;/p&gt;

&lt;p&gt;Existem alguns outros campos bem legais do package.json como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Engine: que define versões mínimas e máximas requeridas para que você possa executar aplicação&lt;/li&gt;
&lt;li&gt;OS: em que sistema operacional sua aplicação pode ser executada (e se for necessário em qual OS não pode ser executado)&lt;/li&gt;
&lt;li&gt;CPU: o tipo de arquitetura de CPU que sua aplicação pode ser executada (semelhante ao OS)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Com isso, o package.json deixa de ser apenas “uma lista de compras” e passa a ser visto como o contrato central que garante que seu projeto vai rodar, compilar e ser instalado do jeito planejado.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rodando o install e entendendo como ele funciona
&lt;/h3&gt;

&lt;p&gt;Então o seu &lt;code&gt;package.json&lt;/code&gt; já está configurado e com as dependências que você precisa listadas com as versões alinhadas, agora seu próximo passo é rodar o &lt;code&gt;npm install&lt;/code&gt; e ver toda aquela mágica de toneladas e toneladas de pacotes sendo baixadas. Mas como funciona isso por debaixo dos panos? é um processo simples? quando executamos o install o npm simplesmente tira os pacotes nas versões que precisamos de algum canto misterioso e &lt;code&gt;auto-mágico&lt;/code&gt;, assim como um mágico tira um coelho da cartola?&lt;/p&gt;

&lt;p&gt;e a resposta é .... NÃO!&lt;/p&gt;

&lt;p&gt;Na verdade o processo de download e instalação de pacotes npm é muito mais burocrático do que parece.&lt;/p&gt;

&lt;p&gt;Assim que executamos um &lt;code&gt;npm install&lt;/code&gt; nas nossas aplicações a primeira pergunta que o npm se faz é: "cadê o package-lock.json dessa aplicação ???"&lt;/p&gt;

&lt;h4&gt;
  
  
  package-lock.json: A caixa-preta do projeto
&lt;/h4&gt;

&lt;p&gt;Quando algum avião tem qualquer tipo de problema, o primeiro lugar que todos vão checar é a famigerada "caixa preta", a caixa preta não abre margem para chutes e achismos, o que está nela são os registros absolutos do avião...assim como o &lt;code&gt;package-lock.json&lt;/code&gt; é a caixa preta dos seus pacotes. O lock não é apenas um arquivo gigantesco que serve para complicar a sua vida com changes no momento de um git rebase ou um git pull, ele é justamente o registro fiel de como cada dependência sua foi instalada, um raio-x perfeito da arvore de dependências da aplicação&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lg40js3phdzs8figk5i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6lg40js3phdzs8figk5i.png" alt=" " width="800" height="421"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos olhar com um pouco mais de proximidade para o caso do &lt;code&gt;@angular/core&lt;/code&gt; e tomar como exemplo para os demais:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no package.json a dependência está listada como:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"@angular/core"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^16.2.0"&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quando usamos o &lt;a href="https://docs.npmjs.com/cli/v6/using-npm/semver#ranges" rel="noopener noreferrer"&gt;semVer range syntax (~, ^)&lt;/a&gt; não sabemos exatamente a versão especifica do pacote que será baixada para o nosso projeto, temos como ter um controle e uma certa visibilidade, mas se usamos o range syntax (o mais comum) ficamos com algumas incertezas sobre a versão. Essas incertezas se tornam certezas quando olhamos no detalhe o registro da dependência no package-lock.json&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8f2jogs9odkulfbmsa9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd8f2jogs9odkulfbmsa9.png" alt=" " width="800" height="101"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Aqui nós temos o registro exato da dependência:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A dependência foi instalada na versão &lt;code&gt;16.2.9&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Ela foi encontrada no registry do npm (não foi configurado o uso de nenhum "articatory" ou qualquer outro tipo de Registry privado (como Nexus, Verdaccio, etc.). &lt;em&gt;Curiosidade: o arquivo do pacote vem no formato .tgz. Experimente rodar npm pack no build de uma lib Node e veja o pacote gerado: &lt;code&gt;nome_da_sua_lib&lt;/code&gt;.tgz&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;O pacote está integro e tem a garantia disso através de uma chave SHA512, mas o que isso quer dizer ? quer dizer que o pacote que você baixou está em conformidade com o que o autor publicou no npm, evitando que você baixe pacotes com conteúdos malicioso/prejudiciais.&lt;/li&gt;
&lt;li&gt;Todos os pacotes adicionais que a dependência precisa serão baixados  para funcionar corretamente graças ao campo &lt;code&gt;requires&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;E por aqui já podemos ver o quanto é importante termos apenas as dependências que precisamos nos nossos projetos, afinal as dependências também tem dependências o que gera mais download de pacotes....logo node_modules tende ao infinito 😁.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8gbkc7lvpcm4j9cghsx1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8gbkc7lvpcm4j9cghsx1.png" alt=" " width="800" height="575"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para finalizarmos o assunto package-lock.json: se sua aplicação já estiver com um install ou seu projeto clonado já vier com um package-lock.json (é uma boa práticas sempre que necessário comitarmos o package-lock.json, inclusive é uma questão de segurança), o npm vai usar esse arquivo como referencia e ir fazendo o download de dependência por dependência seguindo com fidelidade a questão do registry(presente no campo resolved) e das versões, garantindo a &lt;code&gt;reprodutibilidade&lt;/code&gt; do seu projeto.&lt;/p&gt;

&lt;h4&gt;
  
  
  Continuando o fluxo do npm install
&lt;/h4&gt;

&lt;p&gt;Dada a necessária explicação sobre o package-lock.json, vamos voltar a falar agora sobre como o npm te entrega esses pacotes, do registry até a sua máquina...e para isso nada melhor que um fluxograma certo? (fluxogramas salvam vidas, pode confiar)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx33j0d1l0kw5828pmx7r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx33j0d1l0kw5828pmx7r.png" alt=" " width="800" height="1487"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Neste fluxo ainda não estamos considerando peerDependencies no processo de instalação, uma breve explicação sobre peerDependecies:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;São dependências que os pacotes precisam que o consumidor também instale, porque ela não vai instalar sozinha.&lt;/li&gt;
&lt;li&gt;A partir do npm v7, o npm tenta instalar automaticamente as peerDependencies quando possível. Se houver conflito de versões que ele não consegue resolver, ele falha e pede instalação manual.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;E após todo esse processo de: checagem, download, extração e disponibilização, os seus pacotes vão estar prontos para consumo em runTime e sua aplicação (esperamos todos nós) vai estar funcional.&lt;/p&gt;

&lt;p&gt;Estamos certos em cruzar os dedos toda vez que rodamos um &lt;code&gt;npm i&lt;/code&gt;, afinal de contas olha quantos processos são executados por "de baixo do capô", e quase um jogo de azar no qual sempre torcemos pelo nosso gerenciador de pacotes nos salvar de mais algum bug que vai nos custar horas.&lt;/p&gt;

&lt;p&gt;E você? já tomou algum erro de peerDependecies ou de ETARGET?&lt;/p&gt;

</description>
      <category>npm</category>
      <category>angular</category>
      <category>react</category>
      <category>node</category>
    </item>
    <item>
      <title>Da Glória ao Caos: como CJS e ESM dividem o JavaScript até hoje</title>
      <dc:creator>coin_guy</dc:creator>
      <pubDate>Sun, 25 May 2025 17:29:03 +0000</pubDate>
      <link>https://dev.to/gui_md_03d69380d4d21dee00/da-gloria-ao-caos-como-cjs-e-esm-dividem-o-javascript-ate-hoje-4l07</link>
      <guid>https://dev.to/gui_md_03d69380d4d21dee00/da-gloria-ao-caos-como-cjs-e-esm-dividem-o-javascript-ate-hoje-4l07</guid>
      <description>&lt;p&gt;JS é uma linguagem de programação fantástica, que te dá a possibilidade de fazer inúmeras coisas — desde um &lt;a href="https://www.chartjs.org/docs/latest/samples/bar/border-radius.html" rel="noopener noreferrer"&gt;gráfico bem ilustrado&lt;/a&gt;, até &lt;a href="https://threejs.org/" rel="noopener noreferrer"&gt;modelos 3Ds incríveis&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mas o JavaScript não se limita a gráficos bonitos ou interfaces coloridas.&lt;/p&gt;

&lt;p&gt;Precisa de uma API? Ótimo, o Node.js pode te atender.&lt;br&gt;
Quer uma aplicação performática? Builders modernos com SSR e SSG podem resolver seus problemas (e talvez até criar outros no caminho) com velocidade.&lt;/p&gt;

&lt;p&gt;Aplicações mobile? WebViews criadas com frameworks JS vão te salvar.&lt;br&gt;
Quer criar seu próprio jogo? Dá uma olhada no &lt;a href="https://phaser.io/" rel="noopener noreferrer"&gt;Phaser&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A lista é extensa: bots, pacotes NPM, Machine Learning... JS é praticamente o gênio do Aladdin esperando para sair da lâmpada: &lt;strong&gt;"Você nunca teve um amigo como eu."&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0xhshr1ifflwl0q8a763.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0xhshr1ifflwl0q8a763.jpg" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mas, ainda assim, temos os críticos, não precisa pesquisar muito para encontrar alguém reclamando do JS no Reddit, no Stack Overflow ou em algum fórum de programação.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fex4qizk9uyvuhgns76xb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fex4qizk9uyvuhgns76xb.png" alt=" " width="800" height="808"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Os motivos variam desde opiniões pessoais até coisas que, de fato, são difíceis de defender no JavaScript...principalmente quando falamos de coerções de tipo e comparações inesperadas.&lt;/p&gt;

&lt;p&gt;Além disso, há frustrações práticas: ter que alinhar versões dos pacotes NPM no &lt;code&gt;package.json&lt;/code&gt; para que tudo volte a funcionar depois de um erro inesperado é algo comum. Problemas com dependências quebradas por atualizações são reais, e podem virar uma dor de cabeça.&lt;/p&gt;

&lt;p&gt;E você ainda pode ter mais azar: cair num problema de incompatibilidade entre CJS e ESM — o motivo que originou este post:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbt9ehz4bwr3lpp8gzgh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsbt9ehz4bwr3lpp8gzgh.png" alt=" " width="800" height="484"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;É... e então, de repente, aquele seu amigo gênio começa a virar um pesadelo.&lt;/p&gt;

&lt;p&gt;Cada versão de cada pacote pode se tornar seu inimigo.&lt;/p&gt;

&lt;p&gt;E o pior: &lt;strong&gt;qual pacote é o culpado?&lt;/strong&gt;&lt;br&gt;
Você só vai descobrir trocando as versões, deletando o &lt;code&gt;node_modules&lt;/code&gt;, dando &lt;code&gt;npm install&lt;/code&gt;, rodando &lt;code&gt;npm start&lt;/code&gt; e torcendo.&lt;br&gt;
Cada tentativa é um teste de fé, corrigir o pacote X pode quebrar o Y e &lt;br&gt;
a tarefa que parecia durar 2 horinhas vira um loop eterno de frustração. Parece raro… mas acontece &lt;strong&gt;muito&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Queria te dizer que existe uma bala de prata pra resolver isso — mas não tem.&lt;br&gt;
&lt;strong&gt;Ninguém vai vir te salvar.&lt;/strong&gt; 🤯&lt;/p&gt;

&lt;p&gt;O que dá pra fazer é &lt;strong&gt;entender os mecanismos, a história, e os "porquês"&lt;/strong&gt; por trás dessas decisões no JavaScript.&lt;br&gt;
Conhecer a linguagem a fundo vai te dar mais controle, vai fazer você &lt;strong&gt;parar de suar frio&lt;/strong&gt; quando vir o infame diretório &lt;code&gt;node_modules&lt;/code&gt; nos logs de erro.&lt;/p&gt;
&lt;h2&gt;
  
  
  A ORIGEM DO PROBLEMA ENTRE CJS E ESM
&lt;/h2&gt;

&lt;p&gt;Se você voltar um pouco no tempo e na história do JS, vai notar que o motor V8 (o interpretador do JS do Chrome) era executado apenas no lado do cliente.&lt;br&gt;&lt;br&gt;
O Node ainda não existia, e não tínhamos JavaScript no backend.&lt;/p&gt;

&lt;p&gt;O JS no lado do cliente não era nem de longe "parrudo" e complexo como é hoje.&lt;br&gt;&lt;br&gt;
Módulos? Isso não existia. Empacotadores como Webpack? Só daqui a alguns anos. Frameworks? Muito futurista.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Naquela época, JavaScript sequer tinha noção de modularidade. Não existia &lt;code&gt;import&lt;/code&gt;, nem &lt;code&gt;export&lt;/code&gt;. Tudo que você escrevia, você torcia pra não colidir com mais nada.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;O que tínhamos era um arquivo index.html que carregava alguns JS hospedado em algum servidor, e quando esse arquivo era consumido, o navegador apenas interpretava os JS com o V8 — e com isso, renderizava a aplicação na tela.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fho89k8uzlp5hlpctd5l9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fho89k8uzlp5hlpctd5l9.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Quem reinava nessa época era o nosso saudoso &lt;strong&gt;jQuery&lt;/strong&gt;, que ainda está presente em aproximadamente &lt;a href="https://w3techs.com/technologies/overview/javascript_library" rel="noopener noreferrer"&gt;73% de todos os sites da web!!&lt;/a&gt;&lt;br&gt;&lt;br&gt;
Mas aí vem a pergunta: &lt;em&gt;como as coisas eram feitas no passado? se não tínhamos módulos?&lt;/em&gt; Todo o código da aplicação era inserido em um único JS?&lt;/p&gt;

&lt;p&gt;Quase isso.&lt;/p&gt;

&lt;p&gt;Nesse período, tínhamos o famoso &lt;strong&gt;"script soup"&lt;/strong&gt;: o arquivo &lt;code&gt;index.html&lt;/code&gt; era encarregado de carregar todos os JS da aplicação — seja via CDN, seja arquivos próprios:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4lxsm0h550h0ypam1rv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd4lxsm0h550h0ypam1rv.png" alt=" " width="800" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Parecia simples e até fácil de controlar.&lt;br&gt;&lt;br&gt;
Mas aí começa o caos: todos os arquivos JS carregados dessa forma são executados &lt;strong&gt;no mesmo escopo global&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
O que isso significa? Que funções e variáveis declaradas em um arquivo podem ser sobrescritas por outro &lt;strong&gt;sem nem te avisar&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;E mais: &lt;strong&gt;os scripts são executados na ordem em que aparecem no HTML&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
Ou seja, se você tentar usar uma função antes de ela ser carregada, pode dar erro — mesmo que ela exista em outro arquivo.&lt;/p&gt;

&lt;p&gt;Vamos a um exemplo simples:&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;script1.js&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dogsName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Zelda&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sayHiToDog&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hi &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;dogsName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;script2.js&lt;/code&gt;
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dogsName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;McIntosh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Se esses dois scripts forem incluídos no mesmo HTML, você vai se deparar com esse erro no console:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Uncaught SyntaxError: Identifier &lt;span class="s1"&gt;'dogsName'&lt;/span&gt; has already been declared &lt;span class="o"&gt;(&lt;/span&gt;at script2.js:1:1&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por quê?&lt;br&gt;
Porque o conteúdo dos arquivos JS é carregado como se tudo estivesse em um mesmo arquivo gigante.&lt;br&gt;
Todos os valores, funções e variáveis vazam para o escopo global. Isso abre espaço pra conflitos, sobrescrições e bugs que só aparecem no runtime.&lt;/p&gt;
&lt;h2&gt;
  
  
  Longe do caos da web
&lt;/h2&gt;

&lt;p&gt;Um pouco distante do cenário mencionado acima, em 2009 tivemos o lançamento do Node.js (para felicidade de alguns e tristeza de outros): tínhamos agora JS no backend!&lt;/p&gt;

&lt;p&gt;Pra lidar com a bagunça que era a gestão de arquivos no frontend — cheio de scripts globais brigando por espaço — o Node adotou um modelo de modularização inspirado em uma proposta da comunidade chamada commonJS.&lt;/p&gt;
&lt;h3&gt;
  
  
  Nasce uma solução no backend para iluminar o frontend
&lt;/h3&gt;

&lt;p&gt;O commonJS era uma maneira mais elegante de lidar com importação de trechos de código para os arquivos, por que? porque ele tratava os arquivos/dependências como &lt;code&gt;módulos!&lt;/code&gt;. Com o commonJS, o JavaScript finalmente ganhava uma forma real de modularização prática e isolada, sem depender de escopo global.&lt;/p&gt;

&lt;p&gt;Se você já mexeu em alguma aplicação nodeJS com certeza já viu essas palavrinhas soltas por ai: &lt;code&gt;require&lt;/code&gt; e &lt;code&gt;module.exports&lt;/code&gt;, e são justamente elas que faziam a mágica acontecer. O &lt;code&gt;require&lt;/code&gt; importava o que outros arquivos exportavam como módulo e o &lt;code&gt;module.exports&lt;/code&gt; exportava o conteúdo que você queria dos seus scripts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dogsName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;McIntosh&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dogsName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E para consumir isso bastava você chamar o &lt;code&gt;require&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dogsName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./script1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dogsName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;//McIntosh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  O commonJS no front
&lt;/h2&gt;

&lt;p&gt;Com o nodeJS ganhando cada vez mais espaço, os desenvolvedores começaram a se dedicar na criação de pacote modularizados(&lt;code&gt;npm&lt;/code&gt;) para suas aplicações, pacotes esses com funções reutilizáveis que poderiam ser adicionados em qualquer aplicação, e as libs mais antigas ao commonJS (lodash e o axios por exemplo) começaram a seguir esse caminho também e se modularizaram utilizando essa mecânica, que revolucionou como o JS lidava com a gestão do código. Mas ai temos um problema, o navegador não entendia essa sintaxe de require e module.exports do nodeJS ☠, se você fizer um teste rápido no seu navegador colocando isso:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dogsName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dogsLib&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O navegador não vai reclamar que &lt;code&gt;dogsLib&lt;/code&gt; não existe (e não existe mesmo) ele vai é reclamar que &lt;code&gt;require&lt;/code&gt; não existe! por conta da execução quebrar antes da tentativa da importação.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;VM361:1 Uncaught ReferenceError: require is not defined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;E como resolvemos isso ? como vamos trazer um pedacinho do nodeJS para o navegador ? é aí que surgem os bundlers — ferramentas que ajudam a trazer essa modularização para o ambiente do navegador.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sobre os Bundlers
&lt;/h3&gt;

&lt;p&gt;Quando estamos no nosso processo de desenvolvimento de aplicações no front, raramente nos atentamos aos bundlers (webpack, browserify, esbuild...) a menos quando temos algum erro que cite que o bundler quebrou no processo de compilação. Mas para que serve os bundlers e como eles solucionaram esse problema de trazer a modularização para o front?&lt;/p&gt;

&lt;p&gt;Bom, entre as inúmeras funções que um bundler tem uma delas é a de deixar o código "entendível" ao navegador, quando adicionamos um bundler na aplicação o fluxo deixa de ser:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Seu JS -&amp;gt; Navegador
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;para:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Seu JS -&amp;gt; bundler -&amp;gt; Navegador
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O navegador não sabe o que é a sintaxe de modularização do nodeJS e o bundler sabe disso, então nesse caso o bundler vai agir também como um &lt;code&gt;tradutor&lt;/code&gt; para o navegador, ele vai compilar o seu código JS em algo que o navegador não tenha nenhuma dificuldade de entender tentando manter ao máximo a fidelidade do que o seu código está fazendo e como ele está lidando com a gestão dos módulos. E com a adição dos bundlers no front voa lá, temos modularização em aplicações web também.&lt;/p&gt;

&lt;h2&gt;
  
  
  Nem tudo são flores
&lt;/h2&gt;

&lt;p&gt;Todo começo de relacionamento é um mar de flores, mas nem todos eles continuam assim com o passar do tempo, e foi justamente isso que aconteceu na relação navegador e CJS. O CJS revolucionou e não foi pouco não a maneira como os desenvolvedores web olhavam para a estrutura do seu código, mas mesmo assim o &lt;code&gt;commonJS&lt;/code&gt; não tinha nascido para o front, ele foi "empurrado" para lá e com isso os problemas que não notávamos no backend começaram a se apresentar no frontend. Problemas como: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;performance: A execução síncrona do CJS pode ser um gargalo no cliente, onde o carregamento não pode bloquear a renderização da página. Somado a isso temos problemas que impossibilitam muito uma tentativa de tree-shaking do que realmente está sendo usado do módulo e do que não está.&lt;/li&gt;
&lt;li&gt;inconsistência: apesar existir uma certa coerência, especialmente em épocas anteriores, diferentes bundlers implementavam o suporte ao CJS de maneiras ligeiramente distintas, gerando uma certa inconsistência no momento de build (o mesmo arquivo tinha builds diferentes no webpack e em outro bundler).&lt;/li&gt;
&lt;li&gt;sem suporte: a comunidade entendeu a dor de não dar suporte para os módulos e começou a trabalhar em uma maneira diferente de gerir isso, criando o ESM, ao invés de dar suporte ao CJS.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conhecemos o ESM
&lt;/h2&gt;

&lt;p&gt;O escmaScript 2015 (ES6) foi considerado por alguns uma das versões que mais revolucionaram o JS, e não estou nem falando da criação de features modernas que tiraram aquela aparência de "linguagem remendada" do JS como: variáveis que respeitam o escopo que são declaradas (&lt;code&gt;let&lt;/code&gt; e &lt;code&gt;const&lt;/code&gt;), arrow functions ou classes, estamos falando dos &lt;code&gt;ESModules&lt;/code&gt;. Se o CJS era a solução elegante ao carregamento global de scripts, o ESM era a solução elegante ao CJS. O CJS era popular e difundido na comunidade web (o que vai ser um problemão) e o desafio do ESM era provar o seu valor cobrindo as brechas deixadas pelo CJS no web.&lt;/p&gt;

&lt;h2&gt;
  
  
  ESM vs CJS na Web — Comparativo de Benefícios
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Característica&lt;/th&gt;
&lt;th&gt;ESM (ES Modules)&lt;/th&gt;
&lt;th&gt;CJS (CommonJS)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Suporte nativo em navegadores&lt;/td&gt;
&lt;td&gt;✅ Sim&lt;/td&gt;
&lt;td&gt;❌ Não (precisa de bundler)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Carregamento assíncrono&lt;/td&gt;
&lt;td&gt;✅ Sim&lt;/td&gt;
&lt;td&gt;❌ Não, é síncrono&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tree-shaking (remoção de código)&lt;/td&gt;
&lt;td&gt;✅ Suportado pelos bundlers modernos&lt;/td&gt;
&lt;td&gt;❌ Ineficiente, exige soluções manuais&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Importação dinâmica (&lt;code&gt;import()&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;✅ Suporte nativo&lt;/td&gt;
&lt;td&gt;✅ Suporte via &lt;code&gt;require()&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Análise estática de dependências&lt;/td&gt;
&lt;td&gt;✅ Sim, desde o parse inicial&lt;/td&gt;
&lt;td&gt;❌ Não, requer execução&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Paralelização de carregamento&lt;/td&gt;
&lt;td&gt;✅ Sim&lt;/td&gt;
&lt;td&gt;❌ Não&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Execução condicional de módulos&lt;/td&gt;
&lt;td&gt;❌ Não (estrutura rígida)&lt;/td&gt;
&lt;td&gt;✅ Sim (pode usar lógica com &lt;code&gt;require&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compatibilidade com o Node.js&lt;/td&gt;
&lt;td&gt;✅ Sim (desde Node 12+ com &lt;code&gt;type: module&lt;/code&gt;)&lt;/td&gt;
&lt;td&gt;✅ Sim, nativamente&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Padrão moderno&lt;/td&gt;
&lt;td&gt;✅ Sim, especificação oficial&lt;/td&gt;
&lt;td&gt;❌ Legado, criado como solução temporária&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ideal para aplicações web&lt;/td&gt;
&lt;td&gt;✅ Totalmente&lt;/td&gt;
&lt;td&gt;❌ Foi adaptado via bundler&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Para o contexto de web (que é o foco desse artigo) o ESM já nasce com uma vantagem imensa em relação ao CJS, ele foi planejado e projetado para ser nativo nos navegadores.&lt;/p&gt;

&lt;p&gt;O ESM logo ganhou tração e os pacotes e projetos web passaram por refatorações para dizer adeus ao CJS e olá ao ESM, e aqui para variar temos outro problema.&lt;/p&gt;

&lt;h2&gt;
  
  
  Os fantasmas do passado sempre te perseguem
&lt;/h2&gt;

&lt;p&gt;Não é um mal limitado aos humanos essa questão dos erros do passado continuarem existindo no futuro, isso aconteceu com a web também! e nesse caso vamos falar de como o CJS continua assombrando a web mesmo com uma década de ESM(considerando a data de criação desse post).&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Muitos pacotes que foram escritos com CJS não foram refatorados para ESM, e isso acaba gerando uma verdadeira salada de frutas com o projeto usando pacotes ESM e pacotes CJS (tipos diferentes de sintaxe de execução, CJS usa require enquanto ESM usa import, maneiras diferentes de como lidam com o carregamento de módulo e entre outros pontos.)&lt;/li&gt;
&lt;li&gt;Uma complicação em fazer pacotes CJS funcionar no web, vide o Jest (talvez esse seja um pouco pessoal) que precisa de um arquivo de configuração com um &lt;code&gt;mapper&lt;/code&gt; explicando para a lib como ela deve tratar pacotes ESM na hora da execução dos testes.
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flzccw9rr2f37rgjh0gve.png" alt=" " width="800" height="317"&gt;
&lt;/li&gt;
&lt;li&gt;Frameworks conhecidos com versões mais recentes não dão mais nenhum tipo de suporte ao CJS (não é mesmo Angular v17+), pegando como exemplo o Angular v17+ que vem por padrão com o ESBuild como bundler, você pode se deparar com essa surpresa ao buildar uma aplicação com o ESBuild que ainda tem pacotes no CJS:
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdjw3igvlu8uetp8mpodx.png" alt=" " width="638" height="53"&gt;
&lt;/li&gt;
&lt;li&gt;Todo esse problema entre CJS e ESM reforça mais um dos problemas que listamos no inicio desse post, a necessidade de ficar "alinhando" as versões das dependências do seu projeto e torcer MUITO para que o &lt;code&gt;npm start&lt;/code&gt; funcione como estava funcionando antes e não que alguns desses dizeres se apresente no console:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ReferenceError: exports is not defined &lt;span class="k"&gt;in &lt;/span&gt;ES module scope
SyntaxError: Cannot use import statement outside a module
TypeError: Module &lt;span class="s2"&gt;"x"&lt;/span&gt; does not provide an &lt;span class="nb"&gt;export &lt;/span&gt;named &lt;span class="s2"&gt;"default"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As vezes me pego pensando de que a web ainda está em um momento de "velho oeste" aonde as coisas ainda estão se estabelecendo mas não existe muito uma lei a ser seguida... e você? acha que as coisas já estão estabelecidas ou que ainda existirão mudanças drásticas assim como mudamos de CJS para ESM?&lt;/p&gt;

&lt;p&gt;Bom esse foi um breve resumo de como os módulos surgiram na web e de como eles podem facilitar e complicar muito a sua vida. Espero que tenha gostado, nos vemos por aí 🤠.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>node</category>
      <category>esmodule</category>
    </item>
  </channel>
</rss>
