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

          網(wǎng)頁(yè)性能提升 — 構(gòu)建優(yōu)化篇

          共 3145字,需瀏覽 7分鐘

           ·

          2020-12-27 16:04

          最近對(duì)公司的一個(gè) PC 站點(diǎn)做了一次整體的性能優(yōu)化,由于這個(gè)系統(tǒng)業(yè)務(wù)復(fù)雜、依賴非常多,加載速度非常慢,優(yōu)化后各個(gè)性能指標(biāo)都有了顯著提升,大約加載速度快了 5 倍左右。

          我在 構(gòu)建、網(wǎng)絡(luò)、資源加載、運(yùn)行時(shí)、服務(wù)端、功能組織等多個(gè)方面都進(jìn)行了優(yōu)化,準(zhǔn)備做一個(gè)系列,分章節(jié)給大家分享下我的優(yōu)化經(jīng)驗(yàn)。

          今天,我們從優(yōu)化效果最為明顯的構(gòu)建角度開(kāi)始。

          優(yōu)化前

          首先我們看一下在優(yōu)化前站點(diǎn)的資源加載情況:

          可見(jiàn)最大的?vendor?包居然有?3MB(經(jīng)過(guò)?gzip?壓縮后),沒(méi)有做額外配置的話,webpack?將所有的第三方依賴都打入了這個(gè)包,如果引入依賴越來(lái)越多,那么這個(gè)包就會(huì)越來(lái)越大。

          另外,系統(tǒng)本身的邏輯打的包也達(dá)到了?600kb

          分析依賴關(guān)系

          我們可以借助?webpack-bundle-analyzer?將打包后的內(nèi)容展示為方便交互的樹(shù)狀圖,我們可以很直觀的看到有哪些比較大的模塊,然后做針對(duì)性優(yōu)化。

          npm?install?--save-dev?webpack-bundle-analyzer

          const?BundleAnalyzerPlugin?=?require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
          module.exports?=?{
          ??plugins:?[
          ????new?BundleAnalyzerPlugin()
          ??]
          }

          CDN 引入

          CDN 的工作原理是將源站的資源緩存到位于全球各地的 CDN 節(jié)點(diǎn)上,用戶請(qǐng)求資源時(shí),就近返回節(jié)點(diǎn)上緩存的資源,而不需要每個(gè)用戶的請(qǐng)求都回您的源站獲取,避免網(wǎng)絡(luò)擁塞、緩解源站壓力,保證用戶訪問(wèn)資源的速度和體驗(yàn)。

          這個(gè)估計(jì)大家都明白,因?yàn)榇虬蟮漠a(chǎn)物本身也是上傳到?CDN?的。但是我們要做的是將體積較大的第三方依賴單獨(dú)拆出來(lái)放到?CDN?上,這樣這個(gè)依賴既不會(huì)占用打包資源,也不會(huì)影響最終包體積。

          如果一個(gè)依賴有直接打包壓縮好的單文件?CDN?資源,例如上面圖中的?g6,就可以直接使用。

          按照官方文檔的解釋,如果我們想引用一個(gè)庫(kù),但是又不想讓?webpack?打包,并且又不影響我們?cè)诔绦蛑幸?import、require?或者?window/global?全局等方式進(jìn)行使用,那就可以通過(guò)配置?externals。

          externals?配置選項(xiàng)提供了「從輸出的 bundle 中排除依賴」的方法。相反,所創(chuàng)建的?bundle?依賴于那些存在于用戶環(huán)境(consumer's environment)中的依賴。

          首先將?CDN?引入的依賴加入到?externals?中。

          然后借助?html-webpack-plugin?將?CDN?文件打入?html:

          這里有一點(diǎn)需要注意,在?html?中配置的?CDN?引入腳本一定要在?body?內(nèi)的最底部,因?yàn)椋?/p>

          • 如果放在?body?上面或?header?內(nèi),則加載會(huì)阻塞整個(gè)頁(yè)面渲染。
          • 如果放在?body?外,則會(huì)在業(yè)務(wù)代碼被加載之后加載,模塊中使用了該模塊將會(huì)報(bào)錯(cuò)。

          拆 vendor

          某些場(chǎng)景下, 一個(gè)第三方依賴可能拆成了多個(gè)子依賴,例如上面的?monaco,或者沒(méi)有提供可直接通過(guò)?CDN?引入的文件,我們就無(wú)法通過(guò)配置一個(gè)?CDN?文件來(lái)引入它了。

          這時(shí)我們需要自己去?webpack?設(shè)置一些規(guī)則,將我們想拆出來(lái)的依賴單獨(dú)打包一個(gè)?vendor。

          動(dòng)態(tài) import

          將?vendor?拆分后,依賴仍然會(huì)在首屏被加載,如果依賴不在首屏使用,仍然會(huì)造成網(wǎng)絡(luò)資源的浪費(fèi),并阻塞頁(yè)面渲染,對(duì)于沒(méi)必要在首屏進(jìn)行加載的依賴,我們可以采用動(dòng)態(tài)?import?的方式。

          例如上面這個(gè)?js-export-excel?這個(gè)依賴,自己本身有將近?500 kb,但是其只會(huì)在用戶點(diǎn)擊【導(dǎo)出】按鈕的時(shí)候使用,我們首先在?vendor?中將其拆出來(lái)。

          使用時(shí),將?import?的邏輯由首屏改到運(yùn)行時(shí)異步加載

          這樣的話,js-export-excel?這個(gè)依賴包只會(huì)在用戶點(diǎn)擊【導(dǎo)出】按鈕時(shí)引入,首屏不再引入。

          不是所有依賴都適合異步加載,如果你對(duì)使用該依賴有很高的性能要求,然后依賴本身也比較大,這種情況是不適合的,因?yàn)槟憧赡軙?huì)看到明顯的延遲。以上 export 其實(shí)是一個(gè)比較合適的場(chǎng)景,下載 excel 本身需要延遲時(shí)間,加上動(dòng)態(tài)加載依賴的時(shí)間是可接收的。

          React 懶加載

          類似的,對(duì)于某些第三方依賴組件,例如?monaco editor?,我們只有在很少的業(yè)務(wù)場(chǎng)景下才會(huì)用到,但是其本身一個(gè)包占用了?5MB?。。我們每次在打開(kāi)頁(yè)面時(shí)都要加載它,這太耗費(fèi)性能了。

          對(duì)于一個(gè)依賴包,我們可以通過(guò)動(dòng)態(tài)?import?的方式進(jìn)行懶加載,但是對(duì)于一個(gè)?React?組件,直接使用動(dòng)態(tài)?import?可能就不太合適了,組件渲染的運(yùn)行時(shí)都是可多次觸發(fā)了,不可能在每次組件渲染時(shí)都加載一次組件。

          React.lazy?函數(shù)能讓你像渲染常規(guī)組件一樣處理動(dòng)態(tài)引入組件。React.lazy?接受一個(gè)函數(shù),這個(gè)函數(shù)需要?jiǎng)討B(tài)調(diào)用?import()。它必須返回一個(gè)?Promise,該?Promise?需要?resolve?一個(gè)?default export?的?React?組件。

          const?MonacoEditor?=?React.lazy(()?=>?import('react-monaco-editor'));

          此代碼將會(huì)在組件首次渲染時(shí),自動(dòng)導(dǎo)入包含?MonacoEditor?組件的包。但是直接使用React.lazy引入的組件是無(wú)法直接使用的,因?yàn)?React?無(wú)法預(yù)測(cè)組件何時(shí)被加載,直接渲染會(huì)導(dǎo)致頁(yè)面崩潰。

          在?Suspense?組件中渲染?lazy?組件,可以使用在等待加載?lazy?組件時(shí)做優(yōu)雅降級(jí)(如?loading?)。fallback?屬性接受任何在組件加載過(guò)程中你想展示的?React?元素。你可以將?Suspense?組件置于懶加載組件之上的任何位置。你甚至可以用一個(gè)?Suspense?組件包裹多個(gè)懶加載組件。

          將所有?monaco editor?改為懶加載后,首屏已經(jīng)不會(huì)加載?monaco editor。

          路由懶加載

          上面?React?懶加載的方式,同樣適用于路由,對(duì)于每個(gè)路由都使用懶加載的方式引入,則每個(gè)模塊都會(huì)被單獨(dú)打?yàn)橐粋€(gè)?js,首屏只會(huì)加載當(dāng)前模塊引入的?js。

          不過(guò) 路由懶加載 也有一個(gè)很明顯的弊端,就是每個(gè)模塊的資源是只有加載這個(gè)模塊的時(shí)候才回去下載的,所以在切換模塊的時(shí)候可能會(huì)有一小段白屏或?loading?效果,這個(gè)要結(jié)合業(yè)務(wù)自身的情況綜合判斷要不要使用。

          語(yǔ)言包優(yōu)化

          在某些場(chǎng)景下,語(yǔ)言包會(huì)占用整個(gè)包體積的非常大一部分。實(shí)際上庫(kù)本身的邏輯不會(huì)很大,moment?就是一個(gè)很好例子。

          如果最開(kāi)始選擇日期庫(kù),那直接推薦使用?dayjs?了,如果你選擇了?moment?,一定要注意把不使用的語(yǔ)言包過(guò)濾掉,推薦使用?ContextReplacementPlugin,它會(huì)告訴?webpack?我們會(huì)使用到哪個(gè)本地文件:

          plugins:?[
          ????new?webpack.ContextReplacementPlugin(/moment[/\\]locale$/,?/zh-cn/),
          ??]

          優(yōu)化效果

          最終優(yōu)化后,會(huì)發(fā)現(xiàn)模塊已經(jīng)被我們拆的非常均勻,并且只會(huì)在對(duì)應(yīng)頁(yè)面渲染時(shí)加載對(duì)應(yīng)模塊,這對(duì)首屏渲染速度有顯著提升。

          未完待續(xù),期待一下后續(xù)文章吧 !


          瀏覽 66
          點(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>
                  亚州靠逼免费看 | 人人干人人摸人人爱 | 2000年国一级黄片 | 亚洲欧美高清国产精品 | 特级毛片www |