← 返回部落格

微信小程式主包超 2MB 了怎麼辦:一份按收益排序的瘦身清單

點「上傳」,開發者工具彈出一行紅字:主包大小超過 2MB 限制。版本發不出去,需求還在排隊。 這篇文章不講原理大全,只按「省得多、改得少」的順序,列出能把主包壓回 2MB 以內的辦法。 先搞清楚:2MB 到底卡的是什麼 微信對小程式代碼包有兩條硬上限: | 限制 | 上限 | | 主包(含…

分享

點「上傳」,開發者工具彈出一行紅字:主包大小超過 2MB 限制。版本發不出去,需求還在排隊。
這篇文章不講原理大全,只按「省得多、改得少」的順序,列出能把主包壓回 2MB 以內的辦法。


先搞清楚:2MB 到底卡的是什麼

微信對小程式代碼包有兩條硬上限:

限制 上限
主包(含 app.js、tabBar 頁面、公共資源等) 2MB
單個分包 2MB
整個小程式所有包加起來 20MB

注意這裡的「大小」是上傳後的代碼包體積,不只是 JS。專案目錄裡所有會被打包進去的檔案都算:.js、.wxml、.wxss、.、字體、音訊,以及——通常佔大頭的——圖片。

這是一條「壓不下去就發不出版本」的剛性限制,不是「優化一下更好」。所以第一步不是動手,而是先看清錢花在哪了。

第 0 步:看清主包裡是什麼在佔地方

微信開發者工具右上角「詳情 → 基本資訊」能看到本地代碼包的總大小;更細的在工具列的 「代碼依賴分析」,能按檔案列出體積,並標出哪些檔案沒有被任何頁面引用。

大多數專案看完這張表都會發現同一件事:圖片、字體這類靜態資源比業務代碼大得多。JS 寫幾萬行也就幾百 KB,一張沒處理過的 banner 圖就可能上百 KB,一個 images/ 目錄輕鬆吃掉主包一半。

下面按收益從大到小排。


辦法一:刪掉根本沒用的檔案

最省事,也最常被忽略。

  • 「代碼依賴分析」裡標記為未引用的檔案:歷史改版留下的舊圖示、廢棄頁面、測試圖,直接刪。
  • 不該進包的檔案:設計稿、README、.psd、原始素材、Mock 資料。能挪出專案目錄就挪出去;挪不了的,在 project.config. 裡用 packOptions.ignore 排除:

{
"packOptions": {
"ignore": [
{ "type": "folder", "value": "design" },
{ "type": "suffix", "value": ".psd" }
]
}
}

  • 元件庫全量引入:只用了三個元件卻把整個 UI 庫打進主包,是常見的「隱形胖子」。改成按需引入,只保留用到的元件目錄。

辦法二:分包——把不是首屏的頁面挪出主包

這是官方給的正解。主包只留啟動頁、tabBar 頁面和它們真正需要的公共代碼,其餘頁面按業務拆進分包:

{
"pages": ["pages/index/index", "pages/mine/mine"],
"subPackages": [
{ "root": "packageOrder", "pages": ["list/list", "detail/detail"] },
{ "root": "packageActivity", "pages": ["index/index"] }
],
"preloadRule": {
"pages/index/index": { "network": "all", "packages": ["packageOrder"] }
}
}

幾個要點:

  • 資源跟著頁面走:分包頁面自己用的圖片、元件,要放進分包目錄。放在主包的公共 images/ 裡,分包再怎麼拆,體積還是算在主包頭上。
  • preloadRule 分包預下載:進首頁時順手把下一步大概率會用到的分包拉下來,使用者點進去時基本感覺不到延遲。
  • 獨立分包("independent": true):適合活動頁、落地頁這類可以脫離主包單獨打開的頁面,啟動時不依賴主包。
  • 分包非同步化:跨分包引用元件或 JS 時,可以用佔位元件和 require.async,避免為了「共用」把代碼又提回主包。

分包的代價是要改目錄結構和跳轉路徑。老專案拆起來工作量不小,這也是為什麼值得先把下面這一步做了——很多時候,做完它主包就已經回到 2MB 以內了。

辦法三:把圖片壓小(改動最小、收益最直接)

圖片是主包裡最容易「白白胖著」的部分。設計師導出的 PNG 帶著多餘的資料區塊,JPG 用的是偏高的品質參數,這些位元組使用者看不出來,但每一個都計入 2MB。

哪些圖必須留在包裡

不是所有圖都能挪到 CDN:

  • tabBar 圖示:iconPath / selectedIconPath 只能是本地路徑,不支援網路圖片。
  • 啟動頁、首屏 Logo、兜底佔位圖:弱網或離線時也得能顯示。
  • 頻繁出現的小圖示:每次都走網路請求並不划算。

這些圖只能留在包裡,所以唯一的辦法就是讓它們變小。

順帶避開一個坑:wxss 裡的背景圖

在 .wxss 裡用 background-image 引用本地圖片,真機上是不生效的,常見的繞法是轉成 base64 內聯。但 base64 編碼會讓體積膨脹約三分之一,而且它藏在樣式檔案裡,依賴分析裡不太顯眼。能改成 <image> 元件或網路圖片的,就別內聯;非內聯不可的,先把原圖壓小再轉。

用 ImgZilla 原地壓縮整個資源目錄

做小程式最怕的,是壓完圖還要回頭改路徑——wxml 裡、wxss 裡、JS 配置裡、tabBar 配置裡,到處是 /images/xxx.png。很多壓縮工具會另存為 xxx-min.png,或者要求你匯出到別的資料夾,壓完還要手動替換、再核對一遍有沒有漏。

ImgZilla 是一款 macOS 圖片壓縮工具,它的做法是原地壓縮:

  • 檔名、路徑、格式都不變。icon-home.png 壓完還是 icon-home.png,代碼裡一行引用都不用改。
  • 整個目錄拖進去即可。它會遞迴掃描所有子目錄,並自動跳過隱藏檔案和 node_modules。把 images/、static/ 甚至整個專案目錄拖進去,壓完直接在開發者工具裡看包體積變化。
  • 原圖預設移入廢紙簍,覺得哪張不滿意,右鍵「放回原處」即可還原。專案在 Git 裡的話,還多一層保險。
  • 全程本地執行,不聯網上傳。公司專案的素材不會離開你的電腦,也沒有在線壓縮站那種單次張數、單張大小的限制。

畫質方面,不同格式的處理方式不一樣,這裡說清楚:

  • PNG:使用 oxipng 做無損壓縮,像素一點不變。小程式裡大量的圖示、切圖都是 PNG,這部分可以放心壓。
  • SVG:清理冗餘標記,也是無損的。
  • JPG / WebP / GIF 等:屬於有損重編碼,參數已經針對每種格式調校在視覺無損區間——肉眼難以察覺差異。不必憑信任接受,內建對比視窗(⌘D)可以左右分螢幕、放大到實際像素逐張對照。

另外兩點也值得知道:

  • 已經壓到頭的圖它不會硬壓:壓縮率不足 0.4% 的檔案會標為「已最小」,原樣保留,不會為了數字好看把圖搞糊。所以如果你的圖之前已經被認真優化過,這一步能省的可能不多——這很正常,也說明該轉向分包了。
  • 它不轉格式、不改解析度。PNG 壓完還是 PNG,尺寸不變。如果你想把圖換成 WebP,或者把 3 倍圖降成 2 倍圖,那是另一件事,需要另外處理。

能省多少,取決於圖原來是怎麼導出的,我們不給一個籠統的百分比。作為參考,我們做過兩次公開實測:一批網站入庫時已經壓過一遍的 JPG,再壓一次仍然省了 46.8%;一批相機直出的 JPG 省了 76.8%(詳見《ImgZilla 實測》系列)。小程式裡的圖往往是設計工具直接導出的,通常沒被認真壓過,所以值得先跑一遍看看。

ImgZilla 目前只有 macOS 版(macOS 12.3 及以上),Mac App Store 可下載,每天可免費壓縮 10 張。用 Windows 開發的同學,這一節的思路同樣適用,換一個同樣能「保留原檔名」的工具即可。

辦法四:把大圖挪到 CDN

壓小之後仍然很大的圖——比如活動 banner、詳情頁長圖、商品大圖——本來就不適合放在包裡。上傳到物件儲存或 CDN,代碼裡換成網路地址,主包立刻輕一截。

但這不是免費的:

  • 首次載入要走網路,弱網下會有空白期,最好配合佔位圖或骨架螢幕。
  • 要維護一套上傳、快取、更新的流程。
  • CDN 按流量計費。圖片每被載入一次都在花錢,流量費約等於「圖片體積 × 訪問次數」。所以挪到 CDN 之前,同樣值得先把圖壓小——壓一次,之後每一次訪問都在省流量。

辦法五:代碼層面的收尾

圖和結構處理完,剩下的零碎空間可以從代碼裡摳:

  • 開發者工具「詳情 → 本地設定」裡勾選上傳時壓縮腳本、樣式、WXML。
  • app. 開啟 "lazyCodeLoading": "requiredComponents"(按需注入)。它主要改善的是啟動速度而不是包體積,但既然在做效能優化,一起開上。
  • 檢查 miniprogram_npm:構建出的 npm 包是否有整包引入卻只用了一兩個函數的情況。
  • 大段寫死在 JS 裡的靜態資料(城市列表、配置表)考慮改為介面下發。

一張表總結

辦法 能省多少 要改多少 建議順序
刪除無用檔案 看專案歷史包袱 很少 1
原地壓縮圖片 圖片越多、導出越隨意,省得越多 幾乎為零,路徑不變 2
分包 可以很多 目錄和路由都要動 3
大圖挪 CDN 很多 要改引用、維護上傳流程 4
代碼壓縮與按需引入 較少 視情況 5

順序的邏輯很簡單:先做改動小的,再做改動大的。刪檔案和壓圖片幾乎不碰業務代碼,做完再看主包還差多少——如果已經回到 2MB 以內,今天的版本就能發;如果還不夠,再動分包和 CDN,心裡也有數了。

主包超限往往發生在上線前最緊張的時候。把圖片壓縮放進日常流程——每次加新圖之前先壓一遍——下次就不用在截止日前對著那行紅字發愁了。

想讓圖片更小更快?

下載 ImgZilla,在本機完成壓縮,圖片不會上傳雲端。