微信小程序自推出以來,逐漸發展,目前正受到越來越多的青睞。其中很重要的一點得益于小程序的輕量級特性,每個小程序最多不超過2MB,招之即來揮之即去,相比于幾十上百兆的APP,用戶進入小程序,或者說,小程序獲取新用戶,的成本大大降低。
但與之相應的,是開發資源的限制。由于輕量級特性,小程序的代碼包體積、可用內存空間、可用存儲空間等均受限制。如何在有效支持業務邏輯的同時,盡量減少資源占用,在小程序開發環境中顯得尤為重要。代碼包體積是其中的一個重要方面,本文將就此進行分析與探討。
本文內容基于小程序“轉轉官方”經驗總結,部分內容與開發環境密切相關,因而此處進行簡要介紹。
“轉轉官方”是一個重量型小程序,移植了轉轉APP的絕大部分功能,從商品發布、瀏覽、搜索、下單、跟進等交易邏輯,到留言、私信、紅包、推薦、運營活動、個人中心、圈子社區等擴展能力均已支持,目前代碼包體積約為1.5MB。
“轉轉官方”采用wepy框架進行開發。該框架類似vue,支持組件化開發、ES678語法、less語法等,源碼經編譯、壓縮后才生成實際代碼。目前線上使用版本為1.5.8??蚣芙榻B: 像VUE一樣寫微信小程序-深入研究wepy框架
https://mp.weixin.qq.com/s/R2IlOzlA9Mb_XevDXAITdw
控制代碼包大小主要意義:
避開大小限制
小程序代碼包體積存在大小限制,一開始為1MB,后來改為2MB,代碼包體積超過此上限時將無法進行預覽/上傳/發布。
降低用戶獲取成本
減小代碼包體積,可以降低小程序下載時長&首次加載時長,降低新用戶流失率;同時減少下載流量和本地空間占用,提升用戶體驗。
開發維護
保持代碼包干凈整潔,一定程度上有利于代碼的長期維護。
控制代碼包大小主要策略:
搬
能搬的盡量搬。圖片、音頻、數據、甚至頁面,很多都可以搬至服務端,需要時再通過網絡載入。將非核心非必要的內容移出代碼包可以大幅度釋放代碼包空間。
刪
搬不了的盡量刪。已下線、已廢棄、無關、冗余等不需要/不再需要的內容應及時清理,避免持續占用代碼包空間。
壓縮
刪不了的盡量壓縮。圖片、js、wxss、wxml等均存在壓縮空間。很多時候,適當程度的壓縮,能在幾乎不影響功能體驗的同時,有效減少空間占用。
合并
壓縮不了的盡量合并。功能類似的資源可以歸一化,在需求/設計/實現層面減少資源的重復消耗。
其它
其它壓縮策略。
資源外置
非核心不緊急的資源文件,特別是圖片、音頻、視頻等體積較大的媒體文件,可以移至cdn服務器,需要時再通過網絡載入。
這常常是小程序前期膨脹的主要原因和最有效壓縮方式,比如我們的“手機30秒快賣”小程序,將圖片資源移出代碼包后,體積從約2MB直接降到了195KB。
數據外置
非核心不緊急的數據內容,包括城市地區等大段數據,標簽映射等大段配置,使用條約、服務說明等大段文案,可以移至數據服務器或本地storage,需要時再予以載入。
有些內容體積會比想象中大,比如我們的“轉轉使用條約”,移出代碼包后,釋放了約40KB空間。
功能外置
非核心自定義屬性不強烈、不緊急可以異步處理的功能,可以移至外部實現。如選擇地址、查看大圖等功能可以交由小程序原生接口實現,編碼解碼等功能可以交由服務端實現。
頁面外置
非核心不緊急的頁面,可以考慮移至服務端。從基礎庫1.6.4起,小程序開始支持內嵌網頁,非核心頁面可以考慮適當往web服務器遷移。
[wepy] 清理殘留文件
目前wepy編譯時不會自動清理上次編譯殘留的文件,導致歷史資源持續積累。
e.g. 7個頁面,npm run build, 172KB -> 刪掉6個頁面, npm run build, 依然 172KB。
因而應當修改build腳本,在編譯前增加清空dist步驟,或在編譯前手動刪除dist目錄。
清理無關文件
應避免代碼包中混入運行無關的文件,如readme、doc、demo、測試用例等。
可以通過設計合理的文件結構避免無關文件混入代碼目錄,wepy框架下也可以配置.wepyignore自動按類型/目錄過濾文件(項目目錄-新建.wepyignore文件-編輯-語法參考.gitignore)。
清理已下線/已棄用文件
已下線/已棄用的文件資源應及時清理,包括npm包、組件、頁面、媒體資源等。若后續需要重新上線/重新使用,可以通過git等版本控制工具找回。這部分資源不需要持續占用代碼包空間。
IDE的查看引用、范圍搜索等功能可以為清理過程提供一定的便利。
資源都移至cdn之后,這部分空間可能就是最可觀的了。“轉轉官方”小程序代碼包體積從2MB出頭降到了約1.5MB,主要就是由清理殘留文件、清理已下線/已棄用文件釋放的。
[wepy]清理多余wxml文件
目前wepy編譯時會將組件的dom部分拼合到頁面中,而不生成單獨的wxml文件。
但若組件所在文件路徑不含'/components/',則編譯環節wepy不會識別其為組件,會按'Other'類型處理,從而生成多余的wxml文件和json文件。
確保組件都放在components目錄下可以避免這部分多余空間消耗。
清理大文件
大文件常常存在較大的壓縮空間,值得重點排查和處理。
查找大文件tip:資源管理器 - 代碼目錄 - 搜索'*' - 右鍵 - 排序方式:大小,即可將代碼包內所有文件按大小排序展示
資源壓縮
大部分資源都可以進行適當壓縮,常??梢栽诒WC功能體驗的同時,有效地減少空間占用。參考工具:
js壓縮: 配置wepy-plugin-uglifyjs插件
json、wxml壓縮: 配置wepy-plugin-filemin插件
less壓縮: 配置wepy-compiler-less插件
圖片壓縮: 配置wepy-plugin-imagemin插件、TinyPNG
其中TinyPNG工具壓縮效果非??捎^,400KB的圖片壓到40KB不足為奇,并且畫質感知上幾乎無損。
資源合并
功能類似的資源可以歸一化,減少重復空間占用。
需求層面,比如不同運營活動可以采用統一模板,而不每次增加單獨頁面等;
樣式層面,比如可以統一彈窗規范,而不引入五花八門的零碎彈窗組件等;
設計開發層面,比如可以盡量解耦合抽取公共組件,減少重復造輪子等。
[wepy]清理組件DOM冗余拷貝?
觀察發現,目前wepy的組件實現中,編譯后頁面對組件js、wxss的引用是通過require、@import的形式實現的,而對組件dom的引用則是直接拼合到頁面wxml文件中。
這導致,當一個組件被多處引用時,其dom內容會有多份冗余拷貝。
e.g. 10個頁面引用了組件A => 編譯出的10個頁面wxml各含一份A的dom,A的template部分在代碼包中被原模原樣重復了10次
如果修改wepy編譯過程,將組件dom引用過程改為使用include或原生組件(基礎庫1.6.3開始支持)實現,應當可以節省這部分冗余開銷。
[wepy]壓縮自動生成的代碼量?
觀察發現,代碼包中除了手動維護的業務代碼之外,也有不少框架/插件自動生成的代碼。如源碼編譯過程中生成的輔助代碼、兼容ES678語法引入的墊片代碼、兼容各運行環境引入的css前綴代碼等。
通過對框架和插件進行修改/配置,應當可以一定程度減少這部分空間開銷。比如對babel插件進行規則配置、對auto-prefix插件進行最低版本配置,應當可以犧牲部分不必要的兼容性,從而減少墊片代碼的生成量等。諸如此類。
只是筆者未及嘗試,尚不確定這部分開銷是否有可觀的壓縮空間。
壓縮額外文件空間?
觀察發現,代碼包大小總是比代碼內容總大小大得多(上傳后詳情面板中“上次上傳”、“上次預覽”總是比“本地代碼”大得多)。
這部分額外大小應當也是存在壓縮空間的。比如將細碎圖片、細碎js文件、細碎less文件拼合成雪碧圖、js庫、less庫等較大文件,應當可以減少由于文件最小存儲單元引入的額外空間開銷等。諸如此類。
只是筆者未及嘗試,尚不確定這部分開銷是否有可觀的壓縮空間。
由于輕量級特性,小程序開發環境中,對代碼包體積的控制是十分必要且十分有意義的。
本文介紹了代碼包體積壓縮的一些策略、方案和幾個未及實踐的思路。總的來說,就是盡量精簡,盡量只將最核心最必要最緊急的內容放在代碼包內。其它資源過多占用代碼包空間時,則考慮通過搬移/刪除/壓縮/合并等方式予以釋放。
拙劣之處歡迎不吝賜教。