跨平台应用开发进阶(三): uni-app 实现资源在线升级 热更新_uniapp热更新原理(1)

最后

本人分享一下这次字节跳动、美团、头条等大厂的面试真题涉及到的知识点,以及我个人的学习方法、学习路线等,当然也整理了一些学习文档资料出来是给大家的。知识点涉及比较全面,包括但不限于前端基础,HTML,CSS,JavaScript,Vue,ES6,HTTP,浏览器,算法等等

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

前端视频资料:

var appVersion = req.query.version;  
checkUpdate({  
    appName: appName,  
    appVersion: appVersion  
}, function(error, result) {  
    if (error) {  
        throw error;  
    }  
    res.json(result);  
});  

});


注意事项⚠️:


* 服务端的具体判定逻辑,请根据自身的业务逻辑灵活处理。
* 应用中的路径尽量不要包含特殊符号。


客户端检测升级  
 在 `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` 部分有调整,比如新增了 `Maps` 模块等,不可通过此方式升级,必须通过整包的方式升级。
* 原生插件的增改,同样不能使用此方式。
* 对于老的非自定义组件编译模式,这种模式已经被淘汰下线。但以防万一也需要说明下,老的非自定义组件编译模式,如果之前工程没有 `nvue` 文件,但更新中新增了 `nvue` 文件,不能使用此方式。因为非自定义组件编译模式如果没有`nvue`文件是不会打包`weex`引擎进去的,原生引擎无法动态添加。自定义组件模式默认就含着`weex`引擎,不管工程下有没有`nvue`文件。


**注意事项⚠️**


* 条件编译,仅在 `App` 平台执行此升级逻辑。
* `appid` 以及版本信息等,在 `HBuilderX` 真机运行开发期间,均为 `HBuilder` 应用的信息,因此需要打包自定义基座或正式包测试升级功能。
* `plus.runtime.version` 或者 `uni.getSystemInfo()` 读取到的是 `apk/ipa` 包的版本号,而非 `manifest.json` 资源中的版本信息,所以这里用 `plus.runtime.getProperty()` 来获取相关信息。
* ⚠️安装 `wgt` 资源包成功后,必须执行 `plus.runtime.restart()`,否则新的内容并不会生效。
* 如果`App`的原生引擎不升级,只升级`wgt`包时,需要注意测试`wgt`资源和原生基座的兼容性⚠️。平台默认会对不匹配的版本进行提醒,如果自测没问题,可以在`manifest.json`中配置忽略提示。
* ⚠️应用市场为了防止开发者不经市场审核许可,给用户提供违法内容,对热更新大多持排斥态度。


但实际上热更新使用非常普遍,不管是原生开发中还是跨平台开发。


`Apple`曾经禁止过`jspatch`,但没有打击其他的热更新方案,包括`cordovar、react native、DCloud`。封杀`jspatch`其实是因为`jspatch`有严重安全漏洞,可以被黑客利用,造成黑客可篡改其他`App`的数据。


使用热更新需要注意⚠️:


* 🙅‍♂️上架审核期间不要弹出热更新提示;
* ⚠️热更新内容使用`https`下载,避免被三方网络劫持;
* 🙅不要更新违法内容、不要通过热更新破坏应用市场的利益,比如`iOS`的虚拟支付要老老实实给`Apple`分钱。


##### 2.3.2 小结


用户对于热更新及整包更新的感知几乎是无差别的,同样需要主动触发用户下载安装,只不过包的大小不一致。


### 三、整包升级


**接口约定**  
 如下数据接口约定仅为示例,开发者可以自定义接口参数。


请求地址:`https://www.example.com/update`


请求方法:`GET`


请求数据:



{
“appid”: plus.runtime.appid,
“platform”: platformFlag,
“version”: plus.runtime.version
}


其中,platformFlag为手机系统标识,可通过如下方法获取:



