日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
混亂是進(jìn)步的階梯—ESM規(guī)范的崛起【上】

 前言

前端發(fā)展到如今,社區(qū)生態(tài)已經(jīng)非常豐富。

在無數(shù)開源大神的努力下,很多前端開發(fā)的痛點(diǎn)(比如「靜態(tài)類型檢查」、「瀏覽器兼容性」)早已有了事實(shí)上的標(biāo)準(zhǔn)解決方案(比如TS、babel)。

然而,在這繁榮之下,有一個(gè)日常開發(fā)不易感知的問題:

  • 模塊化規(guī)范的混亂

你可曾遇到過莫名其妙的bug,在多方搜資源,反復(fù)驗(yàn)證,耗費(fèi)數(shù)個(gè)小時(shí)終于發(fā)現(xiàn):

原來是某個(gè)包導(dǎo)出的是CJS,而項(xiàng)目使用ESM導(dǎo)致。

比如這個(gè)例子:記一次打包壓縮報(bào)錯(cuò)[1]

如果你覺得這是個(gè)很容易發(fā)現(xiàn)的問題,再考慮結(jié)合上node_modules的層層依賴呢?

這個(gè)問題,揭開了模塊化規(guī)范間斗爭(zhēng)與博弈的冰山一角。

作為現(xiàn)代前端工程化的基石,模塊化規(guī)范有太多值得深究的內(nèi)容。

我會(huì)花幾篇文章來講解模塊化規(guī)范。本文是第一篇,會(huì)圍繞模塊化規(guī)范的演進(jìn)展開。

正文

如果問十年前的前端最頭疼的是什么?一定是瀏覽器兼容性。

隨著babel等編譯工具出現(xiàn),兼容性逐漸被工程化方案解決(ES6+編譯為ES5)。

不僅是「兼容性」問題,DSL(如JSX、VUE的模版語法)、代碼壓縮、代碼靜態(tài)檢查(TS)等日常開發(fā)的剛需都能在工程化方案中找到解決辦法。

如果將當(dāng)今繁榮的前端工程化生態(tài)比喻為一座大廈,那大廈的地基一定是「模塊化規(guī)范」。

現(xiàn)代JS代碼都是基于「模塊化規(guī)范」組織起來,讓我們從下往上來看看這座大廈:

規(guī)范的實(shí)現(xiàn)依賴于宿主環(huán)境,比如瀏覽器環(huán)境實(shí)現(xiàn)了EcmaScript Module(后文簡(jiǎn)稱ESM)規(guī)范。

Node v12之前支持CommonJS(后文簡(jiǎn)稱CJS)規(guī)范,12之后同時(shí)支持CJS與ESM。

在「宿主環(huán)境」之上,是基于模塊化規(guī)范實(shí)現(xiàn)的「工具集」,比如webpack、vite、VScode生態(tài)。

再往上,基于「工具集」提供的API,可以實(shí)現(xiàn)各種工程化工具。比如:

  • webpack loader
  • VScode plugin
  • babel plugin

再往上,就是開發(fā)者自己編寫的業(yè)務(wù)代碼。

開發(fā)者只需要在工具集中配置好工具,就能為業(yè)務(wù)代碼提供服務(wù)。比如:

在VScode(工具集)中配置eslint(工具),就能在開發(fā)時(shí)獲得相應(yīng)提示

在webpack(工具集)中配置babel loader(工具),就能在開發(fā)時(shí)使用ES6+語法

可見,理想狀態(tài)下,在開發(fā)者視角是不需要關(guān)注底層的「模塊化規(guī)范」實(shí)現(xiàn)的。

規(guī)范之爭(zhēng)

然而,事物是動(dòng)態(tài)發(fā)展的,模塊化規(guī)范也不是一蹴而就的,讓我們回到09年。

美國(guó)程序員「Ryan Dahl」創(chuàng)造了node.js項(xiàng)目,將JS用于服務(wù)端開發(fā)。

node.js使用CJS[2]標(biāo)準(zhǔn)作為模塊化規(guī)范。

有了服務(wù)端模塊規(guī)范(CJS),很自然的,JS開發(fā)者們想為客戶端(主要是瀏覽器)提供一種模塊化規(guī)范。

然而CJS是為服務(wù)端設(shè)計(jì)的。

在服務(wù)端,IO操作通常能迅速完成,所以CJS規(guī)范定義的:

  • 模塊加載 --> 模塊解析 --> 模塊執(zhí)行

這個(gè)流程是作為一個(gè)整體同步執(zhí)行的。

然而在瀏覽器環(huán)境,「模塊加載」(即數(shù)據(jù)請(qǐng)求)通常很耗時(shí)。有人曾作出一個(gè)形象的比喻:

如果一個(gè)CPU周期花費(fèi)1秒完成,那么文件的網(wǎng)絡(luò)請(qǐng)求需要花費(fèi)4年。

顯然瀏覽器端需要一種「支持異步」的模塊化規(guī)范。

AMD(Asynchronous Module Definition 異步模塊定義)規(guī)范,就是這樣需求背景下的產(chǎn)物。

然而這些社區(qū)提出的規(guī)范終究只是為了解決一時(shí)的需求,隨著歷史的發(fā)展,新的模塊化規(guī)范不斷涌入、消亡。

直到ESM規(guī)范被提出。

ESM規(guī)范是ES標(biāo)準(zhǔn)的模塊化規(guī)范,他的早期討論可以追溯到2009年。

你可以在這里看到ESM規(guī)范的歷史es-module-history[3]

ESM將模塊規(guī)范分為三個(gè)階段:

  • 模塊加載 --> 模塊實(shí)例化 --> 模塊執(zhí)行

