"Si un trabajador quiere hacer bien su trabajo, primero debe afilar sus herramientas." - Confucio, "Las Analectas de Confucio. Lu Linggong"
Página delantera > Programación > ¡Oh, CommonJS! ¡¿Por qué estás bromeando conmigo?! Razones para deshacerse de CommonJS

¡Oh, CommonJS! ¡¿Por qué estás bromeando conmigo?! Razones para deshacerse de CommonJS

Publicado el 2024-07-29
Navegar:179

Era un día normal de parcheo. Parché y actualicé mis dependencias de npm sin realizar cambios en el código y, de repente, algunas de mis pruebas unitarias fallaron.
Oh CommonJS! Why are you mESMing with me?! Reasons to ditch CommonJS

¡Qué carajo!

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

Mis pruebas fallaron porque Jest encontró un token inesperado; Fallaron porque Jest no puede manejar paquetes exclusivos de ESM listos para usar. De hecho, Jest está escrito en CommonJS.
Pero ¿qué significa eso? Para hacerlo, debemos comprender por qué existen CommonJS y ESM.

¿Por qué necesitamos sistemas modulares?

En los primeros días del desarrollo web, JavaScript se usaba principalmente para manipular el modelo de objetos de documento (DOM) con bibliotecas como jQuery. Sin embargo, la introducción de Node.js también llevó a que JavaScript se utilizara para la programación del lado del servidor. Este cambio aumentó la complejidad y el tamaño de las bases de código JavaScript. Como resultado, surgió la necesidad de un método estructurado para organizar y gestionar el código JavaScript. Se introdujeron sistemas de módulos para satisfacer esta necesidad, permitiendo a los desarrolladores dividir su código en unidades manejables y reutilizables1.

El surgimiento de CommonJS

CommonJS se estableció en 2009, originalmente llamado ServerJS2. Fue diseñado para JavaScript del lado del servidor y proporciona convenciones para definir módulos. Node.js adoptó CommonJS como su sistema de módulos predeterminado, lo que lo hizo prevalente entre los desarrolladores backend de JavaScript. CommonJS utiliza require para importar y module.exports para exportar módulos. Todas las operaciones en CommonJS son sincrónicas, lo que significa que cada módulo se carga individualmente.

El auge de ESM (módulos ECMAScript)

En 2015, ECMAScript introdujo un nuevo sistema de módulos llamado ECMAScript Modules (ESM), dirigido principalmente al desarrollo del lado del cliente. ESM utiliza declaraciones de importación y exportación, y sus operaciones son asincrónicas, lo que permite que los módulos se carguen en paralelo3. Inicialmente, ESM estaba destinado a navegadores, mientras que CommonJS estaba diseñado para servidores. Se convirtió cada vez más en un estándar para el ecosistema JS. Hoy en día, los tiempos de ejecución de JavaScript modernos admiten ambos sistemas de módulos. Los navegadores comenzaron a admitir ESM de forma nativa en 2017. Incluso Typecript adaptó la sintaxis de ESM y, cada vez que la aprendes, también aprendes ESM de manera inconsciente.

How Are you not dead.jpg

CommonJS llegó para quedarse

La verdad es que hay muchos más paquetes exclusivos de CommonJS (CJS) que paquetes exclusivos de ESM4.
Oh CommonJS! Why are you mESMing with me?! Reasons to ditch CommonJS
Sin embargo, hay una tendencia clara. El número de paquetes de módulo dual o solo ESM está aumentando, mientras que se crean menos paquetes solo CJS. Esta tendencia subraya la creciente preferencia por ESM y plantea la pregunta de cuántos de los paquetes exclusivos de CJS se mantienen activamente.

Comparación

Una comparación interesante entre CommonJS y ESM involucra puntos de referencia de rendimiento. Debido a su naturaleza sincrónica, CommonJS es más rápido cuando utiliza directamente declaraciones require e import. Consideremos el siguiente ejemplo:

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

Utilicé el cliente S3 de aws-sdk porque admite módulos duales. Aquí creamos una instancia del cliente y luego lo ejecutamos con el nodo:

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 puede ver, s3-get-files.cjs y, por lo tanto, CommonJS se ejecutan más rápido.
Me inspiré en Buns Blogpost.

Sin embargo, cuando desees producir tu biblioteca JS, debes empaquetarla. De lo contrario, enviará todos los node_modules. Se utiliza esbuild porque puede integrarse en CJS y ESM. Ahora, ejecutemos el mismo punto de referencia con la versión incluida.

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 puede ver, s3-bundle.mjs ahora es más rápido que s3-bundle.cjs. El archivo ESM ahora es incluso más rápido que el archivo CommonJS desagregado porque genera tamaños de archivo más pequeños y tiempos de carga más rápidos debido a la eficiente agitación de árboles, un proceso que elimina el código no utilizado.

¡Abraza el ESM!

El futuro de los módulos JavaScript sin duda se inclina hacia ESM. Esto comienza al crear un nuevo proyecto NodeJS o incluso un proyecto React. Cada tutorial y artículo utiliza la declaración import, que por lo tanto es ESM. A pesar de que existen muchos paquetes CommonJS, la tendencia está cambiando a medida que más desarrolladores y mantenedores adoptan ESM por sus beneficios de rendimiento y su sintaxis moderna. Otra pregunta es también cuántos de estos proyectos exclusivos de CJS todavía se mantienen.

ESM es un estándar que funciona en cualquier tiempo de ejecución, como NodeJS, Bun o Deno, y en el navegador sin ejecutarse en un servidor. No es necesario realizar la conversión a través de Babel a CommonJS porque el navegador comprende ESM. Aún puedes usar Babel para convertir a una versión diferente de ECMAScript, pero no debes convertir a CJS.

Deberías desarrollar solo en ESM porque ahora todos los tiempos de ejecución y los navegadores posteriores a 2017 entienden ESM.

Si tu código falla, es posible que tengas problemas heredados. Considere utilizar diferentes herramientas o paquetes. Por ejemplo, puedes migrar de Jest a vitest o de ExpressJS a h3. La sintaxis sigue siendo la misma; la única diferencia es la declaración de importación.

Conclusiones clave:

  • Paquetes más pequeños: ESM produce paquetes más pequeños mediante sacudidas de árboles, lo que genera tiempos de carga más rápidos.
  • Soporte universal: ESM es compatible de forma nativa con navegadores y tiempos de ejecución de JavaScript (Node.js, Bun, Deno).
  • A prueba de futuro: Con su adopción continua, ESM se posiciona como el estándar para los módulos JavaScript modernos.

Para comenzar, puedes seguir esta esencia u obtener un aprendizaje inspirador aquí.

¡Para un mejor futuro de JavaScript, adopte ESM!

La presentación

Más 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 ↩

Declaración de liberación Este artículo se reproduce en: https://dev.to/jolodev/oh-commonjs-why-are-you-mesming-with-me-reasons-to-ditch-commonjs-enh?1 Si hay alguna infracción, por favor contacto Study_golang@163 .comeliminar
Último tutorial Más>

Descargo de responsabilidad: Todos los recursos proporcionados provienen en parte de Internet. Si existe alguna infracción de sus derechos de autor u otros derechos e intereses, explique los motivos detallados y proporcione pruebas de los derechos de autor o derechos e intereses y luego envíelos al correo electrónico: [email protected]. Lo manejaremos por usted lo antes posible.

Copyright© 2022 湘ICP备2022001581号-3