官方已發(fā)布APP升級中心,支持原生APP整包升級和wgt資源包升級。詳見 https://uniapp.dcloud.io/uniCloud/upgrade-center
注:本文為前端代碼資源熱更新蹬挤。如果是整包升級,另見文檔 https://ask.dcloud.net.cn/article/34972
HBuilderX 1.6.5 起彤避,uni-app 支持生成 App 資源升級包荐类。
生成 App 資源升級包
修改版本號
首先肃叶,更新 manifest.json 中的版本號蹂随。
比如之前是 1.0.0,那么新版本應該是 1.0.1 或 1.1.0 這樣因惭。
發(fā)行
然后岳锁,在 HBuilderX 中生成升級包(wgt)。
菜單->發(fā)行->原生App-制作移動App資源升級包
生成結(jié)束會在控制臺告知升級包的輸出位置蹦魔。
安裝資源升級包
應用的升級需要服務端與客戶端配合完成激率,下面以本地測試過程中的操作舉例說明:
存放資源
將 %appid%.wgt
文件存放在服務器的 static 目錄下,即 http://www.example.com/static/**UNI**832D722.wgt
勿决。
服務端接口
約定檢測升級的接口乒躺,地址為:http://www.example.com/update/
傳入?yún)?shù)
參數(shù)名 | 類型 | 默認值 | 說明 |
---|---|---|---|
name | String | '' | 客戶端讀取到的應用名稱,定義這個參數(shù)可以方便多個應用復用接口低缩。 |
version | String | '' | 客戶端讀取到的版本號信息 |
返回參數(shù)
參數(shù)名 | 類型 | 默認值 | 說明 |
---|---|---|---|
update | Boolean | false | 是否有更新 |
wgtUrl | String | '' | wgt 包的下載地址嘉冒,用于 wgt 方式更新。 |
pkgUrl | String | '' | apk/ipa 包的下載地址或 AppStore 地址表制,用于整包升級的方式健爬。 |
代碼示例
下面是一個簡單的服務端判定的示例,僅做參考么介,實際開發(fā)中根據(jù)自身業(yè)務需求處理。
var express = require('express');
var router = express.Router();
var db = require('./db');
// TODO 查詢配置文件或者數(shù)據(jù)庫信息來確認是否有更新
function checkUpdate(params, callback) {
db.query('一段SQL', function(error, result) {
// 這里簡單判定下蜕衡,不相等就是有更新壤短。
var currentVersions = params.appVersion.split('.');
var resultVersions = result.appVersion.split('.');
if (currentVersions[0] < resultVersions[0]) {
// 說明有大版本更新
callback({
update: true,
wgtUrl: '',
pkgUrl: result.pkgUrl
})
} else {
// 其它情況均認為是小版本更新
callback({
update: true,
wgtUrl: result.wgtUrl,
pkgUrl: ''
})
}
});
}
router.get('/update/', function(req, res) {
var appName = req.query.name;
var appVersion = req.query.version;
checkUpdate({
appName: appName,
appVersion: appVersion
}, function(error, result) {
if (error) {
throw error;
}
res.json(result);
});
});
注意事項
- 以上約定,僅做參考慨仿。
- 服務端的具體判定邏輯久脯,請根據(jù)自身的業(yè)務邏輯靈活處理。
- 應用中的路徑盡量不要包含特殊符號
客戶端檢測升級
在 App.vue 的 onLaunch 中檢測升級镰吆,代碼如下:
// #ifdef APP-PLUS
plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
uni.request({
url: 'http://www.example.com/update/',
data: {
version: widgetInfo.version,
name: widgetInfo.name
},
success: (result) => {
var data = result.data;
if (data.update && data.wgtUrl) {
uni.downloadFile({
url: data.wgtUrl,
success: (downloadResult) => {
if (downloadResult.statusCode === 200) {
plus.runtime.install(downloadResult.tempFilePath, {
force: false
}, function() {
console.log('install success...');
plus.runtime.restart();
}, function(e) {
console.error('install fail...');
});
}
}
});
}
}
});
});
// #endif
不支持的情況
- SDK 部分有調(diào)整帘撰,比如新增了 Maps 模塊等,不可通過此方式升級万皿,必須通過整包的方式升級摧找。
- 原生插件的增改,同樣不能使用此方式牢硅。
對于老的非自定義組件編譯模式蹬耘,這種模式已經(jīng)被淘汰下線。但以防萬一也需要說明下减余,老的非自定義組件編譯模式综苔,如果之前工程沒有 nvue 文件,但更新中新增了 nvue 文件,不能使用此方式如筛。因為非自定義組件編譯模式如果沒有nvue文件是不會打包weex引擎進去的堡牡,原生引擎無法動態(tài)添加。自定義組件模式默認就含著weex引擎杨刨,不管工程下有沒有nvue文件悴侵。
注意事項
- 條件編譯,僅在 App 平臺執(zhí)行此升級邏輯拭嫁。
- appid 以及版本信息等可免,在 HBuilderX 真機運行開發(fā)期間,均為 HBuilder 這個應用的信息做粤,因此需要打包自定義基座或正式包測試升級功能浇借。
- plus.runtime.version 或者 uni.getSystemInfo() 讀取到的是 apk/ipa 包的版本號,而非 manifest.json 資源中的版本信息怕品,所以這里用 plus.runtime.getProperty() 來獲取相關(guān)信息妇垢。
- 安裝 wgt 資源包成功后,必須執(zhí)行 plus.runtime.restart()肉康,否則新的內(nèi)容并不會生效闯估。
- 如果App的原生引擎不升級,只升級wgt包時需要注意測試wgt資源和原生基座的兼容性吼和。平臺默認會對不匹配的版本進行提醒涨薪,如果自測沒問題,可以在manifest中配置忽略提示炫乓,詳見 https://ask.dcloud.net.cn/article/35627
- www.example.com 是一個僅用做示例說明的地址刚夺,實際應用中應該是真實的 IP 或有效域名,請勿直接復制粘貼使用末捣。
關(guān)于熱更新是否影響應用上架
應用市場為了防止開發(fā)者不經(jīng)市場審核許可侠姑,給用戶提供違法內(nèi)容,對熱更新大多持排斥態(tài)度箩做。
但實際上熱更新使用非常普遍莽红,不管是原生開發(fā)中還是跨平臺開發(fā)。
Apple曾經(jīng)禁止過jspatch邦邦,但沒有打擊其他的熱更新方案安吁,包括cordovar、react native圃酵、DCloud柳畔。封殺jspatch其實是因為jspatch有嚴重安全漏洞,可以被黑客利用郭赐,造成三方黑客可篡改其他App的數(shù)據(jù)薪韩。
使用熱更新需要注意:
- 上架審核期間不要彈出熱更新提示
- 熱更新內(nèi)容使用https下載确沸,避免被三方網(wǎng)絡劫持
- 不要更新違法內(nèi)容、不要通過熱更新破壞應用市場的利益俘陷,比如iOS的虛擬支付要老老實實給Apple分錢