本篇文章給大家分享一個小程序實戰,看看小程序中怎么進行圖片優化,希望對大家有所幫助!
前端的性能優化,圖片優化是必不可少的重要環節,大部分網站頁面的構成都少不了圖片的渲染。尤其在電商類項目,往往存在大量的圖片,如 banner 廣告圖,菜單導航圖,商品列表圖等。圖片加載數量多以及圖片體積過大往往會影響頁面加載速度,造成不良的用戶體驗。【相關學習推薦:小程序開發教程】
優化方案
基于上述問題的主要問題是圖片數量和圖片體積,所以應該怎么提高圖片加載速度,提升用戶體驗。其實圖片優化有非常多且優秀的方案,都可以從中借鑒,最后我們對圖片進行不同方向的整體優化。
使用合適的圖片格式
目前廣泛應用的 WEB 圖片格式有 JPEG/JPG、PNG、GIF、WebP、Base64、SVG 等,這些格式都有各自的特點,以下大概簡單總結如下:
使用合適的圖片格式通常可以帶來更小的圖片字節大小,通過合理壓縮率,可以減少圖片大小,且不影響圖片質量。
降低網絡傳輸
小程序使用騰訊云圖片服務器,提供很多圖片處理功能,比如圖片縮放、圖片降質,格式轉換,圖片裁剪、圖片圓角
等功能。這些功能可以通過在圖片URL
中添加規定參數就能實現,圖片服務器會根據參數設置提前將圖片處理完成并保存到CDN
服務器,這樣大大的減少圖片傳輸大小。
目前后臺接口下發返回的圖片 URL 都是未設置圖片參數預處理,比如一張 800x800
尺寸高清的商品圖,體積大概300k
左右,這樣就很容易導致圖片加載和渲染慢、用戶流量消耗大,嚴重影響了用戶體驗。所以我們結合騰訊云的圖片處理功能,網絡圖片加載前,先檢測是否是騰訊云域名的圖片URL
,如果域名
匹配,對圖片URL
進行預處理,預處理包括添加縮放參數
,添加降質參數
,添加WebP參數
的方式減少圖片網絡傳輸大小
我們先看一張通過圖片服務器是騰訊云圖片處理能力,通過設置圖片縮放/降質/WebP,一張尺寸800x800
,體積246KB
圖片,最后輸出生成25.6KB
,圖片體積足足減少了80%
,效果顯著。
圖片縮放
目前業務后臺都是原圖上傳,原始圖尺寸可能比客戶端實際顯示的尺寸要大,一方面導致圖片加載慢,另一方面導致用戶流量的浪費,其中如果是一張很大尺寸圖片加載也會影響渲染性能,會讓用戶感覺卡頓,影響用戶體驗。通過添加縮放參數的方式,指定圖片服務器下發更小和更匹配實際顯示size
的圖片尺寸。
圖片降質
圖片服務器支持圖片質量,取值范圍 0-100
,默認值為原圖質量,通過降低圖片質量可以減少圖片大小,但是質量降低太多也會影響圖片的顯示效果,網絡默認降圖片質量參數設置為85
,同時通過小程序提供的:wx.getNetworkType
、wx.onNetworkStatusChange
、offNetworkStatusChange
的接口監聽網絡狀態變化來獲取當前用戶的網絡類型networkType
,比如用戶當前使用的4G
網絡,則圖片質量會動態設置為80
,對于大部分業務情況,一方面可以大幅減少圖片下載大小和保證用戶使用體驗,另一方面節省用戶瀏覽 ,目前添加圖片降質參數至少可以減少30-40%
的圖片大小。
/** * 設置網絡情況 */ const setNetwork = (res: Record<string, any>) => { const { isConnected = true, networkType = 'wifi' } = res; this.globalData.isConnected = isConnected; this.globalData.networkType = networkType.toLowerCase(); this.events.emit(EventsEnum.UPDATE_NETWORK, networkType); }; wx.getNetworkType({ success: (res) => setNetwork(res) }); wx.offNetworkStatusChange((res) => setNetwork(res)); wx.onNetworkStatusChange((res) => setNetwork(res));
/** * 根據網絡環境設置不同質量圖片 */ const ImageQuality: Record<string, number> = { wifi: 85, '5g': 85, '4g': 80, '3g': 60, '2g': 60, }; /** * 獲取圖片質量 */ export const getImageQuality = () => ImageQuality[getApp().globalData.networkType ?? 'wifi'];
使用 WebP
前面簡單介紹不同的圖片格式都有各自的優缺點和使用場景,其中 WebP
圖片格式提供有損壓縮與無損壓縮的圖片格式。按照Google
官方的數據,與PNG
相比,WebP
無損圖像的字節數要少26%
,WebP
有損圖像比同類JPG
圖像字節數少25-34%
。現如今各大互聯網公司的產品都已經使用了,如淘寶、京東和美團等。
這里放一個 WebP 示例鏈接(GIF、PNG、JPG 轉 Webp),直觀感受 WebP
在圖片大小上的優勢。
在移動端中 WebP
的兼容性,大部分數用戶都已經支持了 Can I use… Support tables for HTML5, CSS3, etc,
針對png
/jpg
圖片格式,自動添加WebP
參數,轉成WebP
圖片格式。雖然WebP
相比png
/jpg
圖片解碼可能需要更長時間,但相對網絡傳輸速度提升還是很大。目前 ios 13
系統版本有不少用戶量的占比,小程序端獲取當前系統版本,降級處理不添加WebP
參數。
// 檢查是否支持webp格式 const checkSupportWebp = () => { const { system } = wx.getSystemInfoSync(); const [platform, version] = system.split(' '); if (platform.toLocaleUpperCase() === PlatformEnum.IOS) { return Number(version.split('.')[0]) > IOS_VERSION_13; } return true; // 默認支持webp格式 };
提示:由于目前圖片服務器并不支持、
SVG、GIF
轉WebP
,并沒有做處理
優化效果
測試我們小程序首頁列表接口加載圖片,來對比優化前后的效果
優化前 | 圖片數 | 不支持 WebP | 支持 WebP |
---|---|---|---|
2300K | 10 | 523K (降低 77%+) |
315K (降低 86%+) |
248M | 100 | 69M (降低 72%+) |
38M (降低 84%+) |
經過我們通過使用騰訊云圖片服務器的圖片處理功能,以及動態處理圖片格式的方式,減少圖片體積,提高圖片加載速度,帶來的收益比非常可觀的
圖片懶加載
懶加載是一種性能優化的方式,將頁面內未出現在可視區域內的圖片先不做加載, 等到滾動到可視區域后再去加載,對于頁面加載性能上會有很大的提升,也提高了用戶體驗。
實現原理
使用小程序提供Intersection Observer API
,監聽某些節點是否可以被用戶看見、有多大比例可以被用戶看見。這樣我們就能判斷圖片元素是否在可是范圍中,進行圖片加載。
我們基于小程序的Intersection Observer API
,封裝一個監聽模塊曝光 IntersectionObserver
函數工具,提供以下用法
import IntersectionObserver from 'utils/observer/observer'; const ob = new IntersectionObserver({ selector: '.goods-item', // 指定監聽的目標節點元素 observeAll: true, // 是否同時觀測多個目標節點 context: this, // 小程序 this 對象實例 delay: 200, // 調用 onFinal 方法的間隔時間,默認 200ms onEach: ({ dataset }) => { // 每一次觸發監聽調用時,觸發 onEach 方法,可以對數據進行一些過濾處理 const { key } = dataset || {}; return key; }, onFinal: (data) => { // 在觸發監聽調用一段時間 delay 后,會調用一次 onFinal 方法,可以進行埋點上報 if (!data) return; console.log('module view data', data); }, }); // 內置函數方法,如下: ob.connect(); // 開始監聽 ob.disconnect(); // 停止監聽 ob.reconnect(); // 重置監聽
然后在我們的FreeImage
圖片組件,添加可視區域加載圖片的功能,以下是部分代碼
import IntersectionObserver from 'utils/observer'; Component({ properties: { src: String, /** * 是否開啟可視區域加載圖片 */ observer: { type: Boolean, value: false, }, .... }, data: { isObserver: false, ... }, lifetimes: { attached() { // 開啟可視區域加載圖片 if (this.data.observer) { this.createObserver(); } }, }, methods: { ... /** * 監聽圖片是否進入可視區域 */ createObserver() { const ob = new IntersectionObserver({ selector: '.free-image', observeAll: true, context: this, onFinal: (data = []) => { data.forEach((item: any) => { this.setData({ isObserver: true, }); ob.disconnect(); // 取消監聽 }); }, }); ob.connect(); // 開始監聽 } } })
<free-image observer src="{{ src }}" />
優化效果
測試我們小程序首頁列表,使用圖片懶加載的效果
通過使用圖片懶加載的功能,減少圖片數量的加載,有效提高頁面加載性能。在上述我們已經對圖片體積進行優化過,所以在我們小程序中,只有在網絡情況較差的情況下,才會自動開啟圖片懶加載功能。
優化請求數
我們項目中有很多本地圖片資源,比如一些 icon 圖標、標簽類切圖、背景圖、圖片按鈕等。而小程序分包大小是有限制:整個小程序所有分包大小不超過 20M
,而單個分包/主包大小不能超過 2M
。所以為了減輕小程序體積,本地圖片資源需要進行調整,比如圖片壓縮、上傳到 CDN 服務器。這樣能減少了小程序主包大小,而大部分圖片都在騰訊云 CDN 服務器中,雖然可以加速資源的請求速度,當頁面打開需要同時下載大量的圖片的話,就會嚴重影響了用戶的使用體驗。
針對此問題,需要找到權衡點來實現來優化請求數,首先我們把圖片資源進行分類,以及使用場景,最后確定我們方案如下:
- 較大體積的圖片,選擇上傳到 CDN 服務器
- 單色圖標使用 iconfont 字體圖標,多彩圖標則使用
svg
格式 - 標簽類的圖片,則生成雪碧圖之后上傳到 CDN 服務器
- 圖片體積小于
10KB
,結合使用場景,則考慮base64
,比如一張圖片體積為3KB
的背景圖,由于小程序css background
不支持本地圖片引入,可以使用base64
方式實現
其他策略
大圖檢測
實現大圖檢測機制,及時發現圖片不符合規范的問題,當發現圖片尺寸太大,不符合商品圖尺寸標準時會進行上報。在小程序開發版/體驗版中,當我們設置開啟Debug
模式,圖片組件FreeImage
會自動檢測到大圖片時,顯示當前圖片尺寸、以及設置圖片高亮/翻轉
的方式提醒運營同學和設計同學進行處理
加載失敗處理
使用騰訊云圖片處理功能,URL
預處理轉換后得新 URL,可能會存在少量圖片不存在的異常場景導致加載失敗
。遇到圖片加載失敗時,我們還是需要重新加載原始圖片 URL, 之后會將錯誤圖片 URL 上報到監控平臺,方便之后調整 URL 預處理轉換規則,同時也發現一部分錯誤的圖片 URL 推動業務修改。
這是我們圖片組件FreeImage
處理圖片加載失敗,以下是部分代碼
onError(event: WechatMiniprogram.TouchEvent) { const { src, useCosImage } = this.data; this.setData({ loading: false, error: true, lazy: 'error', }); // 判斷是否騰訊云服務的圖片 if (useCosImage) { wx.nextTick(() => { // 重新加載原生圖片 this.setData({ formattedSrc: src, // src 是原圖地址 }); }); } // 上報圖片加載失敗 app.aegis.report(AegisEnum.IMAGE_LOAD_FAIL, { src, errMsg: event?.detail.errMsg, }); this.triggerEvent('error', event.detail); }
圖片請求數檢查
使用小程序開發者工具的體驗評分功能,體驗評分是一項給小程序的體驗好壞打分的功能,它會在小程序運行過程中實時檢查,分析出一些可能導致體驗不好的地方,并且定位出哪里有問題,以及給出一些優化建議。
通過體驗評分的結果,可以分析我們存在短時間內發起太多的圖片請求,以及存在圖片太大而有效顯示區域較小。所以根據分析的結果,開發需要合理控制數量,可考慮使用雪碧圖技術、拆分域名或在屏幕外的圖片使用懶加載等。
上傳壓縮
圖片在上傳前在保持可接受的清晰度范圍內同時減少文件大小,進行合理壓縮。現如今有很多不錯的圖片壓縮插件工具,就不在詳情介紹了。
推薦一個比較優秀的圖片壓縮網站:TinyPNG使用智能有損壓縮技術將您的 WebP, PNG and JPEG 圖片的文件大小降低