Es war ein normaler Patch-Tag. Ich habe meine NPM-Abhängigkeiten gepatcht und aktualisiert, ohne Codeänderungen vorzunehmen, und plötzlich schlugen einige meiner Komponententests fehl.
Wtf!
Meine Tests sind fehlgeschlagen, weil Jest auf ein unerwartetes Token gestoßen ist. Sie scheiterten, weil Jest standardmäßig keine reinen ESM-Pakete verarbeiten kann. Tatsächlich ist Jest in CommonJS geschrieben.
Aber was bedeutet das? Dazu müssen wir verstehen, warum CommonJS und ESM existieren.
In den Anfängen der Webentwicklung wurde JavaScript hauptsächlich zur Manipulation des Document Object Model (DOM) mit Bibliotheken wie jQuery verwendet. Die Einführung von Node.js führte jedoch auch dazu, dass JavaScript für die serverseitige Programmierung verwendet wurde. Diese Verschiebung erhöhte die Komplexität und Größe der JavaScript-Codebasen. Infolgedessen entstand Bedarf an einer strukturierten Methode zum Organisieren und Verwalten von JavaScript-Code. Um diesem Bedarf gerecht zu werden, wurden Modulsysteme eingeführt, die es Entwicklern ermöglichen, ihren Code in verwaltbare, wiederverwendbare Einheiten zu unterteilen1.
CommonJS wurde 2009 gegründet und hieß ursprünglich ServerJS2. Es wurde für serverseitiges JavaScript entwickelt und bietet Konventionen zum Definieren von Modulen. Node.js hat CommonJS als Standardmodulsystem übernommen und ist damit bei Backend-JavaScript-Entwicklern weit verbreitet. CommonJS verwendet require zum Importieren und module.exports zum Exportieren von Modulen. Alle Vorgänge in CommonJS sind synchron, d. h. jedes Modul wird einzeln geladen.
Im Jahr 2015 führte ECMAScript ein neues Modulsystem namens ECMAScript Modules (ESM) ein, das hauptsächlich auf die clientseitige Entwicklung abzielt. ESM verwendet Import- und Exportanweisungen und seine Vorgänge sind asynchron, sodass Module parallel geladen werden können3. Ursprünglich war ESM für Browser gedacht, während CommonJS für Server konzipiert war. Es wurde immer mehr zum Standard für das JS-Ökosystem. Heutzutage unterstützen moderne JavaScript-Laufzeiten beide Modulsysteme. Browser haben 2017 damit begonnen, ESM nativ zu unterstützen. Sogar Typescript hat die ESM-Syntax angepasst, und wann immer Sie es lernen, lernen Sie ESM auch unbewusst.
Die Wahrheit ist, dass es viel mehr reine CommonJS (CJS)-Pakete als reine ESM-Pakete gibt4.
Es gibt jedoch einen klaren Trend. Die Anzahl reiner ESM-Pakete oder Pakete mit zwei Modulen nimmt zu, während weniger reine CJS-Pakete erstellt werden. Dieser Trend unterstreicht die wachsende Präferenz für ESM und wirft die Frage auf, wie viele der reinen CJS-Pakete aktiv gepflegt werden.
Ein interessanter Vergleich zwischen CommonJS und ESM betrifft Leistungsbenchmarks. Aufgrund seiner synchronen Natur ist CommonJS schneller, wenn die Anweisungen require und import direkt verwendet werden. Betrachten wir das folgende Beispiel:
// 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' });
Ich habe den aws-sdk S3-Client verwendet, da er Dual-Modul-Unterstützung bietet. Hier instanziieren wir den Client und führen ihn dann mit node:
aus
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
Wie Sie sehen, laufen s3-get-files.cjs und damit CommonJS schneller.
Ich habe mich von Buns Blogpost inspirieren lassen.
Wenn Sie Ihre JS-Bibliothek jedoch produzieren möchten, müssen Sie sie bündeln. Andernfalls versenden Sie alle node_modules. Esbuild wird verwendet, da es eine Bündelung zu CJS und ESM ermöglicht. Lassen Sie uns nun denselben Benchmark mit der gebündelten Version ausführen.
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
Wie Sie sehen können, ist s3-bundle.mjs jetzt schneller als s3-bundle.cjs. Die ESM-Datei ist jetzt sogar schneller als die entbündelte CommonJS-Datei, da sie aufgrund des effizienten Tree-Shaking zu kleineren Dateigrößen und schnelleren Ladezeiten führt – einem Prozess, der ungenutzten Code entfernt.
Die Zukunft der JavaScript-Module tendiert zweifellos zu ESM. Dies beginnt beim Erstellen eines neuen NodeJS-Projekts oder sogar eines React-Projekts. Jedes Tutorial und jeder Artikel verwendet die import-Anweisung, also ESM. Trotz zahlreicher vorhandener CommonJS-Pakete ändert sich der Trend, da immer mehr Entwickler und Betreuer ESM aufgrund seiner Leistungsvorteile und modernen Syntax übernehmen. Eine andere Frage ist auch, wie viele dieser reinen CJS-Projekte noch gepflegt werden.
ESM ist ein Standard, der in jeder Laufzeit, wie NodeJS, Bun oder Deno, und im Browser funktioniert, ohne auf einem Server ausgeführt zu werden. Eine Konvertierung über Babel nach CommonJS ist nicht erforderlich, da der Browser ESM versteht. Sie können Babel weiterhin zum Konvertieren in eine andere ECMAScript-Version verwenden, sollten jedoch nicht in CJS konvertieren.
Sie sollten nur in ESM entwickeln, da alle aktuellen Laufzeitumgebungen und Browser neuer als 2017 ESM verstehen.
Wenn Ihr Code kaputt geht, liegen möglicherweise Legacy-Probleme vor. Erwägen Sie die Verwendung anderer Tools oder Pakete. Sie können beispielsweise von Jest zu vitest oder von ExpressJS zu h3 migrieren. Die Syntax bleibt gleich; Der einzige Unterschied ist die Importanweisung.
Wichtige Erkenntnisse:
Um zu beginnen, können Sie diesem Gist folgen oder hier inspirierende Informationen erhalten.
Für eine bessere JavaScript-Zukunft nutzen Sie ESM!
Die Präsentation
https://www.freecodecamp.org/news/javascript-es-modules-and-module-bundlers/#why-use-modules ↩
https://deno.com/blog/commonjs-is-hurting-javascript ↩
https://tc39.es/ecma262/#sec-overview ↩
https://twitter.com/wooorm/status/1759918205928194443 ↩
Das obige ist der detaillierte Inhalt vonOh CommonJS! Warum chattest du mit mir?! Gründe, CommonJS aufzugeben. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!