在 JavaScript 的發展歷程中,模組系統是非常重要的一環。
目前主要存在兩種模組系統:CommonJS (CJS) 與 ECMAScript Modules (ESM)。
它們在設計理念、使用方式、支援環境上都有明顯的差異。
在 npm 套件中,可以透過 package.json 定義模組的入口點:
這樣做可以讓同一個套件同時提供 CJS 與 ESM 的版本,方便不同環境使用。
模組系統的一個重要差別,就是是否預設使用 嚴格模式 (strict mode)。
設計於 ECMAScript 5 之前,默認非嚴格模式。
特性:
允許在函數中使用未宣告的變數
在同一作用域使用this來引用全局對象 (global)
this 在函數中會指向全域物件。
可以刪除變數、刪除物件屬性,這些在嚴格模式中是禁止的。
由 ECMAScript 標準引入,默認嚴格模式。
嚴格模式下:
變數必須先宣告才能使用。
this 在模組頂層或函數中不再指向全域物件,而是 undefined。
禁止使用 with 等危險語法。
嚴格模式的目的,是消除 JavaScript 中一些不良行為,提高程式的安全性與可維護性。
瀏覽器原生支援 ESM,可以使用 引入。
但瀏覽器並不支援 CJS,因此如果要在瀏覽器使用 npm 上的 CJS 套件,就需要打包工具。
npm 上大部分套件最初都是以 CJS 發布。
當模組的入口點改變(CJS → ESM),就需要調整所有的 import 或 require 語法。
由於相容性問題,許多套件會同時提供 CJS 與 ESM 版本。
工具的角色
瀏覽器原生模組機制雖然標準化,但在實務上會遇到相容性問題,無法直接兼容 npm 上大量的 CJS 套件。
因此,才需要透過 webpack、rollup、vite 等工具進行打包,讓 CJS 與 ESM 可以互相轉換並共存。