載入速度優化專項 > 體積優化分享
說到載入速度優化我們能想到什麼?網上能找到一些什麼內容?CDN? GZIP? 開啟快取?HTTP2? Tree-shaking?
這些內容對嗎?不全對!接下來我們針對性的分析一下。
網路、載入速度優化
為什麼我說 CDN 可以提速不全對?脫離劑量談毒性,都是耍流氓(這裡指脫離環境一把梭哈不現實)
CDN 是指是什麼?CDN 的全稱是 Content Delivery Network,即內容分發網路。CDN 是構建在現有網路基礎之上的智慧虛擬網路,依靠部署在各地的邊緣伺服器,通過中心平臺的負載均衡、內容分發、排程等功能模組,使使用者就近獲取所需內容,降低網路擁塞,提高使用者訪問響應速度和命中率。CDN 的關鍵技術主要有內容儲存和分發技術。
- 如果你的 CDN 本身節點比較少,並沒有覆蓋全面,那麼並不會提速。(比如說你買的這個 CDN 沒有海外節點,但是你想提升海外節點的訪問速度)
- 如果你的 CDN 是外網的,而你的專案是內網,那麼速度反而會更慢。(內網的距離比較近,所以速度快,內網頻寬足,所以速度快)
- 你的 CDN 是否可以承載你的請求量級?(比如說目前各大廠子都在自研自己的雲服務,阿里雲、騰訊雲)
- 開啟 GZIP 真的提速了嗎?是的真的提速了。但是一般伺服器早都開啟了。
是沒有損耗的嘛?有損耗每個檔案都會計算 gzip,且無快取。可以手動生成對應的 gz 檔案。 - 開啟快取?無腦快取?看來你是沒有被 ios 支配過。
一般來說快取也都是開啟狀態。我們目前一般的方案是 html 檔案無快取,js、css 強快取 hash 控制。 - HTTP2 真的是救星嘛?一般情況下是的,支援多路複用(突破六個連結限制,比如說有慢介面,大檔案),頭部壓縮。
但是在高延遲的情況下,HTTP2 反而會更慢 有線 vs 無線(WIFI、4G),服務商對於網路有影響嘛?只有外網專案受影響嘛?
- 外網。服務商對於網路是有影響的,比如我家就是移動,ping 部分 ip 丟包嚴重,光纖和 4G 都是如此。使用聯通 4G 就什麼問題都沒有。
內網。這裡推薦使用有線,比較穩定。這裡分為兩個場景:
- 公司,一般都是 AP 皮膚。但是有時候 AP 節點就是換不過來,偶爾網路波動。再看 P90 的資料的時候就特別難看。
- 家裡,一般都是單個路由器。你可以參考在訊號強時,和訊號弱時比對載入速度。
體積優化
Tree-shaking。好像有了 Tree-shaking 就完事大吉了。
- 但是在 webpack4 以後就是預設開啟的了。(
yarn serve
不優化,yarn build
優化,內部通過環境變數控制的) - Tree-shaking 只對 ES Module 起作用,對於 commonjs 無效,對於 umd 亦無效。
- 如果你的三方包不支援,那麼就不支援。所以這裡需要更新你包的版本,支援 按需 和 tree-shaking
- 但是在 webpack4 以後就是預設開啟的了。(
依賴共享。
- 比如說我們寫了一個 Request 庫,裡面用了 axios。然後我們還有個訊息中心的庫,裡面也用了 axios。這個時候輸出的包裡面會有兩個 axios。
這裡我們用的是(monorepo Lerna yarn)+ (config.externals)實現依賴共享,只載入一份 axios。 還有一個情況是我們使用了按需元件庫。但是主專案並沒有按需,而是全量匯入,導致載入了兩遍 element-ui。解決辦法就是主專案改成全量按需。
[ 'component', { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" }, 'element-ui', ],
- 比如說我們寫了一個 Request 庫,裡面用了 axios。然後我們還有個訊息中心的庫,裡面也用了 axios。這個時候輸出的包裡面會有兩個 axios。
分包。 對於不需要的資源延時載入、非同步載入。比如說有個流程中心,在你審批的時候同步載入了幾千個流程。但是你只需要使用其中一個。
vue 元件支援非同步載入。當元件真的渲染的時候再去載入。
Vue.component('async-example', function (resolve, reject) { setTimeout(function () { // 向 `resolve` 回撥傳遞元件定義 resolve({ template: '<div>I am async!</div>' }) }, 1000) }) Vue.component( 'async-webpack-example', // 這個動態匯入會返回一個 `Promise` 物件。 () => import('./my-async-component') )
對於大依賴( xlsx.js、echarts)或者其他不著急的資源也可以非同步載入
injectFn() { if (this.injected) {return;} this.injected = true; if (this.useBuiltIn && this.username && this.Prop) { import('../../../inject.js').then(({ inject }) => { inject(this.Prop!, this.username); }); } }
合包。也不能拆太細,平白提高了 QPS。
什麼叫壓縮?說白了就是相同和合並,比如說 '11111111111111111111' 改成 '1'.repeat(20)
內容壓縮很簡單,它就是移除多餘的空白字元,插入單個的重複字元指出一個字串中重複的字元,以及將小型的位串用頻繁使用的字元替代。這種型別的壓縮能夠將文字檔案的大小減少50%。壓縮由使用特定公式和演算法的程式來執行,它確定如何壓縮和解壓資料。
gzip 使用deflate演算法進行壓縮。gzip 對於要壓縮的檔案,首先使用LZ77演算法的一個變種進行壓縮,對得到的結果再使用Huffman編碼的方法
合理的 babel 處理。比如說你的內網專案,那麼可以只支援較高版本的瀏覽器,減少 babel 和 polyfill。
# 你知道這代表了什麼? > 1% last 2 versions # 表示將會支援 IE10 & IE11
邏輯優化
減少序列程式碼。
Promise.all
代替axios().then(() => axios())
axios1 = axios();axios2 = axios();await Promise.all(axios1,axios2);
代替await axios();await axios();
總結
優化之路,相輔相成。
- 優化網路,可以更快載入,也就可以更快執行。
- 優化併發不阻塞,並行載入,也可以更快執行。
- 優化體積,更小的體積,更高的複用,這樣就可以使用更少的頻寬,同樣可以更快的執行
- 使用快取,更低的 QPS,提前做 DNS 解析。也可以讓載入更快。
專案實戰
我提供了一些最簡案例在倉庫中:Demo 倉庫地址,你只需要看例子就可以直接看到問題(然後你可以去優化它)。
比如說:
分析手段
Chrome DevTools Lighthouse
這裡可以給我們的頁面打分,也會給出優化建議。如果能把這裡的點都優化了,那麼你的頁面載入就會起飛。
- 我們看看思否首頁,這分就挺高了。不過他們這個是靜態直出肯定會好很多,一般慢的都是後臺中臺 vue、react、單頁應用、巨石應用。
- 我們再看看掘金首頁,這個分就差點事了,可以看到有一些優化建議。看了好像他們首頁資料好像是骨架,然後後面回來的資料。
- 之前聽說 26 分,我也來看看。
Chrome DevTools Network
這裡主要是看網路阻塞情況,比如說 http1.1 的時候是不是那個請求阻塞了你。
yarn build --report
這個主要是分析包體積的,我使用的工具也主要是這個。
比如說這個案例,你可以看到有多個 axios,然後每一個 axios 那哪裡引入的,這個時候你可以考慮通過 peerDependencies 還是 externals 來處理一下這樣的資源。
Chrome DevTools Performance
這個主要是分析程式碼執行效率的。