Maison  >  Article  >  interface Web  >  Oh CommonJS ! Pourquoi tu discutes avec moi ?! Raisons d’abandonner CommonJS

Oh CommonJS ! Pourquoi tu discutes avec moi ?! Raisons d’abandonner CommonJS

PHPz
PHPzoriginal
2024-07-17 21:56:18702parcourir

C'était une journée de patch normale. J'ai corrigé et mis à niveau mes dépendances npm sans apporter de modifications au code, et tout à coup, certains de mes tests unitaires ont échoué.
Oh CommonJS! Why are you mESMing with me?! Reasons to ditch CommonJS

Wtf !

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

Mes tests ont échoué car Jest a rencontré un jeton inattendu ; ils ont échoué parce que Jest ne peut pas gérer les packages ESM uniquement prêts à l'emploi. En fait, Jest est écrit en CommonJS.
Mais qu’est-ce que cela signifie ? Pour ce faire, nous devons comprendre pourquoi CommonJS et ESM existent.

Pourquoi avons-nous besoin de systèmes de modules ?

Au début du développement Web, JavaScript était principalement utilisé pour manipuler le modèle objet de document (DOM) avec des bibliothèques comme jQuery. Cependant, l’introduction de Node.js a également conduit à l’utilisation de JavaScript pour la programmation côté serveur. Ce changement a augmenté la complexité et la taille des bases de code JavaScript. En conséquence, il est apparu nécessaire de disposer d’une méthode structurée pour organiser et gérer le code JavaScript. Des systèmes de modules ont été introduits pour répondre à ce besoin, permettant aux développeurs de diviser leur code en unités gérables et réutilisables1.

L'émergence de CommonJS

CommonJS a été créé en 2009, initialement nommé ServerJS2. Il a été conçu pour JavaScript côté serveur, fournissant des conventions pour définir les modules. Node.js a adopté CommonJS comme système de modules par défaut, ce qui le rend répandu parmi les développeurs JavaScript backend. CommonJS utilise require pour importer et module.exports pour exporter des modules. Toutes les opérations dans CommonJS sont synchrones, ce qui signifie que chaque module est chargé individuellement.

L'essor de l'ESM (modules ECMAScript)

En 2015, ECMAScript a introduit un nouveau système de modules appelé ECMAScript Modules (ESM), ciblant principalement le développement côté client. ESM utilise des instructions d'importation et d'exportation et ses opérations sont asynchrones, permettant aux modules d'être chargés en parallèle3. Initialement, ESM était destiné aux navigateurs, alors que CommonJS était conçu pour les serveurs. C’est devenu de plus en plus un standard pour l’écosystème JS. De nos jours, les environnements d'exécution JavaScript modernes prennent en charge les deux systèmes de modules. Les navigateurs ont commencé à prendre en charge ESM de manière native en 2017. Même Typescript a adapté la syntaxe ESM, et chaque fois que vous l'apprenez, vous apprenez également ESM inconsciemment.

How Are you not dead.jpg

CommonJS est là pour rester

La vérité est qu'il existe beaucoup plus de packages CommonJS (CJS) uniquement que de packages uniquement ESM4.
Oh CommonJS! Why are you mESMing with me?! Reasons to ditch CommonJS
Il existe cependant une tendance claire. Le nombre de packages ESM uniquement ou à deux modules est en augmentation, tandis que moins de packages uniquement CJS sont créés. Cette tendance souligne la préférence croissante pour ESM et soulève la question de savoir combien de packages uniquement CJS sont activement maintenus.

Comparaison

Une comparaison intéressante entre CommonJS et ESM implique des benchmarks de performances. En raison de sa nature synchrone, CommonJS est plus rapide lorsqu'il utilise directement les instructions require et import. Considérons l'exemple suivant :

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

J'ai utilisé le client S3 aws-sdk car il prend en charge deux modules. Ici, nous instancions le client puis l'exécutons avec 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

Comme vous pouvez le constater, s3-get-files.cjs et, par conséquent, CommonJS fonctionnent plus rapidement.
Je me suis inspiré de Buns Blogpost.

Cependant, lorsque vous souhaitez mettre en production votre bibliothèque JS, vous devez la regrouper. Sinon, vous expédierez tous les node_modules. Est utilisé esbuild car il est capable de se regrouper avec CJS et ESM. Maintenant, exécutons le même benchmark avec la version fournie.

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

Comme vous pouvez le constater, le s3-bundle.mjs est désormais plus rapide que le s3-bundle.cjs. Le fichier ESM est désormais encore plus rapide que le fichier CommonJS dégroupé, car il entraîne des tailles de fichier plus petites et des temps de chargement plus rapides grâce à un tremblement d'arborescence efficace, un processus qui supprime le code inutilisé.

Adoptez l’ESM !

L'avenir des modules JavaScript penche sans aucun doute vers l'ESM. Cela commence lors de la création d'un nouveau projet NodeJS ou même d'un projet React. Chaque tutoriel et article utilise l'instruction import—, qui est donc ESM. Malgré de nombreux packages CommonJS existants, la tendance évolue à mesure que de plus en plus de développeurs et de responsables adoptent ESM pour ses avantages en termes de performances et sa syntaxe moderne. Une autre question est également de savoir combien de ces projets uniquement CJS sont encore maintenus.

ESM est un standard qui fonctionne dans n'importe quel environnement d'exécution, tel que NodeJS, Bun ou Deno, et dans le navigateur sans s'exécuter sur un serveur. Il n'est pas nécessaire de convertir via Babel vers CommonJS car le navigateur comprend ESM. Vous pouvez toujours utiliser Babel pour convertir vers une autre version d'ECMAScript, mais vous ne devez pas convertir en CJS.

Vous devez développer uniquement dans ESM, car tous les environnements d'exécution actuels et les navigateurs plus récents que 2017 comprennent ESM.

Si votre code tombe en panne, vous pourriez avoir des problèmes hérités. Pensez à utiliser différents outils ou packages. Par exemple, vous pouvez migrer de Jest vers vitest ou d'ExpressJS vers h3. La syntaxe reste la même ; la seule différence est la déclaration d'importation.

Points clés à retenir :

  • Packs plus petits : ESM produit des bundles plus petits grâce au tremblement d'arbre, ce qui entraîne des temps de chargement plus rapides.
  • Support universel : ESM est pris en charge nativement par les navigateurs et les runtimes JavaScript (Node.js, Bun, Deno).
  • À l'épreuve du temps : avec une adoption continue, ESM se positionne comme la norme pour les modules JavaScript modernes.

Pour commencer, vous pouvez suivre cet Gist ou obtenir un apprentissage inspirant ici.

Pour un avenir JavaScript meilleur, adoptez ESM !

La présentation

Plus de ressources

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

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn