自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

模塊化規(guī)范 CommonJS 會消失嗎?

開發(fā) 前端
JavaScript 出現(xiàn)大約 15 年后,開始從瀏覽器擴展到服務端。許多更大的項目選擇使用 JavaScript 進行構(gòu)建,而 JavaScript 需要一種更好的方法來處理大量源代碼,它需要模塊化。

當談到 JavaScript 的模塊化規(guī)范時,我們不可避免地會提到 CommonJS。多年來,CommonJS 在 Node.js 生態(tài)系統(tǒng)中扮演著至關重要的角色,它讓開發(fā)者能夠方便地使用模塊化的代碼組織方式。然而,隨著 ES Modules(ESM)的出現(xiàn)和日益普及,人們開始思考一個問題:CommonJS 是否注定會消失?在本文中,我們將探討 CommonJS 的現(xiàn)狀和未來,并評估它與ESM之間的關系。是否真的可以全面過渡到ESM,拋棄CommonJS?讓我們一起來看看。

CommonJS 的興起

JavaScript 出現(xiàn)大約 15 年后,開始從瀏覽器擴展到服務端。許多更大的項目選擇使用 JavaScript 進行構(gòu)建,而 JavaScript 需要一種更好的方法來處理大量源代碼,它需要模塊化。

2009 年,Mozilla 的開發(fā)者 Kevin Dangoor 發(fā)出了號召。在 “服務端 JavaScript 需要什么”一文中,他列舉出了服務端 JavaScript 所缺少的許多內(nèi)容,包括模塊系統(tǒng)。

JavaScript 需要一種標準的方式來包含其他模塊,并且這些模塊應該存在于獨立的命名空間中。雖然有一些簡單的方法來創(chuàng)建命名空間,但是目前還沒有一種標準的編程方式來加載一個模塊(一次性)。這一點非常重要,因為服務端應用可能包含大量代碼,并且可能會混合和匹配滿足這些標準接口的部分。

— 出自Kevin Dangoor的《Server Side JavaScript需要什么》(2009年)

在一周內(nèi),包括 npm 的創(chuàng)始人 Issac Schlueter 和 Node.js 的創(chuàng)建者 Ryan Dahl 在內(nèi),共有 224 人加入了當時稱為 ServerJS 的 Google 群組。該郵件列表將繼續(xù)規(guī)范 CommonJS 的第一個版本,該模塊系統(tǒng)成為 Node.js 的一部分。

提議的 CommonJS 語法(require()、module.exports等)看起來并不像客戶端JavaScript。這是經(jīng)過設計的。Dangoor意圖將CommonJS與瀏覽器JavaScript區(qū)分開來,這一點從他 2009 年在 CommonJS Google 群組上的消息中就可以看出來:

我確實認為服務端代碼的需求與客戶端代碼的需求有很大不同,因此最好從 Python 和 Ruby 中獲取,而不是從 Dojo 和 jQuery 中獲取。

除了 Node.js 之外,其他幾個早期的服務端 JavaScript 運行時也采用了 CommonJS,例如 Flusspferd、GPSEE、Narwhal、Persevere、RingoJS、Sproutcore 和 v8cgi(大多數(shù)由核心 CommonJS 團隊構(gòu)建)。

但隨著 Node.js 成為真正的服務端 JavaScript 運行時,并以 CommonJS 作為其主要模塊系統(tǒng),更廣泛的 CommonJS 標準化工作失去了動力。當只有一個主要運行時時,對標準的需求就會減少:Node.js 實現(xiàn)就成為了標準。

盡管 CommonJS 是默認的模塊系統(tǒng),但它仍然存在一些核心問題:

  • 模塊加載是同步的,每個模塊都按照需要的順序一一加載和執(zhí)行。
  • 難以進行 tree shaking,這可以刪除未使用的模塊并最小化包大小。
  • 不是瀏覽器原生的,需要打包工具和轉(zhuǎn)譯器來使所有這些代碼在客戶端工作。使用 CommonJS,您=要么陷入巨大的構(gòu)建步驟,要么為客戶端和服務端編寫單獨的代碼。

到 2013 年,CommonJS 小組開始逐漸解體。但到了那一年,負責監(jiān)督 JavaScript 核心語言更新的 TC39 委員會已經(jīng)開始開發(fā) CommonJS 模塊的后繼者:ECMAScript 模塊。

ECMAScript 模塊是面向Web的

隨著ES6語言規(guī)范的發(fā)布,TC39委員會最終引入了一個直接嵌入到JavaScript語言中的模塊系統(tǒng)。其目標是構(gòu)建一個適用于Web的單一模塊加載器系統(tǒng),包括異步模塊加載、與瀏覽器兼容、靜態(tài)分析和 tree shaking。ES模塊假設它們將從網(wǎng)絡中獲取數(shù)據(jù),而不是從文件系統(tǒng)中獲取,以提供更好的性能和用戶體驗。

現(xiàn)在,由于模塊加載系統(tǒng)已經(jīng)直接集成到語言中,大家都會使用它,這樣就可以將精力集中在更高級別、更重要的問題上了。

Node 決定同時支持 CJS 和 ESM

Borins 是 Node“模塊團隊”的開發(fā)人員之一,負責在 Node.js 中實現(xiàn) ES 模塊。盡管成功地將 ESM 添加到 Node,但團隊未能就 ESM 和 CJS 之間的互操作性達成明確的共識。然而 Node 無法擺脫 CJS,因為它的嵌入程度如此之深。這意味著互操作性問題被推給了軟件包作者。

以下是支持 ESM 和 CJS 所需的模塊 package.json 的片段:

顯然,支持 CommonJS 已經(jīng)成為不容忽視的問題。但是,CommonJS 真的是一無是處嘛?

CommonJS 的優(yōu)勢

CommonJS 啟動速度更快

對于較大的應用,ES 模塊速度較慢。與 require 不同,要么需要在使用語句時加載整個模塊圖,要么需要使用表達式等待每個導入。例如,如果想要延遲加載一個包以在函數(shù)中使用,代碼必須返回一個 Promise。

async function transpileEsm(code) {
  const { transform } = await import("@babel/core");
  // ... return 必須是一個 Promise
}

function transpileCjs(code) {
  const { transform } = require("@babel/core");
  // ... return 是同步的
}

ES模塊為了綁定導入和導出,需要進行兩次處理。整個模塊圖會被解析和分析,然后代碼會被評估。這些被分為不同的步驟。正是這種方式使得ES模塊中的“實時綁定”成為可能。

考慮以下兩個簡單的文件:

// babel.cjs
require("@babel/core")

// babel.mjs
import "@babel/core";

Babel 是一個由大量文件組成的包,因此比較這兩個文件的運行時間是評估與模塊解析相關的性能成本的好方法。結(jié)果如下:

在 Bun 中(一個新的 JavaScript 運行時),使用 CommonJS 加載 Babel 的速度大約比使用 ES 模塊快 2.4 倍,相差了 85ms。在無服務器冷啟動的情況下,這個差距是巨大的。在 Node.js 中,差異為 1.8 倍(約 60 毫秒)。

增量加載

CommonJS 允許動態(tài)模塊加載——可以有條件地 require() 文件,或者 require() 動態(tài)構(gòu)造的路徑/說明符,或者在函數(shù)體中 require()。這種靈活性在需要動態(tài)加載的場景中非常有利,例如插件系統(tǒng)或基于用戶交互的延遲加載特定組件。

ES 模塊提供了具有類似屬性的動態(tài) import() 函數(shù)。從某種意義上說,它的存在證明了 CommonJS 的動態(tài)方法具有實用性并受到開發(fā)人員的重視。

現(xiàn)狀

發(fā)布到 npm 的數(shù)百萬個模塊已經(jīng)使用 CommonJS,其中許多都是:

(a) 不再積極維護。

(b) 對現(xiàn)有項目很重要。

可能永遠不會達到所有包都可以使用 ES 模塊的地步。不支持CommonJS的運行時或框架將失去巨大的價值。

小結(jié)

盡管 ES Modules(ESM)的出現(xiàn)給予了 CommonJS 微弱的競爭壓力,但我們可以得出結(jié)論:CommonJS 不會輕易消失。

CommonJS 在 Node.js 生態(tài)系統(tǒng)中的廣泛應用以及大量已發(fā)布在 npm 上的模塊都使用了 CommonJS 規(guī)范,這使得 CommonJS 成為不可忽視的存在。很多模塊雖然不再得到積極維護,但對于現(xiàn)有項目仍具有重要性。因此,在實際應用中,對于不支持 CommonJS 的運行時或框架來說,忽視 CommonJS 將意味著錯失巨大的價值。

盡管 ES Modules 在語言層面提供了更強大的靜態(tài)分析和優(yōu)化能力,并且被認為是 JavaScript 的未來,但 CommonJS 仍然具有優(yōu)勢。它簡單易用,適合動態(tài)加載和代碼重用。因此,在目前的情況下,我們?nèi)匀恍枰獙?CommonJS 視為一個重要的模塊化規(guī)范。

無論是 CommonJS 還是 ES Modules,它們都有各自的特點和適用場景。我們不應該試圖完全取代 CommonJS,而是應該在技術發(fā)展的過程中平衡實用性和未來趨勢。只有這樣,才能更好地利用 JavaScript 的模塊化能力,為項目和生態(tài)系統(tǒng)帶來最大的價值。

參考資料:

  • https://bun.sh/blog/commonjs-is-not-going-away。
  • https://deno.com/blog/commonjs-is-hurting-javascript。
責任編輯:姜華 來源: 前端充電寶
相關推薦

2012-11-08 09:45:44

JavaScriptrequireJS

2020-11-09 10:46:35

CommonJS

2021-06-10 18:40:32

ES 標準模塊化

2019-08-28 16:18:39

JavaScriptJS前端

2023-03-20 16:18:08

JavascriptCSS前端

2018-12-18 11:20:28

前端模塊化JavaScript

2023-01-11 07:20:27

編程能力人工智能

2022-03-01 10:51:55

自動駕駛汽車底盤

2013-08-20 15:31:18

前端模塊化

2017-05-18 10:23:55

模塊化開發(fā)RequireJsJavascript

2020-09-17 10:30:21

前端模塊化組件

2015-10-10 11:29:45

Java模塊化系統(tǒng)初探

2020-09-18 09:02:32

前端模塊化

2022-03-11 13:01:27

前端模塊

2009-06-05 07:41:19

Java 7模塊化JDK 7

2022-06-15 09:26:43

Perl編程語言

2018-03-21 21:31:28

Java9編程Java

2022-09-05 09:01:13

前端模塊化

2018-06-21 09:36:09

模塊化數(shù)據(jù)中心集中化

2019-09-02 10:51:59

Python腳本語言程序員
點贊
收藏

51CTO技術棧公眾號