<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>

          這才是你需要了解的性能優(yōu)化呀!

          共 5579字,需瀏覽 12分鐘

           ·

          2021-06-18 13:06

          前言

          說到性能優(yōu)化,大家肯定能想到很多內(nèi)容。比如說如何修改 Webpack 配置來達(dá)到構(gòu)建提速以及優(yōu)化產(chǎn)物的需求;比如說如何對頁面進(jìn)行性能優(yōu)化等等。

          其實性能優(yōu)化還存在很多可以玩的地方,今天筆者就來聊一些大家不常關(guān)注的地方,從開發(fā)到 CI 的構(gòu)建階段以及最后部署上線這幾個鏈路。

          構(gòu)建階段

          構(gòu)建階段分為兩個部分:

          ?本地開發(fā)?CI 構(gòu)建

          這兩部分各自側(cè)重的點并不相同。前者更加關(guān)注構(gòu)建速度,對于產(chǎn)物沒有什么要求,畢竟本地開發(fā)時候構(gòu)建是一件很頻繁的事情,速度慢就意味著降低開發(fā)效率;后者更關(guān)注產(chǎn)物,比如說文件體積、數(shù)量等等指標(biāo),當(dāng)然了構(gòu)建速度也不能說完全不關(guān)心,但多是在保證產(chǎn)物的前提下再去提升構(gòu)建速度。

          接下來筆者會就這兩部分來分別聊聊我們可以做的性能優(yōu)化。

          本地開發(fā)

          以 Webpack 為例,本地開發(fā)構(gòu)建這部分是我們?nèi)粘9ぷ髦凶畛=佑|到的,如果能帶來一定的提速,那么感知還是挺強的。

          這部分主要分為兩個階段:

          ?啟動項目,比如說 yarn start?修改保存代碼觸發(fā)熱更新

          第一階段相對來說頻率低點,速度慢點在大部分情況下還是可以忍受的。

          但是第二階段是我們前端開發(fā)每天都會進(jìn)行數(shù)十次甚至上百次的高配操作,并且對于一些中大型項目來說,在這部分花的時間一次可能就需要 10 秒多。假設(shè)老王每天修改 100 次代碼,那么在這部分每天都得等待上 15 分鐘甚至更多。

          那么我們有辦法去提效這部分內(nèi)容么?答案是有的,應(yīng)該很多讀者都早已了解到這類產(chǎn)品了:Vite。

          Vite 屬于 NoBundle 方案,也可以稱之為 UnBundle、Bundleless,反正都是同一個玩意。同類競品還有 snowpack、wmr 等,當(dāng)然名氣都不如前者大。

          如果你已經(jīng)使用過 Vite,那么應(yīng)該對它秒級啟動以及熱更新有了映像,相比單純的 Webpack 提升巨大。

          截屏2021-06-06下午10.05.06

          上圖出自該文章,項目有 15 萬行代碼,很大型的一個項目了,大家可以發(fā)現(xiàn)在啟動以及熱更新上真的是有數(shù)十倍的提升,這對于開發(fā)體驗來說真的流暢很多。另外筆者之前也參與過公司內(nèi)部 NoBundle 方案的研發(fā),得出的數(shù)據(jù)也是很可觀的。

          那么為什么 Vite 能帶來這樣的體驗的呢,到底是如何實現(xiàn)這樣的效果的?筆者這里就粗略的來聊聊。

          首先來聊聊 Webpack 構(gòu)建,基于 Webpack4 以及中大型項目來說。當(dāng)我們執(zhí)行 yarn start 以后,Webpack 會開始全量打包,構(gòu)建出依賴圖后把所有內(nèi)容都打成幾個文件,這個構(gòu)建依賴圖以及打包的過程會花掉我們數(shù)分鐘。

          當(dāng)觸發(fā)熱更新的時候,Webpack 也需要找出這一條依賴鏈路并再次對鏈路進(jìn)行打包,因此這個過程耗時也不少。當(dāng)然如果你用上了 Webpack5 的話,基于持久化緩存應(yīng)該能提速不少。

          基于打包器的開發(fā)服務(wù)器

          但是對于 Vite 來說就不需要這樣干了。

          首先 Vite 使用到了 ESBuild 來預(yù)構(gòu)建依賴,這是一個用 Go 寫的特別牛逼的構(gòu)建器,效率相比 JS 來說快了數(shù)十倍甚至百倍,Vite 需要利用這個來處理模塊以及構(gòu)建 ESM 環(huán)境。

          另外就是得益于 ESM 按需加載的特性,我們無需啟動項目的時候構(gòu)建依賴圖以及打包文件,而是瀏覽器請求什么文件才編譯什么文件(比如說編譯 TS、插入熱更新代碼等),依托于這個特性我們能很快的跑起來項目。

          最后當(dāng)用戶觸發(fā)熱更新的時候,Vite 也無需像 Webpack 那樣做,而是找出最小的依賴路徑(一般來說就是修改的那個文件),然后修改下文件的 hash 下發(fā)給瀏覽器失效之前的緩存即可。

          基于上面的一些特性以及 ESBuild,Vite 基本不會因為代碼量變大而造成速度有明顯拖慢,但是對于 Webpack 來說,項目體積很明顯會拖慢構(gòu)建速度。

          基于 ESM 的開發(fā)服務(wù)器

          讀者看到這里,可能覺得這玩意確實牛逼,摩拳擦掌準(zhǔn)備干上一番。但是,這里要給各位潑個冷水。根據(jù)我們內(nèi)部的 Nobundle 使用結(jié)果以及筆者與多位在大廠做過這個方案的朋友交流的結(jié)果來看,接入業(yè)務(wù)成本巨大,雖然提效不錯,但是以接入的成本來看可能投入產(chǎn)出比就不是那么可觀了。目前也沒有一套很好的接入方案,很可能在不同的項目里會踩到不同的坑,最大的原因還是來自于 ESM 環(huán)境。

          但是筆者認(rèn)為 Nobundle 以后一定會成為本地開發(fā)構(gòu)建的主流,因為開發(fā)體驗實在太順滑了。

          另外很可能讀者會問 Vite 是否會取締 Webpack 這類問題。筆者認(rèn)為這兩個東西算不上是競品,Webpack 能適用于復(fù)雜、需要定制化的場景,這點 Vite 是做不到的(未來可能也不會去做),Vite 主要是為了改善開發(fā)階段的體驗,頂多在開發(fā)階段 Vite 能頂替掉 Webpack 的工作。

          以下筆者列了點資料,大家有興趣可以了解下:

          ?云謙大大的 toy vite?15 萬行代碼遷移至 Vite 的系列文章

          最后大家如果有興趣在業(yè)務(wù)里做遷移的話,一定要多看看市面上遷移相關(guān)的文章,能幫助大家在踩坑的時候快速解決問題。

          CI

          在 CI 中構(gòu)建大致分為三個環(huán)節(jié):

          1.安裝依賴2.代碼質(zhì)量保障3.構(gòu)建

          前兩個環(huán)節(jié)涉及到的內(nèi)容不多,筆者這里就快速帶過。

          安裝依賴

          依賴安裝還是挺耗時的,我們可以通過以下幾點來加速這個環(huán)節(jié):

          ?源必須切換到淘寶源或者自己的私有源?緩存 node_modules 必須整上?有條件可以試試 yarn2

          這里稍微聊一下 yarn2 這個事情。升級到 yarn2 以后會有兩種可選方案,一種還是 node_modules 的方案,另一種是拋棄 node_modules,轉(zhuǎn)而使用 PnP。

          這兩種方案前者在遷移的過程中基本不用動代碼,但是已經(jīng)能改善依賴安裝的速度;后者需要變更的地方還挺多,在內(nèi)部全部推廣開來還是存在一部分阻力的,但是這種方案能夠大幅度減少依賴體積以及改善安裝速度,大家可以自行評估投入產(chǎn)出比。

          代碼質(zhì)量保障

          代碼質(zhì)量保障一般分為兩塊:

          ?ESLint?單測

          當(dāng)然還有別的質(zhì)量保障方案,這里就不表了。

          ESLint 其實沒啥優(yōu)化的方案,倒是本地提交代碼的時候大部分項目應(yīng)該都做了優(yōu)化,只是可能很多人都忽略了。想必大家項目中應(yīng)該都會存在 husky + Lint-stage,這兩個工具其實能幫助我們在提交代碼的時候只對需要提交的文件進(jìn)行 lint。這是一種增量的思路,在很多情況下我們都需要這種思路來幫助我們做性能優(yōu)化。

          對于單測來說,可能很多讀者壓根就沒寫過這玩意。但是如果你做過一些 npm 包或者 Node 服務(wù)的話,會發(fā)現(xiàn)單測還是挺有必要的。

          對于大型的項目來說,Test case 是相當(dāng)多的。以我們內(nèi)部的組件庫為例,總共有 1000+ 的 Test case,光在本地完整執(zhí)行一次 yarn test 就足足需要花費兩三分鐘,在云端跑的速度就更不用說了。但是實際上我們每次提交的代碼影響到的 Test case 遠(yuǎn)沒有那么多,每次全量跑單測花費的時間真的太多了。

          說到這兒,讀者們應(yīng)該能記起筆者上文提到過的增量。沒錯,在這里我們完全可以使用增量來提高跑單測的速度。如果你使用 Jest 框架的話,可以了解下和 —onlyChanged 相關(guān)聯(lián)的參數(shù)來實現(xiàn)增量單測。

          構(gòu)建

          說到構(gòu)建優(yōu)化,想必很多讀者都會說這題我會。畢竟優(yōu)化 Webpack 配置已經(jīng)算是面試考爛的題目了,并且市面上關(guān)于這類的文章也是層出不窮。

          因此筆者這里就不再來聊我們該這樣那樣配置 Webpack,如果讀者有需要的話可以自行網(wǎng)上翻閱資料。

          其實除了修改 Webpack 來達(dá)成性能優(yōu)化的目的,升級版本也會有很大的驚喜。

          比如說從 4 升級到 5 以后,我們可以通過這些新增特性來實現(xiàn)提效:

          ?持久化緩存,這玩意上文已經(jīng)講過了,可以幫助我們提高二次啟動及 HMR 的速度?更好用的 Tre shaking 能力,能夠更好地清除未使用的導(dǎo)出,進(jìn)一步降低構(gòu)建產(chǎn)物的體積?Prepack 能力,通過靜態(tài)計算降低代碼數(shù)量?聯(lián)邦模塊,能夠運行時加載遠(yuǎn)程模塊或者依賴,減少構(gòu)建所帶來的時間消耗

          筆者以上列舉了一部分升級 Webpack 能帶來的收益,大家如果對某個特性有興趣的話可以自行搜索文章。

          另外其實我們常說的構(gòu)建速度優(yōu)化,其中有一個點關(guān)注的人并不多,但是對構(gòu)建速度也有不小的影響,那就是壓縮代碼。

          如果你用過 Speed Measure Plugin 這個插件的話,就能發(fā)現(xiàn)筆者所言不虛。對于大型應(yīng)用來說,就算你使用多線程進(jìn)行壓縮,最終可能還是會花費二三十秒的時間。

          當(dāng)然了,我們是能夠?qū)@個階段做優(yōu)化的,用到的工具上文也說過,也就是 ESBuild。ESBuild 主打的就是構(gòu)建快,從官方的性能對比圖里可以看出是降維打擊其它構(gòu)建器。

          截屏2021-06-08下午10.34.37

          恐怖的數(shù)百倍提升(當(dāng)然筆者實測拿不到這樣的數(shù)據(jù)),但即使它構(gòu)建速度確實很快,目前還是存在了一些問題(最大的問題是 CSS 上的處理)導(dǎo)致上生產(chǎn)還是不大現(xiàn)實。但是實際上 ESBuild 還支持用于壓縮代碼,風(fēng)險基本可以忽略,筆者實測業(yè)務(wù)項目中能帶來 30% ~ 40% 的速度提升,還是相當(dāng)可觀的。

          另外除了以上說的這些之外,其實在構(gòu)建這個環(huán)節(jié)中我們也可以通過增量的思路來提升效率。

          對于多頁應(yīng)用來說,大部分情況下我們每次發(fā)布所修改的代碼不會影響到所有的入口。因此沒有被影響到的入口實際是不需要再次被構(gòu)建的,直接使用之前的緩存就行了。那么根據(jù)這個思路,我們需要每次在構(gòu)建前找出上次發(fā)布到當(dāng)前為止所有變動過的文件以及這些文件所影響的入口,最后動態(tài)修改 Webpack 的入口配置即可實現(xiàn)增量構(gòu)建

          說干就干,以下是增量構(gòu)建的大致思路。

          首先是找到距離上次發(fā)布后有變更的文件,這個很簡單,一行命令就搞定了:

          git diff --name-only {git tag / commit sha}

          部署完別忘了打個 tag 或者記錄一下 commit id,下次執(zhí)行命令的時候傳入。

          當(dāng)我們拿到變更后的文件名后,接下來需要找出這些文件所影響的入口,因此需要開始構(gòu)建依賴樹。雖然 Webpack 也會幫助我們構(gòu)建這個,但是我們沒必要用到那么重的東西,找個專注依賴樹的庫就行,大家可以選擇 madge 或者別的類似產(chǎn)品。

          接下來我們只需要匹配文件找到影響的幾個入口就行,然后動態(tài)修改 Webpack 配置里的 entry 屬性進(jìn)行構(gòu)建即可。

          最后我們將構(gòu)建的內(nèi)容替換掉之前的舊入口產(chǎn)物就行了,沒有變動的不需要管。

          其實這個多頁應(yīng)用的增量構(gòu)建做法和 monorepo 里的部署很相似。如果我們在 monorepo 里只需要對改過代碼的 package 進(jìn)行部署的話,那么部署代碼的邏輯是很相似的,同樣也是找到被影響的 package(多頁應(yīng)用里就是入口了),然后進(jìn)行構(gòu)建發(fā)布。

          如果大家業(yè)務(wù)中也存在多頁應(yīng)用的項目,那么可以嘗試下該方案,帶來的收益應(yīng)該會很可觀。

          小結(jié)

          說了那么多,筆者來總結(jié)一下上文中聊過的優(yōu)化手段:

          ?開發(fā)階段嘗試使用 NoBundle 替換 Webpack,效果很好,但是遷移成本需要考量?ESBuild 是個好東西,既能用于構(gòu)建,又能用于壓縮代碼。前者存在風(fēng)險且存在處理不佳的場景,后者風(fēng)險很小,效率也能有不錯的提高?安裝依賴提速可以從源、緩存、升級 yarn2 上著手?大型項目代碼質(zhì)量保障階段耗時過長,考慮通過增量方案來提速,當(dāng)然如果你覺得全量跑一遍更安心也沒啥毛病?CI 構(gòu)建層面,Webpack 配置相關(guān)的說爛了,還不了解的可以自行了解,另外升級 Webpack 也會有意想不到的收益,當(dāng)然遷移成本還是有的?多頁應(yīng)用沒必要每次都把所有入口構(gòu)建一遍,只構(gòu)建代碼影響的入口即可?增量思路在性能優(yōu)化里相當(dāng)普遍

          上線后

          上線后的通用性能優(yōu)化也被說爛了,無非從網(wǎng)絡(luò)協(xié)議、CSS、Webpack 配置入手,筆者還是來講點別的。

          既然要聊性能優(yōu)化,那么我們肯定得知道到底哪里存在性能問題,否則就是虛空優(yōu)化了。如何檢測性能優(yōu)化、到底有哪些性能指標(biāo)也是筆者常問的面試問題(當(dāng)然得面試者簡歷里寫了做過這方面),但是大部分時候得到的答案在筆者看來是不正確的,并不能確定到底對方是不是真的做過這方面的優(yōu)化。

          比如說談到性能指標(biāo),問十人九人必會說白屏?xí)r間,但是其實白屏?xí)r間在當(dāng)下并不是一個合格的指標(biāo)。大部分應(yīng)用開屏都會存在 Loading 或者骨架屏,在這些內(nèi)容過渡到頁面出現(xiàn)用戶關(guān)心的內(nèi)容還需要一段時間。但是如果我們僅僅靠收集白屏?xí)r間來判斷用戶看到 DOM 出現(xiàn)是錯誤的做法,單靠這個指標(biāo)去做開屏的優(yōu)化是遠(yuǎn)遠(yuǎn)不夠的,我們必須得收集到用戶看到真實 DOM 的時間。

          此時我們可以收集 LCP(Largest Contentful Paint)指標(biāo),這個指標(biāo)會幫助我們記錄頁面中最大內(nèi)容繪制的時間戳。

          img

          通過這個指標(biāo)外加白屏?xí)r間,我們才能夠正確的去做開屏?xí)r間的優(yōu)化。另外在這里不使用 LCP 指標(biāo)也是可以的,我們可以自己給關(guān)鍵 DOM 打點,實現(xiàn)個性化的收集。

          除了 LCP 指標(biāo)之外,還存在不少新的指標(biāo),大家有興趣的可以了解下筆者之前寫的文章,文中做幾個新的指標(biāo)做了闡述并說明了該如何優(yōu)化這些指標(biāo)。

          用戶體驗指標(biāo)

          最后

          以上就是本文的全部內(nèi)容了。性能優(yōu)化是一個很大的話題,除了那些耳熟能詳?shù)氖侄沃猓鋵嵾€存在著不少方案能做。

          瀏覽 41
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <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>
                  欧美一区亚洲一区 | 天天操天天操天天逼天天逼天天日天天逼 | 天堂一区二区三区18 | 国产探花在线播放 | 777精品视频在线 |