久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      聊聊Node兩種模塊規(guī)范:CJS 與 ESM,有什么不同點(diǎn)?

      本篇文章給大家?guī)Т蠹伊私庖幌翹ode的兩種模塊規(guī)范(難以相容的 CJS 與 ESM),介紹一下CJS 和 ESM 的不同點(diǎn),怎么實(shí)現(xiàn) CJS、ESM 混寫,希望對大家有所幫助!

      聊聊Node兩種模塊規(guī)范:CJS 與 ESM,有什么不同點(diǎn)?

      13.2.0 版本開始,Nodejs 在保留了 CommonJS(CJS)語法的前提下,新增了對 ES Modules(ESM)語法的支持。

      天下苦 CJS 久已,Node 逐漸擁抱新標(biāo)準(zhǔn)的規(guī)劃當(dāng)然值得稱贊,我們也會展望未來 Node 不再需要借助工具,就能打破兩種模塊化語法的壁壘……

      但實(shí)際上,一切沒有想象中的那么美好。

      一、并不完美的 ESM 支持

      1.1 在 Node 中使用 ESM

      Node 默認(rèn)只支持 CJS 語法,這意味著你書寫了一個 ESM 語法的 js 文件,將無法被執(zhí)行。

      如果想在 Node 中使用 ESM 語法,有兩種可行方式:

      • ⑴ 在 package.json 中新增 "type": "module" 配置項(xiàng)。
      • ⑵ 將希望使用 ESM 的文件改為 .mjs 后綴。

      對于第一種方式,Node 會將和 package.json 文件同路徑下的模塊,全部當(dāng)作 ESM 來解析。

      第二種方式不需要修改 package.json,Node 會自動地把全部 xxx.mjs 文件都作為 ESM 來解析。

      同理,如果在 package.json 文件中設(shè)置 "type": "commonjs",則表示該路徑下模塊以 CJS 形式來解析。 如果文件后綴名為 .cjs,Node 會自動地將其作為 CJS 模塊來解析(即使在 package.json 中配置為 ESM 模式)。

      我們可以通過上述修改 package.json 的方式,來讓全部模塊都以 ESM 形式執(zhí)行,然后項(xiàng)目上的模塊都統(tǒng)一使用 ESM 語法來書寫。

      如果存在較多陳舊的 CJS 模塊懶得修改,也沒關(guān)系,把它們?nèi)颗驳揭粋€文件夾,在該文件夾路徑下新增一個內(nèi)容為 {"type": "commonjs"}package.json 即可。

      Node 在解析某個被引用的模塊時(無論它是被 import 還是被 require),會根據(jù)被引用模塊的后綴名,或?qū)?yīng)的 package.json 配置去解析該模塊。

      1.2 ESM 引用 CJS 模塊的問題

      ESM 基本可以順利地 import CJS 模塊,但對于具名的 exports(Named exports,即被整體賦值的 module.exports),只能以 default export 的形式引入:

      /** @file cjs/a.js **/ // named exports module.exports = {     foo: () => {         console.log("It's a foo function...")     } }   /** @file index_err.js **/ import { foo } from './cjs/a.js';   // SyntaxError: Named export 'foo' not found. The requested module './cjs/a.js' is a CommonJS module, which may not support all module.exports as named exports. foo();   /** @file index_err.js **/ import pkg from './cjs/a.js';  // 以 default export 的形式引入 pkg.foo();  // 正常執(zhí)行

      到 Github 獲取示例代碼(test1):

      https://github.com/VaJoy/BlogDemo3/tree/main/220220/test1

      具體原因我們會在后續(xù)提及。

      1.3 CJS 引用 ESM 模塊的問題

      假設(shè)你在開發(fā)一個供別人使用的開源項(xiàng)目,且使用 ESM 的形式導(dǎo)出模塊,那么問題來了 —— 目前 CJS 的 require 函數(shù)無法直接引入 ESM 包,會報錯:

      let { foo } = require('./esm/b.js');               ^  Error [ERR_REQUIRE_ESM]: require() of ES Module BlogDemo3220220test2esmb.js from BlogDemo3220220test2require.js not supported. Instead change the require of b.js in BlogDemo3220220test2require.js to a dynamic import() which is available in all CommonJS modules.     at Object.<anonymous> (BlogDemo3220220test2require.js:4:15) {   code: 'ERR_REQUIRE_ESM' }

      按照上述錯誤陳述,我們不能并使用 require 引入 ES 模塊(原因會在后續(xù)提及),應(yīng)當(dāng)改為使用 CJS 模塊內(nèi)置的動態(tài) import 方法:

      import('./esm/b.js').then(({ foo }) => {     foo(); });  // or  (async () => {      const { foo } = await import('./esm/b.js');  })();

      到 Github 獲取示例代碼(test2):

      https://github.com/VaJoy/BlogDemo3/tree/main/220220/test2

      查閱 dynamic import 文檔

      https://v8.dev/features/dynamic-import#dynamic

      開源項(xiàng)目當(dāng)然不能強(qiáng)制要求用戶改用這種形式來引入,所以又得借助 rollup 之類的工具將項(xiàng)目編譯為 CJS 模塊……


      由上可見目前 Node.js 對 ESM 語法的支持是有限制的,如果不借助工具處理,這些限制可能會很糟心。

      對于想入門前端的新手來說,這些麻煩的規(guī)則和限制也會讓人困惑。

      截至我落筆書寫本文時, Node.js LTS 版本為 16.14.0,距離開始支持 ESM 的 13.2.0 版本已過去了兩年多的時間。

      那么為何 Node.js 到現(xiàn)在還無法打通 CJS 和 ESM?

      答案并非 Node.js 敵視 ESM 標(biāo)準(zhǔn)從而遲遲不做優(yōu)化,而是因?yàn)?—— CJS 和 ESM,二者真是太不一樣了。

      二、CJS 和 ESM 的不同點(diǎn)

      2.1 不同的加載邏輯

      在 CJS 模塊中,require() 是一個同步接口,它會直接從磁盤(或網(wǎng)絡(luò))讀取依賴模塊并立即執(zhí)行對應(yīng)的腳本。

      ESM 標(biāo)準(zhǔn)的模塊加載器則完全不同,它讀取到腳本后不會直接執(zhí)行,而是會先進(jìn)入編譯階段進(jìn)行模塊解析,檢查模塊上調(diào)用了 importexport 的地方,并順騰摸瓜把依賴模塊一個個異步、并行地下載下來。

      在此階段 ESM 加載器不會執(zhí)行任何依賴模塊代碼,只會進(jìn)行語法檢錯、確定模塊的依賴關(guān)系、確定模塊輸入和輸出的變量。

      最后 ESM 會進(jìn)入執(zhí)行階段,按順序執(zhí)行各模塊腳本。

      所以我們常常會說,CommonJS 模塊是運(yùn)行時加載,ES6 模塊是編譯時輸出接口。

      在上方 1.2 小節(jié),我們曾提及到 ESM 中無法通過指定依賴模塊屬性的形式引入 CJS named exports:

      /** @file cjs/a.js **/ // named exports module.exports = {     foo: () => {         console.log("It's a foo function...")     } }  /** @file index_err.js **/ import { foo } from './cjs/a.js';   // SyntaxError: Named export 'foo' not found. The requested module './cjs/a.js' is a CommonJS module, which may not support all module.exports as named exports. foo();

      這是因?yàn)?ESM 獲取所指定的依賴模塊屬性(花括號內(nèi)部的屬性),是需要在編譯階段進(jìn)行靜態(tài)分析的,而 CJS 的腳本要在執(zhí)行階段才能計算出它們的 named exports 的值,會導(dǎo)致 ESM 在編譯階段無法進(jìn)行分析。

      2.2 不同的模式

      ESM 默認(rèn)使用了嚴(yán)格模式(use strict),因此在 ES 模塊中的 this 不再指向全局對象(而是 undefined),且變量在聲明前無法使用。

      這也是為何在瀏覽器中,<script> 標(biāo)簽如要啟用原生引入 ES 模塊能力,必須加上 type="module" 告知瀏覽器應(yīng)當(dāng)把它和常規(guī) JS 區(qū)分開來處理。

      查看 ESM 嚴(yán)格模式的

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號-2    滬公網(wǎng)安備31011702889846號