async initSystemInfo() {
uni.getSystemInfo({
success(e) {
console.log('The system info e is: ', e)
// #ifndef MP
getApp().globalData.deviceInfo = e
Vue.prototype.StatusBar = e.statusBarHeight;
if (e.platform === ‘android’) {
getApp().globalData.deviceInfo.platformFlag = ‘0’ // Android系统标识
Vue.prototype.CustomBar = e.statusBarHeight + 50;
} else {
getApp().globalData.deviceInfo.platformFlag = ‘1’ // IOS系统标识
Vue.prototype.CustomBar = e.statusBarHeight + 43;
}
// #endif
// #ifdef MP-WEIXIN
Vue.prototype.StatusBar = e.statusBarHeight;
const custom = wx.getMenuButtonBoundingClientRect();
Vue.prototype.Custom = custom;
Vue.prototype.CustomBar = custom.top - e.statusBarHeight;
// #endif
// #ifdef MP-ALIPAY
Vue.prototype.StatusBar = e.statusBarHeight;
Vue.prototype.CustomBar = e.statusBarHeight + e.titleBarHeight;
// #endif
}
});
},


响应数据:



{
“status”:1,//升级标志,1:需要升级;0:无需升级 在这里插入代码片
“note”: “修复bug1;\n修复bug2;”,//release notes
“url”: “http://www.example.com/uniapp.apk” //更新包下载地址
}


#### 3.1 客户端实现


`App`启动时,向服务端上报当前版本号,服务端判断是否提示升级。


在`App.vue`的`onLaunch`中,发起升级检测请求,如下:



onLaunch: function () {
//#ifdef APP-PLUS
var server = “https://www.example.com/update”; //检查更新地址
var req = { //升级检测数据
“appid”: plus.runtime.appid,
“version”: plus.runtime.version
};
uni.request({
url: server,
data: req,
success: (res) => {
if (res.statusCode == 200 && res.data.status === 1) {
uni.showModal({ //提醒用户更新
title: “更新提示”,
content: res.data.note,
success: (res) => {
if (res.confirm) {
switch (uni.getSystemInfoSync().platform) {
case ‘android’:
// 开始下载任务
const downloadTask = uni.downloadFile({
url: data.url,
// 接口调用成功
success: (downloadResult) => {
uni.hideLoading();
console.log(‘----------------downloadResult----------------’, downloadResult)
if (downloadResult.statusCode === 200) {
// uni.showLoading({
// mask:true,
// title: ‘安装中…’
// });
plus.runtime.install(downloadResult.tempFilePath, {
force: false
}, function() {
// uni.hideLoading();
console.log(‘install success…’);
plus.runtime.restart();
}, function(e) {
console.error(‘install fail…’);
});
}
},
// 接口调用失败
fail: (err) => {
console.log(‘----------------Fail----------------’, err);
uni.showToast({
icon:‘none’,
mask:true,
title: ‘安装失败,请重新下载’,
});
},
// 接口调用结束
complete: () => {
console.log(‘----------------Complete----------------:’, downloadTask)
downloadTask.offProgressUpdate(); //取消监听加载进度
}
});

								//监听下载进度
								downloadTask.onProgressUpdate(res => {
									// _self.percent = res.progress;
									state.percent = res.progress;
									// console.log('下载进度百分比:' + res.progress); // 下载进度百分比
									// console.log('已经下载的数据长度:' + res.totalBytesWritten); // 已经下载的数据长度,单位 Bytes
									// console.log('预期需要下载的数据总长度:' + res.totalBytesExpectedToWrite); // 预期需要下载的数据总长度,单位 Bytes
								});
								break;
							case 'ios':
								// 跳转至Apple Store
								let appleId=1549638327 //app的appleId
								plus.runtime.launchApplication({
								  action: `itms-apps://itunes.apple.com/cn/app/id${appleId}?mt=8`
								}, function(e) {
								  console.log('Open system default browser failed: ' + e.message);
								});
								break;
						}
                    }  
                }  
            })  
        }  
    }  
})  
//#endif 

}


