首頁 > web前端 > js教程 > 噢,CommonJS!為什麼跟我聊天?放棄 CommonJS 的原因

噢,CommonJS!為什麼跟我聊天?放棄 CommonJS 的原因

PHPz
發布: 2024-07-17 21:56:18
原創
726 人瀏覽過

這是正常的補丁日。我在沒有更改程式碼的情況下修補併升級了我的 npm 依賴項,突然間,我的一些單元測試失敗了。
Oh CommonJS! Why are you mESMing with me?! Reasons to ditch CommonJS

臥槽!

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

我的測試失敗了,因為 Jest 遇到了意外的令牌;他們失敗了,因為 Jest 無法處理開箱即用的僅 ESM 套件。事實上,Jest 是用 CommonJS 寫的。
但這意味著什麼?為此,我們需要了解 CommonJS 和 ESM 存在的原因。

為什麼我們需要模組系統?

在 Web 開發的早期,JavaScript 主要用於透過 jQuery 等函式庫來操作文件物件模型 (DOM)。然而,Node.js 的引入也導致 JavaScript 被用於伺服器端程式設計。這種轉變增加了 JavaScript 程式碼庫的複雜性和大小。因此,需要一種結構化方法來組織和管理 JavaScript 程式碼。模組系統的引入就是為了滿足這種需求,使開發人員能夠將程式碼劃分為可管理、可重複使用的單元1.

CommonJS 的出現

CommonJS 成立於 2009 年,原名為 ServerJS2。它是為伺服器端 JavaScript 設計的,提供了定義模組的約定。 Node.js 採用 CommonJS 作為其預設模組系統,使其在後端 JavaScript 開發人員中流行。 CommonJS 使用 require 導入,使用 module.exports 導出模組。 CommonJS 中的所有操作都是同步的,這表示每個模組都是單獨載入的。

ESM(ECMAScript 模組)的興起

2015 年,ECMAScript 引進了一個名為 ECMAScript Modules (ESM) 的新模組系統,主要針對客戶端開發。 ESM使用導入和導出語句,其操作是非同步的,允許並行載入模組3。最初,ESM 是為瀏覽器設計的,而 CommonJS 是為伺服器設計的。它越來越成為 JS 生態系統的標準。如今,現代 JavaScript 運行時支援這兩種模組系統。瀏覽器從 2017 年開始原生支援 ESM。甚至 Typescript 也適配了 ESM 文法,每當你學習它時,你也在潛意識中學習 ESM。

How Are you not dead.jpg

CommonJS 將會繼續存在

事實是,僅 CommonJS (CJS) 的軟體包比僅 ESM 的軟體包多得多4.
Oh CommonJS! Why are you mESMing with me?! Reasons to ditch CommonJS
然而,有一個明顯的趨勢。僅 ESM 或雙模組軟體包的數量正在增加,而僅 CJS 軟體包的數量正在減少。這一趨勢凸顯了人們對 ESM 日益增長的偏好,並提出了有多少純 CJS 軟體包得到積極維護的問題。

比較

CommonJS 和 ESM 之間的一個有趣的比較涉及性能基準。由於其同步特性,CommonJS 直接使用 require 和 import 語句時速度較快。讓我們考慮以下範例:

// 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' });
登入後複製

我使用了aws-sdk S3-Client,因為它有雙模組支援。這裡我們實例化客戶端,然後用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
登入後複製

如您所見,s3-get-files.cjs 以及 CommonJS 運作得更快。
我受到 Buns 部落格文章的啟發。

但是,當你想要生產你的 JS 函式庫時,你需要捆綁它。否則,您將運送所有的node_modules。使用 esbuild 因為它能夠捆綁到 CJS 和 ESM。 現在,讓我們使用捆綁版本來執行相同的基準測試。

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
登入後複製

如您所見,s3-bundle.mjs 現在比 s3-bundle.cjs 更快。 ESM 檔案現在甚至比未捆綁的 CommonJS 檔案更快,因為由於有效的樹搖動(刪除未使用的程式碼的過程),它會導致更小的檔案大小和更快的載入時間。

擁抱 ESM!

JavaScript 模組的未來無疑傾向於 ESM。這在創建新的 NodeJS 專案甚至 React 專案時開始。每個教學和文章都使用 import 語句,這就是 ESM。儘管已有許多 CommonJS 包,但隨著越來越多的開發人員和維護人員因其效能優勢和現代語法而採用 ESM,這種趨勢正在改變。另一個問題是還有多少這些僅 CJS 的項目仍在維護中。

ESM 是一個可以在任何運行時(例如 NodeJS、Bun 或 Deno)以及瀏覽器中運行的標準,無需在伺服器上運行。沒有必要透過 Babel 轉換為 CommonJS,因為瀏覽器可以理解 ESM。您仍然可以使用 Babel 轉換為不同的 ECMAScript 版本,但不應轉換為 CJS。

您應該只使用 ESM 進行開發,因為現在的每個運行時間和 2017 年更新的瀏覽器都可以理解 ESM。

如果您的程式碼損壞,您可能會遇到遺留問題。考慮使用不同的工具或套件。例如,您可以從 Jest 遷移到 vitest,或從 ExpressJS 遷移到 h3。語法保持不變;唯一的差異是 import 語句。

關鍵要點

  • 更小的捆綁包:ESM 透過 tree-shaking 產生更小的捆綁包,從而加快載入時間。
  • 通用支援:瀏覽器和 JavaScript 執行時期(Node.js、Bun、Deno)原生支援 ESM。
  • 面向未來:隨著不斷採用,ESM 被定位為現代 JavaScript 模組的標準。

要開始使用,您可以遵循此要點或在這裡獲得啟發性學習。

為了更好的 JavaScript 未來,擁抱 ESM!

示範

更多資源

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

以上是噢,CommonJS!為什麼跟我聊天?放棄 CommonJS 的原因的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板