在開發微信小程式的過程中,隨著業務邏輯日漸龐大之後,突顯了一些問題。
首先我們發現在 dev mode 時,本地包大小已經達到了 4m ,這種情況下,已經無法在 dev mode 使用真機調試了。
其次此時,小程式 build 後面也有 1.8M 左右。而且後續還有相當多的業務需求需要開發,包大小一定會更大。
這時候就想要優化小程式包大小。下面分享一下我的定位過程和解決思路。儘管我們使用 uni-app 開發,但思路是通用的,希望能給大家一些幫助。
先分析套件大在哪裡了。
開啟本機程式碼目錄以查看檔案大小。可以發現 common/vendor.js 和 page,components 中 js 佔了大部分。
在 build 編譯模式下,程式碼壓縮已經啟用了,需要思考別的最佳化方式。這時候可以使用webpack-bundle-analyzer
外掛程式。它可以幫助分析 vendor.js 中都有哪些 js 模組,哪些模組比較大,以便我們進一步優化程式碼
透過這個插件,發現了下面兩個問題。
如果不是使用uni-app 開發可以跳過這段
透過程式碼分析發現有些模組應該被tree shaking 但卻被打包進來了。基本確定是 tree shaking 沒有生效。
也是 webpack4 babel7。在不使用 uni-app,直接使用 vue-cli create 專案的前提下,tree shaking 是沒有問題的。而使用 uni-app 去新建項目,tree shaking 卻無效。
排查 babel 設定時發現是由於 uni-app 在建立專案的時候,設定了 modules: 'commonjs'導致。修改後,demo 的 tree shaking ok。但回到專案裡一編譯,又出錯了。繼續定位發現是 uni-app 自訂元件模式編譯問題。目前uni-app已經修復了我提的bug,雖然還未正式發布。
當然你不使用uni-app 自訂元件模式編譯也可以解決,uni-app 也支援template模板模式
,但會有一些開發差異和效能差距,有興趣可以看下這篇文章
有些函式庫(例如lodash)本身並沒有使用import/export,所以webpack 並不能對它們tree shaking。這些庫我們可以分情況優化。
首先可以找下網路上是否有庫對應的 esm 版本可以替代,例如 lodash-es。
其次可以從程式碼分析中看出,如果庫的每個模組都在不同檔案中,入口檔案只是一個統一入口,那麼我們就可以透過修改寫法按需加載,如
import add from "lodash/add"; import Button from 'ant-design-vue/lib/button';复制代码
我們也可以使用babel-plugin-import
插件來針對那些庫統一實現按需加載,它的本質是在編譯時統一按配置修改加載路徑,不需要自己手動去修改程式碼。
最後如果都不行,那就要么接受,要么自己重寫為社區做貢獻~
為了免除無法tree shaking 的煩惱,我們在開發npm 模組的時候也需要遵循一定的規範,從而減少模組打包後的大小。
我們的模組需要同時支援 commonjs 和 es module。這樣才能既滿足 commonjs 開發的用戶,也支援 tree shaking。
如何實現呢?如果你的程式碼是typescript,以@sentry/browser 為例,可以在編譯時編譯cjs 和esm 兩種規範碼,如下
// package.json"build": "run-s build:dist build:esm build:bundle","build:bundle": "rollup --config","build:dist": "tsc -p tsconfig.build.json","build:esm": "tsc -p tsconfig.esm.json",复制代码
然後在package.json 中指定兩個入口以及無副作用標識
"main": "dist/index.js", "module": "esm/index.js", "sideEffects": false,复制代码
這樣當webpack 解析模組(解析規則),就會按需優先解析esm 目錄。並且當識別到無副作用時進行 tree shaking。
如果你的程式碼本身就是es6,你也可以這樣
"module": "src/index.js",复制代码
如果使用了第三方微信自訂元件,由於引用是在json 文件,所以webpack 在編譯時並不能透過entry 分析到相關文件,因此不會對其進行編譯、壓縮等。這時候就需要我們自己處理。而且由於 webpack 不處理,tree shaking 自然也無法支持,因此建議盡量避免這種方式引用元件。
小程式分包也是一種常規的最佳化方案。
通过分析后,可以将一些较大的页面划分为子包。如果有单页依赖第三方自定义组件,而且第三方组件还挺大,也可以考虑将该页面划分为子包。也因此尽量避免将第三方自定义组件放在 globalStyle,不然没法将它放到子包去。
小程序中的大图,尽量避免打包进来,应该放到 CDN 通过 url 加载。我们的做法是在开发时加载本地图片,在 CI/CD 环节自动化发布图片,并改写地址。
首先还是查看编译后的文件,发现common/vendor.js
巨大,足有 1.5M。其次pages
和components
也有 1.4M,而这其中占了 js 的大小又占了绝大部分。
为什么 js 文件这么大呢?主要是因为在 dev mode 默认并没有压缩,当然也没有 tree shaking。
我的选择是修改编译配置,在 dev mode 压缩 js 代码。本地代码减少到了 2M。预览大小则是减少到了 1.4M。参考配置如下:
// vue.config.js configureWebpack: () => { if (isDev && isMp) { return { optimization: { minimize: true, }, } } }复制代码
这看上去并不是个好方案,但确实简单有效。也考虑过分包,但分包并不能解决 common/vendor.js 巨大的问题,预览时包还是很大。如果有其它好的办法也欢迎留言~
更多相关免费学习推荐:微信小程序开发
以上是uni-app之小程式包大小優化的詳細內容。更多資訊請關注PHP中文網其他相關文章!