注意⚠️:`App`的升级检测代码必须使用**条件编译**,否则在微信环境由于不存在`plus`相关`API`,将会报错。


#### 3.2 数据表实现


需维护一张数据表,用于维护`APP`版本信息,主要字段信息如下:




| 字段名称 | 数据类型 | 数据说明 |
| --- | --- | --- |
| `AppID` | `varchar` | mobile AppID |
| `version` | `varchar` | 应用市场版本号 |
| `notes` | `varchar` | 版本更新说明 |
| `url` | `varchar` | 应用市场下载URL。 注意:⚠️根据谷歌、App Store应用市场审核规范,应用升级只能通过提交应用市场更新,不能通过下载`apk`、`IPA`安装方式更新应用。 |


#### 3.3 服务端实现


根据客户端接收的版本号,比对服务端最新版本号,决定是否需要升级,若需升级则返回升级信息(`rlease notes`、`更新包地址`等)


开发者可以根据服务端开发语言,自己实现升级检测逻辑,如下是一个`php`示例代码:



header(“Content-type:text/json”);
$appid = $_GET[“appid”];
$version = $_GET[“version”]; //客户端版本号
KaTeX parse error: Expected 'EOF', got '&' at position 23: …rray("status" =&̲gt; 0); //默认返回值…appid) && isset(KaTeX parse error: Expected '}', got 'EOF' at end of input: …)) { if (appid === “__UNI__123456”) { //校验appid
if ($version !== “1.0.1”) { //这里是示例代码,真实业务上,最新版本号及relase notes可以存储在数据库或文件中
$rsp[“status”] = 1;
$rsp[“note”] = “修复bug1;\n修复bug2;”; //release notes
KaTeX parse error: Expected 'EOF', got '}' at position 73: …下载地址 }̲ } } …rsp);
exit;


注意事项⚠️:


* `plus.runtime.appid`,`plus.runtime.version`, `plus.runtime.openURL()` 在真机环境下才有效。
* 版本检测需要打包`app`,真机运行基座无法测试。因为真机运行的`plus.runtime.version`是固定值。
* 根据谷歌应用市场的审核规范,应用升级只能通过提交应用市场更新,不能通过下载`apk`安装方式更新应用。`apk`安装失败可能是因为缺少`android.permission.INSTALL_PACKAGES`、`android.permission.REQUEST_INSTALL_PACKAGES`权限导致,注意:添加上面两个权限无法通过谷歌审核。


#### 3.4 发版配置


APP发版时,应注意维护`manifest.json`中`versionName`、`versionCode`字段,以免影响版本升级。


