SPA 網頁首屏渲染優化
最近在處理一個SPA網站首頁渲染優化的問題。前端主要使用的是React開發,UI設計使用的是antDesign的庫。最終打包出來的文件為1.2M,在沒有使用其他技術優化之前,首屏的用戶體驗是非常不理想的,所以第一步是縮小文件體積。
一、 縮小js文件體積
項目開發的時候依賴一些第三方的庫,例如React,Lodash,moment等,他們都有提供免費的CDN庫。前端構建使用了webpack,打包的時候會將這些依賴的庫一起打包,所以第一步是將這些庫分離出來。webpack提供了這樣的功能,配置如下:
經過以上處理之後,打包結果為900kb左右, 使用GZIP壓縮之後,(level 4) 200kb左右。勉強達到標準。接下來就是spa頁面載入順序的處理了。
二、載入順序
首屏渲染速度除了受js文件大小的影響,還有HTML的解析時機。為了提早載入完document,最好將沒有用到的其他文件的下載往後推或者非同步下載(不要讓他阻塞document的載入)。這裡給這些js文件添加了 defer屬性。
我們首次打開頁面是一個登錄的界面:
那麼問題來了, 已經登錄的用戶下次打開頁面的時候,是不是就有白屏了?那麼繼續往下看。
三、伺服器端協議304與max-age
我們給我們的CDN伺服器配置了返回max-age的頭部信息。該屬性會告知瀏覽器在某段時間如果要訪問這個文件的話,可以直接從瀏覽器的緩存里取, 而如果沒有這個設置的話, 瀏覽器可能會請求一次CDN伺服器, 伺服器返回304,告知瀏覽器此文件並沒有修改,可以使用緩存的文件。 這個技術可以減少白屏時間。另外,增加一個loading 可以優化用戶體驗。
四、補充
為了安全,我們使用了httpOnly,這樣前端無法讀取cookie信息, 完全靠伺服器判斷。那麼我們怎麼知道第一次是渲染登錄界面還是進入主界面呢?這裡使用了類似jsonP的實現原理。在網關里做了攔截, 當訪問主界面時,如果發現用戶沒有登錄, 就在返回的結果前面插入一個script標籤,調用一段js代碼,使主界面隱藏並顯示登錄頁面。 jsonP實現跨域訪問的方法也是類似這樣的。
五、雜項
1、webpack插件webpack-bundle-analyzer, 可以顯示所打包的js文件由哪些部分組成
2、webpack插件script-ext-html-webpack-plugin, 可以給script標籤加上defer等屬性
3、lodash等比較大的js庫,如果使用的工具比較少的話,可以自己實現。
推薦閱讀:
※react的虛擬dom是以什麼形式存儲在哪裡的?
※Redux 非同步流最佳實踐
※關於在react中request到底是應該寫在哪裡?
※react源碼解析-4ReactElement與ReactElementValidator