為SPA進行合理的代碼分割
SPA,即Single Page App。它將路由掌控完全交由前端來管理,與後端的通訊僅僅是數據交換,是近兩年比較流行的一種前端模型。
為什麼要把一個業務做成SPA呢?
其實SPA的應用場景是比較狹小的。它沒有了SEO,前端完全承擔路由,將網頁轉變為一種更加接近應用的模式。
我所處理的「個人中心」是一個與其它功能模塊相對獨立而自身所包含功能又比較具有耦合度的模塊。沒有SEO的需要,內部功能模塊都以前端渲染實現,比較適合SPA的應用場景。
整個功能採用react + react router,使用webpack進行代碼打包。
設計圖如下所示:
當然,SPA的詬病就是代碼體積過於臃腫。在完成整個模塊的功能開發後代碼的bundle size為142KB,如圖:
針對這個問題,webpack為我們提供了code splitting的功能,結合react router可以做到代碼的動態載入。當然,將所有的模塊代碼都切割下來動態載入並不是一個好的方法。要知道用戶進入個人中心都帶有明確的目的。個人中心只是一個「目錄」,用戶的目的在進入個人中心頁面後才會體現出來。
因此,我們可以根據用戶的行為統計來決定如何切割代碼。將用戶進入個人中心後訪問量較高的幾個模塊的代碼打包到一起,訪問量較小的功能模塊代碼進行切割動態載入,使得打包後的代碼最大限度的不包含冗餘邏輯,效率因而得到保證。
在這個場景中,用戶進入個人中心後「優惠券」、「連豆」和「餘額」的訪問量是最高的,彼此相差無幾。相比之下其他模塊的訪問統計量相形見絀,較上述模塊都不在一個數量級上。
因此,將「優惠券」、「連豆」和「餘額」的代碼與主文件打包到一起,代碼片段為:
//SPA的路由設置代碼片段 childRoutes: [..., { path: lyanbean, component: Bean //到一起的功能模塊 }, { path: balance, component: Balance }, { path: cafeclock, getComponent(location, cb) { //此為動態載入的功能模塊 require.ensure([], (require) => { cb(null, require(./Clock.jsx).default) }, MemberClock); } }, ...]
webpack 打包後:
此時bundle size降為38.9KB。
這還不行,由於動態請求載入的js文件不同於模版文件中引入的js文件,是沒有版本號的。如果就這樣發布到生產環境,若是文件修改後重新進行了發布,用戶會因為緩存而請求不到之後發布的代碼,造成線上錯誤。
這裡使用uuid為動態載入的js文件名添加一個根據時間生成的隨機數的拓展。於是乎,每次發布後動態載入的js文件名都會變化,瀏覽器便會去請求新的js文件。
代碼如下:
//在webpack中定義一個根據時間生成uuid的版本號//webpack.config.jsconst uuidV1 = require(uuid/v1);const version = uuidV1().replace(/.*-/,);//只取uuid的最後一段plugins: [..., new webpack.DefinePlugin({__VERSION__: JSON.stringify(version)}), ...];//路由設置代碼片段childRoutes: [..., { path: cafeclock, getComponent(location, cb) { //動態載入的功能模塊 require.ensure([], (require) => { cb(null, require(./Clock.jsx).default) }, MemberClock_ + __VERSION__);//在此處加入「版本」 } }, ...];
修改之後的bundle文件:
同時,由於每一次我們都改變了js文件名,導致新打包的js文件不會覆蓋舊的文件。這裡添加CleanWebpackPlugin,使webpack在打包時前清空dist文件夾,保證每次打包出代碼都是「最新鮮」的。
最後應當注意的幾點:
- 要好好利用webpack的CommonsChunkPlugin,重複打包chunk的bundle size分分鐘搞死你;
- 隨著迭代的進行,用戶的行為也在發生著變化,應該及時關注用戶行為統計數據來更新代碼的打包策略,保證高效率。
然而,還沒有結束。。
從個人中心訪問「咖啡庫」由之前的url跳轉變為前端控制路由,後端在這裡寫session的操作被強行略去了,導致上線後個別用戶反映訪問「咖啡庫」會報錯(還好咖啡庫的訪問量並不高),想死的心都有了。。
前端同胞們,一定要和同事隨時通氣,有個什麼改動趕緊昭告天下,不然就是在給自己埋雷啊~!
推薦閱讀:
※HTTP入門(三):使用Nodo.js腳本實現簡易伺服器
※個人前端小知識總結
※[2018IFE]第一天:為什麼有那麼多人要做前端?
※WEB前端開發人員須知的常見瀏覽器兼容問題及解決技巧
※ant-design-pro Authorized許可權組件設計
TAG:前端開發 | SPASinglePageApp |