![在这里插入图片描述](https://img-blog.csdnimg.cn/942cd3d907444bee83ab2d91d2567870.png)


#### 3.5 注意事项


* `plus.runtime.version` 为属性方式同步获取,拿到的是编译阶段`manifest.json`中设置的`apk/ipa`版本号,整包更新后的版本号,在`manifest.json`中配置时需要提交到App云端打包后才能生效。
* `plus.runtime.getProperty` 为异步方法调用获取,拿到的当前应用的版本号,如果热更新过就是热更新后的版本号。



plus.runtime.getProperty(plus.runtime.appid, function(widgetInfo) {
console.log(widgetInfo.version);
})


### 四、Uni-app 版本升级中心


`uni-app`提供了一整套版本维护框架,包含升级中心`uni-upgrade-center - Admin`、前台检测更新`uni-upgrade-center-app`。


#### 4.1 升级中心 uni-upgrade-center - Admin


`uni-app`提供了版本维护后台应用升级中心`uni-upgrade-center - Admin`,升级中心是一款`uni-admin`插件,负责`App`版本更新业务。包含后台管理界面、更新检查逻辑,`App`内只要调用弹出提示即可。


![在这里插入图片描述](https://img-blog.csdnimg.cn/4df0e1c9ac5243299154a0655525f4e4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATm8gU2lsdmVyIEJ1bGxldA==,size_20,color_FFFFFF,t_70,g_se,x_16)


在上传安装包界面填写此次发版信息,其中包地址可以选择手动上传一个文件到云存储,会自动将地址填入该项。


也可以手动填写一个地址(例如:<https://appgallery.huawei.com/app/C10764638>),就可以不用再上传文件。


⚠️如果是发布苹果版本,包地址则为应用在`AppStore`的链接。


![在这里插入图片描述](https://img-blog.csdnimg.cn/8188d937c4f044219b07045c638ac4d4.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBATm8gU2lsdmVyIEJ1bGxldA==,size_12,color_FFFFFF,t_70,g_se,x_16)


升级中心有以下功能点:



> 
> * 云储存安装包`CDN`加速,使安装包下载的更快、更稳定
> * 应用管理,对`App`的信息记录和应用版本管理。
> * 版本管理,可以发布新版,也可方便直观的对当前`App`历史版本以及线上发行版本进行查看、编辑和删除操作。
> * 版本发布信息管理,包括更新**标题**,**内容**,**版本号**,静默更新,强制更新,灵活上线发行的设置和修改。
> * 原生`App`安装包,发布`Apk`更新,用于`App`的整包更新,可设置是否强制更新。
> * `wgt`资源包,发布`wgt`更新,用于`App`的热更新,可设置是否强制更新,静默更新。
> * App管理列表及App版本记录列表搜索。
> * 只需导入插件,初始化数据库即可拥有上述功能。
> * 也可以自己修改逻辑自定义数据库字段,和随意定制 UI 样式。
> 


#### css

1,盒模型
2,如何实现一个最大的正方形
3,一行水平居中,多行居左
4,水平垂直居中
5,两栏布局,左边固定,右边自适应,左右不重叠
6,如何实现左右等高布局
7,画三角形
8,link @import导入css
9,BFC理解


![](https://img-blog.csdnimg.cn/img_convert/00d0d05126be9b901c4f2272aa93fc7a.webp?x-oss-process=image/format,png)

#### js

1,判断 js 类型的方式
2,ES5 和 ES6 分别几种方式声明变量
3,闭包的概念?优缺点?
4,浅拷贝和深拷贝
5,数组去重的方法
6,DOM 事件有哪些阶段?谈谈对事件代理的理解
7,js 执行机制、事件循环
8,介绍下 promise.all
9,async 和 await,
10,ES6 的 class 和构造函数的区别
11,transform、translate、transition 分别是什么属性?CSS 中常用的实现动画方式,
12,介绍一下rAF(requestAnimationFrame)
13,javascript 的垃圾回收机制讲一下,
14,对前端性能优化有什么了解?一般都通过那几个方面去优化的?


![](https://img-blog.csdnimg.cn/img_convert/4d466aaa70013a1125aa69e416b19d2a.webp?x-oss-process=image/format,png)

**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/topics/618166371)**



 ES6 分别几种方式声明变量
3,闭包的概念?优缺点?
4,浅拷贝和深拷贝
5,数组去重的方法
6,DOM 事件有哪些阶段?谈谈对事件代理的理解
7,js 执行机制、事件循环
8,介绍下 promise.all
9,async 和 await,
10,ES6 的 class 和构造函数的区别
11,transform、translate、transition 分别是什么属性?CSS 中常用的实现动画方式,
12,介绍一下rAF(requestAnimationFrame)
13,javascript 的垃圾回收机制讲一下,
14,对前端性能优化有什么了解?一般都通过那几个方面去优化的?


[外链图片转存中...(img-aJR7CN9N-1715275855396)]

**[开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】](https://bbs.csdn.net/topics/618166371)**



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值