SPA 網頁首屏渲染優化

最近在處理一個SPA網站首頁渲染優化的問題。前端主要使用的是React開發,UI設計使用的是antDesign的庫。最終打包出來的文件為1.2M,在沒有使用其他技術優化之前,首屏的用戶體驗是非常不理想的,所以第一步是縮小文件體積。

一、 縮小js文件體積

項目開發的時候依賴一些第三方的庫,例如React,Lodash,moment等,他們都有提供免費的CDN庫。前端構建使用了webpack,打包的時候會將這些依賴的庫一起打包,所以第一步是將這些庫分離出來。webpack提供了這樣的功能,配置如下:

然後為了保證能夠正常運行, 需要在頁面中引入這些第三方的庫:

之後發現,mxa體積也挺大的,所以凡是引用mxa的地方都改為引用到具體的組件:

後來,有大神指點,只要修改babelrc文件里的配置就能達到上面類似的效果:

經過以上處理之後,打包結果為900kb左右, 使用GZIP壓縮之後,(level 4) 200kb左右。勉強達到標準。接下來就是spa頁面載入順序的處理了。

二、載入順序

首屏渲染速度除了受js文件大小的影響,還有HTML的解析時機。為了提早載入完document,最好將沒有用到的其他文件的下載往後推或者非同步下載(不要讓他阻塞document的載入)。這裡給這些js文件添加了 defer屬性。

我們首次打開頁面是一個登錄的界面:

這個界面並沒有用到打包的js文件,所以我們非同步下載和推遲載入這個文件。以及那些他依賴的第三方庫。 登錄所需的js文件全都用原生實現,並且它的樣式也直接寫在主HTML頁面里。這樣,用戶會在第一時間看到這個頁面,同時,瀏覽器會默默的下載那些比較大的js文件而不影響用戶的操作。當用戶登錄成功之後, 判斷js文件載入完畢,則移除登錄界面,直接顯示主界面。這樣一來,就不會有白屏的效果了。

那麼問題來了, 已經登錄的用戶下次打開頁面的時候,是不是就有白屏了?那麼繼續往下看。

三、伺服器端協議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

TAG:webpack | React | JSONP |