<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          從 Bundleless 看前端構(gòu)建

          共 5241字,需瀏覽 11分鐘

           ·

          2021-06-08 12:52

          點(diǎn)擊上方 程序員成長(zhǎng)指北,關(guān)注公眾號(hào)

          回復(fù)1,加入高級(jí) Node 進(jìn)階交流群

          ??  點(diǎn)擊上方卡片關(guān)注

           原文鏈接:https://zhuanlan.zhihu.com/p/349406330

          作者:ES2049 Studio

          前言

          Bundle or Bundleless?自 2015 年 ESM 標(biāo)準(zhǔn)發(fā)布后,路線之爭(zhēng)就開始逐步升溫。轉(zhuǎn)眼間,時(shí)間已來到 2021 年。如果白酒的車你錯(cuò)過了,那么不妨看看 Bundleless,或許它就是前端圈的下一位「茅臺(tái)」。

          前端構(gòu)建當(dāng)下的問題

          不得不說,曾經(jīng)把自己定位為「打包器」的 Webpack,如今已形成強(qiáng)大的構(gòu)建生態(tài),儼然一統(tǒng)江湖。但前端構(gòu)建的道路還遠(yuǎn)沒有走到最后。隨著業(yè)務(wù)的發(fā)展,前端工程的復(fù)雜度越來越高,構(gòu)建方面的也開始暴露出新的問題。

          構(gòu)建時(shí)間逐步拉長(zhǎng)

          相信許多前端同學(xué)剛?cè)胄袝r(shí),都經(jīng)歷過「刷新一下全都有」的幸福時(shí)光:寫幾個(gè) HTML 標(biāo)簽,寫幾句內(nèi)嵌代碼,瀏覽器中就會(huì)呈現(xiàn)出美妙的 UI。而如今,業(yè)務(wù)工程越來越復(fù)雜,代碼量連年增長(zhǎng),構(gòu)建的時(shí)間也越來越長(zhǎng)。曾經(jīng)「秒級(jí)構(gòu)建」的前端,終究躋身「分鐘級(jí)構(gòu)建」的圈子了。

          img

          前端工程構(gòu)建時(shí)間的拉長(zhǎng),自然使得前端開發(fā)者在日常業(yè)務(wù)工作中的狀態(tài),從圖左逐漸運(yùn)動(dòng)到了圖右。

          img

          模塊標(biāo)準(zhǔn)引領(lǐng)方向

          如果我們縱觀前端領(lǐng)域的發(fā)展,就可以看到標(biāo)準(zhǔn)是如何推動(dòng)各大瀏覽器建設(shè),整個(gè)前端生態(tài)又是如何發(fā)生的變化。

          img

          2002 年,AJAX 推出,此后前端承擔(dān)的工作越來越多。彼時(shí),瀏覽器廠各行其是,因此兼容性是當(dāng)時(shí)的主要問題。于是 2006 年,jQuery 的出現(xiàn)進(jìn)一步帶動(dòng)了前端的發(fā)展。

          2009 - 2011 年,CommonJS、AMD、UMD 相繼為 JS 帶來了模塊規(guī)范。同一時(shí)期,部分遵循 CommonJS 的 Node 為 JS 帶來了運(yùn)行環(huán)境,為前端工程化的解鎖奠定基礎(chǔ):

          • 模塊加載工具開始涌現(xiàn),如 RequireJS、SeaJS 等
          • 包管理工具,如 npm、spm 等
          • 輕量的打包器開始出現(xiàn),如 Browserify
          • 任務(wù)工具開始出現(xiàn),如 Gulp

          Angular、React、Vue 等的相繼火爆,也推動(dòng)了前端的又一波浪潮:它們的發(fā)展提高了前端在業(yè)務(wù)中的表達(dá)能力,并向更高程度的工程化提出訴求。

          2015 年,HTTP/2.0 推出,同時(shí) JS 迎來了自己的模塊標(biāo)準(zhǔn) ESM:ES2015 一發(fā)布,Babel 就讓開發(fā)者們用上了 ES Module,真香。于是此后的幾年,Webpack & Babel 幾乎成了前端工程化的代名詞,甚至讓人以為,前端工程化已成定局。

          2018 年,Chrome、Safari、Firefox 相繼完成了對(duì) ESM 的支持。但得益于 Webpack 生態(tài)對(duì) CommonJS、AMD、UMD 的支持,開發(fā)者們對(duì) ESM 的享用更多是在編碼階段和一定程度的 Tree-shaking,在構(gòu)建層面并沒有直接的得利。

          總結(jié)

          當(dāng)下時(shí)間點(diǎn),出現(xiàn)了新的契機(jī):其一,「工程體積的日益增長(zhǎng)」與「亟待提升的構(gòu)建性能」之間的矛盾;其二,「先進(jìn)的前端模塊標(biāo)準(zhǔn)」與「落后的前端模塊規(guī)范」之間的矛盾。

          Bundleless 為什么是答案

          Bundleless 說到底,就是指無打包構(gòu)建,與我們當(dāng)下流行的打包構(gòu)建相對(duì),而打包器則是我們前端開發(fā)者用于將 JS 模塊打包成單一的、可在瀏覽器內(nèi)運(yùn)行的文件的工具。

          為什么過去需要打包

          這一問題在社區(qū)也有非常多的總結(jié),概況來講,主要包括以下理由:

          • HTTP/1.1 各瀏覽器有并行連接限制
          • 瀏覽器不支持模塊系統(tǒng)(如 CommonJS 包不能直接在瀏覽器運(yùn)行)
          • 代碼依賴關(guān)系與順序管理

          HTTP/1.1 各瀏覽器默認(rèn)并行連接數(shù)

          瀏覽器 Firefox 3+ Opera 12 Safari 5 IE 7 IE 10 Edge Chrome
          并行連接 6 6 6 2 8 6 6

          為什么開始嘗試不打包

          近幾年時(shí)間,標(biāo)準(zhǔn)的確立、瀏覽器大廠和前端生態(tài)的跟進(jìn),使得「不打包」成為可能:

          • HTTP/2.0 多路并用
          • 各大瀏覽器逐一支持 ESM
          • 越來越多的 npm 包擁抱 ESM(盡管很多包的依賴并不是)

          我們可以發(fā)現(xiàn):

          • 通過打包來減少網(wǎng)絡(luò)請(qǐng)求數(shù)量從而提高性能的優(yōu)化手段理論上在 HTTP/2.0 下會(huì)變得不再必要;
          • ESM 標(biāo)準(zhǔn)的推廣和各大瀏覽器的支持:
          • 讓模塊代碼可以直接在瀏覽器中運(yùn)行
          • 原生的解決了代碼依賴和復(fù)用的問題
          • 會(huì)進(jìn)一步推動(dòng)越來越多的 npm 包支持 ESM,甚至?xí)霈F(xiàn)新的包管理或分發(fā)方式

          Bundleless vs Bundle

          模塊加載的對(duì)比

          如果是打包式構(gòu)建,在模塊加載時(shí),實(shí)際上加載的是若干模塊的集合。這種方式的優(yōu)點(diǎn)是以少量的請(qǐng)求連接數(shù)完成 JS 腳本的下載。如果是無打包式構(gòu)建,模塊的加載則是基于原生模塊方案,直接獲取具體的模塊腳本。

          img

          本地開發(fā)構(gòu)建的對(duì)比

          如果是打包式構(gòu)建,無論是項(xiàng)目啟動(dòng)還是文件變更,都需要完整的走一遍打包過程。以 Webpack 為例,我們就會(huì)經(jīng)歷依賴分析、代碼轉(zhuǎn)譯和打包的過程,哪怕我們只是簡(jiǎn)單的修改了一行文案。當(dāng)然,Split chunk 會(huì)在一定程度上緩解這一問題,但粒度仍然偏大。

          img

          而無打包式構(gòu)建,在啟動(dòng)過程中基本只是啟動(dòng)服務(wù)(當(dāng)然不同的 Bundleless 方案可能還會(huì)做些其他的工作),而不用對(duì)業(yè)務(wù)代碼進(jìn)行依賴分析、打包,ESM 會(huì)幫助我們?cè)跒g覽器中完成依賴的分析。當(dāng)文件發(fā)生變更時(shí),本地開發(fā)服務(wù)只是提供了文件的映射,只需要重新轉(zhuǎn)譯對(duì)應(yīng)的文件,并重新替換即可。

          結(jié)論

          以上,我們可以知道:

          • 打包過程的必要性已降低
          • 擁抱 ESM 是未來趨勢(shì)

          社區(qū)在領(lǐng)域內(nèi)的工作

          概覽

          前端構(gòu)建并不只是構(gòu)建工具的問題。事實(shí)上,「構(gòu)建」和「分發(fā)」共同組成了前端工程的構(gòu)建,只不過通常情況下,我們是通過 npm install 將三方包下載下來,并打包到構(gòu)建結(jié)果中實(shí)現(xiàn)的。

          構(gòu)建可以分為兩種類型。

          一種是基于服務(wù)的構(gòu)建方式,通常服務(wù)于實(shí)際生產(chǎn)。我們可以再細(xì)分成本地服務(wù)構(gòu)建遠(yuǎn)端服務(wù)構(gòu)建本地服務(wù)構(gòu)建就是我們常規(guī)的操作,目前基本已經(jīng)被 Webpack 統(tǒng)治,是 Bundle 方案的代表;Snowpack、Vite、Web Dev Server 則是目前非常火的 Bundleless 方案,近一年的時(shí)間里勢(shì)頭迅猛。遠(yuǎn)端服務(wù)構(gòu)建則是依托云能力的玩法,把構(gòu)建過程放在服務(wù)端完成,從而把本地的開發(fā)流程搬到 Web 上,并給出于本地服務(wù)構(gòu)建基本一致的體驗(yàn)。

          另一種是基于瀏覽器的構(gòu)建方式,通常面向 Demo 的快速搭建或預(yù)覽方案。Codesandbox、StackBlitz、CodePen 和 Riddle 是業(yè)內(nèi)較出色的方案,整體是在瀏覽器端實(shí)現(xiàn)代碼的編譯、打包、構(gòu)建和運(yùn)行。當(dāng)然,具體到各個(gè)方案的細(xì)節(jié),通常對(duì)服務(wù)還是有一定依賴。

          img

          目前來看,100% 在瀏覽器端進(jìn)行打包、構(gòu)建,現(xiàn)階段并不是最理想的方案。隨著 Bundleless 的發(fā)展,瀏覽器 Bundleless 和包分發(fā)平臺(tái)的結(jié)合會(huì)得到進(jìn)一步的發(fā)展,并逐步影響前端工程的架構(gòu)。

          Snowpack

          原理

          這一部分在 Snowpack 的文檔上有一定的講解。整體來說,Snowpack 盡可能利用了現(xiàn)有前端生態(tài)的工具,對(duì)三方包打包來壓縮依賴鏈,對(duì)業(yè)務(wù)代碼走無構(gòu)建路線,以此提供 Bundleless 體系下的開發(fā)體驗(yàn)。值得一提的是,Snowpack 的構(gòu)建速度很快,這得益于內(nèi)置打包工具 esbuild 的發(fā)展。

          img

          Snowpack vs Webpack

          我們不妨將其與 Webpack 進(jìn)行一個(gè)對(duì)比。

          img

          啟動(dòng)時(shí)間,如上文所說,Webpack 會(huì)完整打包整個(gè)項(xiàng)目,因此隨著項(xiàng)目體積的增長(zhǎng),啟動(dòng)時(shí)間也會(huì)越發(fā)漫長(zhǎng);而 Snowpack 主要是啟動(dòng)本地的服務(wù),對(duì)于 Snowpack 來說,盡管初次啟動(dòng)時(shí)會(huì)分析三方依賴,并通過 Rollup 將其進(jìn)行打包,但是打包結(jié)果會(huì)緩存在 node_modules/.cache/snowpack/development 目錄下,后續(xù)就可以享受到飛一樣的啟動(dòng)。

          構(gòu)建時(shí)間,對(duì)于 Webpack 而言,構(gòu)建時(shí)長(zhǎng)會(huì)隨著項(xiàng)目體積整體以線性方式增長(zhǎng);而 Snowpack 的模式則是 O(1) 的復(fù)雜度(當(dāng)然這里也有點(diǎn)小噱頭)。

          緩存能力,可以說 Webpack 的緩存利用率尚有優(yōu)化空間。盡管我們可以通過 Split Chunk,合理的劃分打包方式,但如果我們只是改了一句文案,那么用戶側(cè)仍然會(huì)重新獲取對(duì)應(yīng) Chunk 資源。Snowpack 的緩存利用率近乎完美。業(yè)務(wù)代碼文件發(fā)生變更,直接替代產(chǎn)出資源,其他全部可返回緩存;三方依賴包,如 react.js,則直接更新該包,其他全部可用緩存。不過,盡管生產(chǎn)環(huán)境優(yōu)化可以做 Tree-shaking,但是業(yè)務(wù)代碼本身,Snowpack 并不會(huì)做處理(只是以 ESM 來對(duì)待),即使使用 Snowpack 生態(tài)的 Webpack 插件來做生產(chǎn)環(huán)境的構(gòu)建也是如此,所以是近乎完美,這是相對(duì)于理想的 DCE(dead code elimination) 而言的。Webpack 在生產(chǎn)環(huán)境會(huì)把沒有使用到的代碼 Tree-shaking 掉,不可謂不強(qiáng)大。

          至于調(diào)試體驗(yàn),因?yàn)?Webpack 需要打包,因此在調(diào)試的時(shí)候我們依賴 SourceMap 來幫助我們看到源碼。但對(duì)于 Snowpack 而言(實(shí)際上 Bundleless 模式都是如此),我們并不強(qiáng)依賴于 SourceMap,如果轉(zhuǎn)譯后的代碼閱讀無礙(ES6 其實(shí)還好嘛),就可以直接進(jìn)行單文件調(diào)試。

          不過即使 Snowpack 有千番好,整個(gè) Bundleless 生態(tài)還不足以取代 Webpack。Webpack 終究是一代神器,只是我們明白 Bundleless 也確實(shí)代表了未來。

          ??Vite

          Vite 是尤大的力作,本篇便不再對(duì)其進(jìn)行討論。有趣的是,他和 Webpack 作者 Sean 在推上的討論可以看出,大佬們也在 Bundleless 方向不斷發(fā)力,Webpack 成為了大家發(fā)起挑戰(zhàn)的目標(biāo)。

          img

          總結(jié)

          本文以 Bundleless 為切入點(diǎn),結(jié)合前端構(gòu)建的發(fā)展過程,對(duì)當(dāng)下無構(gòu)建方案進(jìn)行了討論。未來我們會(huì)更多的在此方面進(jìn)行實(shí)踐。

          如果覺得這篇文章還不錯(cuò)
          點(diǎn)擊下面卡片關(guān)注我
          來個(gè)【分享、點(diǎn)贊、在看】三連支持一下吧

             “分享、點(diǎn)贊在看” 支持一波  

          瀏覽 67
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  好操逼在线视频 | 青青草视频在线观看免费 | 影音先锋男人资源在线 | 日爽夜爽 | 97国产在线 |