其中「模塊加載」由宿主環(huán)境提供的loader完成(比如在瀏覽器環(huán)境,loader的行為由HTML規(guī)范[4]定義)。

「模塊實(shí)例化」與「模塊執(zhí)行」由ESM規(guī)范定義執(zhí)行流程。

區(qū)別于CJS規(guī)范的同步執(zhí)行,ESM規(guī)范將流程拆解為3個(gè)獨(dú)立階段。

「模塊加載」同步、異步與否由宿主環(huán)境決定。

支持不同宿主環(huán)境,抹平多端差異、能力比其他規(guī)范都強(qiáng)大(后文會(huì)介紹)、再加上血統(tǒng)純正(ES官方提出),

使得ESM規(guī)范一統(tǒng)前端「看似」指日可待。

然而,此時(shí)社區(qū)已經(jīng)有大量基于CJS規(guī)范產(chǎn)出的開源包、組件,他們無法立刻切換到ESM規(guī)范。

所以,JS生態(tài)的現(xiàn)狀是:會(huì)處于、并將長(zhǎng)期處于CJS規(guī)范的庫與ESM規(guī)范的庫共存的狀態(tài)。

但是最終,ESM規(guī)范一定會(huì)成為主導(dǎo),畢竟他的優(yōu)點(diǎn)太多(同樣,后文會(huì)介紹)。

規(guī)范割裂帶來的機(jī)會(huì)

當(dāng)前模塊化規(guī)范的混亂,對(duì)開源大佬們來說,就是機(jī)會(huì)。

為了讓開發(fā)者將更多精力放在業(yè)務(wù),而不是模塊規(guī)范的適配上。

很多開源「工具集」都試圖抹平模塊化差異,比如:

  • 在babel中使用babel-plugin-transform-commonjs可以將CJS規(guī)范的代碼轉(zhuǎn)換為ESM規(guī)范
  • 為了一刀切解決當(dāng)前ESM、CJS、瀏覽器script標(biāo)簽導(dǎo)入這3種規(guī)范互相不兼容的情況,提出了兼容三者格式的UMD(Universal Module Definition)規(guī)范

一些「工具集」利用模塊化規(guī)范的不同與其他競(jìng)品形成差異化競(jìng)爭(zhēng),比如:

  • browserify這款打包工具的賣點(diǎn)是:使用CJS規(guī)范打包,使一份代碼同時(shí)在Node環(huán)境與瀏覽器環(huán)境(打包后)執(zhí)行。

其中,在瀏覽器環(huán)境中,Node的一些核心庫(如events、stream、path...)會(huì)被打包成瀏覽器支持的版本。

  • Vite在DEV環(huán)境使用ESM規(guī)范構(gòu)建模塊間的依賴關(guān)系。

依賴于大部分現(xiàn)代瀏覽器原生支持ESM規(guī)范,省去了打包的過程,使其編譯速度大大提升。

  • rollup原生對(duì)ESM提供更多支持。

嚴(yán)格支持ESM規(guī)范,并提供更好的靜態(tài)分析,使rollup一度提供性能更優(yōu)異的treeShaking能力。

成為更多庫打包工具的選擇。

與webpack這樣的的大而全方案形成差異競(jìng)爭(zhēng)。

規(guī)范割裂帶來的痛

可以看到,由于底層宿主環(huán)境對(duì)模塊化規(guī)范支持的割裂,需要上層工具集來抹平模塊規(guī)范的差異。

設(shè)想一個(gè)同時(shí)使用了webpack、babel、TS的項(xiàng)目。

這3個(gè)工具集都對(duì)多種模塊規(guī)范有兼容處理。比如:

單獨(dú)使用babel時(shí),對(duì)于如下代碼:

 
 
 
 
  1. import a from 'lib';
  2. console.log(a);

會(huì)被babel編譯為:

 
 
 
 
  1. "use strict";
  2. var _lib = _interopRequireDefault(require("lib"));
  3. function _interopRequireDefault(obj) {
  4.   return obj && obj.__esModule ? obj : { default: obj };
  5. }
  6. console.log(_lib.default);

ESM的「默認(rèn)導(dǎo)出」會(huì)被編譯為包含default屬性的對(duì)象。

你可以打開babel playground[5]試試

當(dāng)多個(gè)「工具集」在同一個(gè)項(xiàng)目中,為了各自目的做著同一件事(抹平模塊化規(guī)范差異),

一旦工具鏈中某個(gè)插件配置有一絲絲不符合預(yù)期,或者引入了一個(gè)不符合預(yù)期的包,那么艱難的debug就此開始了......

曙光即使當(dāng)前有諸多不便,歷史的進(jìn)程是無法阻止的,那些被歷史巨輪甩下并碾碎的模塊化規(guī)范,會(huì)逐漸消失在開發(fā)者的視野中。

而贏家注定會(huì)通吃。

為什么ESM注定會(huì)成為最大贏家?他有什么無法比擬的優(yōu)勢(shì)?我們會(huì)在下篇文章揭曉。

參考資料

[1]記一次打包壓縮報(bào)錯(cuò):

https://cloud.tencent.com/developer/article/1650627

[2]CJS:

http://wiki.commonjs.org/wiki/Modules/1.1

[3]es-module-history:

https://gist.github.com/jkrems/769a8cd8806f7f57903b641c74b5f08a

[4]HTML規(guī)范:

https://html.spec.whatwg.org/#fetch-a-module-script-tree

[5]babel playground:

https://babeljs.io/repl


網(wǎng)頁題目:混亂是進(jìn)步的階梯—ESM規(guī)范的崛起【上】
瀏覽地址:http://m.5511xx.com/article/dhsdgsj.html