概述
本文档记录了CodePush的研究过程。主要记录了过程当中的尝试、步骤、代码、错误等等内容。 本记录主旨在于1. 备忘。2. 避免重复研究。3. 反复在错误方向上是错。 记录内容按时间先后记录,未经分类整理,相对混乱。
研究记录
在研究Cordova热更新的时候发现微软的AppCenter已经提供了一套完整的热更新方案。其中也包含了关于Cordova的热更新策略,不用自己开发。 这套策略大概叫做「CodePush」(后文简称「CP」)
本文为将记录研究和实践「CP」的步骤、问题、方法以及备忘。
创建项目以测试方案。 创建一个Cordova项目测试、实践「CP」方案。 需要注意的是,iOS和Android要独立建立项目,这说的是App的项目要独立(Web可以共用),否则会出现冲突的情况。 因为对iOS比较熟悉,这里先建立一个iOS的「CP」项目。 项目名:CodePush-iOS 简单用Cordova create创建项目,没有对项目的配置,包括项目名进行任何修改。
$ cordova create CodePush-iOS
创建以后添加iOS平台。 用xcode打开项目,经过测试能够正常运行。
$ cordova platform add ios
我把项目commit到gitlab上,方便后面进行不同的分支测试。
补充一些学习材料 https://github.com/microsoft/cordova-plugin-code-push#getting-started
https://github.com/microsoft/code-push/blob/master/cli/README.md#releasing-updates
添加CodePushPlugin
$ cordova plugin add cordova-plugin-code-push@latest
需要在config.xml
添加下面配置。
Android
<platform name="android">
<preference name="CodePushDeploymentKey" value="YOUR-ANDROID-DEPLOYMENT-KEY" />
</platform>
iOS:
<platform name="ios">
<preference name="CodePushDeploymentKey" value="YOUR-IOS-DEPLOYMENT-KEY" />
</platform>
YOUR-XXX-DEPLOYMENT-KEY需要通过向AppCenter注册App获取,后面再修改
[CP]提供一套管理工具,CLI。 安装管理工具:
$ npm install -g code-push-cli
安装完CLI以后可以通过code-push
命令进行[CP]相关的管理操作。
注册AppCenter账号
$ code-push register
该命令会在浏览器打开注册网页,注册完以后会返回一个token。把token输入到命令终端完成登录。
注册AppCenter需要微软账号或者也可以通过GitHub,facebook,google账号进行注册。因为主要跟开发有关,跟微软的产品关系不大,我用的GitHub账号进行注册。 注册时大概是这样的:
如果已经注册过,需要在其它机器上进行登录操作,可以用下面命令进行操作,同样会打开网页进行登录
$ code-push login
向AppCenter账号添加App
$ code-push app add CodePush-iOS ios cordova
code-push app add
是添加命令
CodePush-iOS
项目名
ios cordova
项目平台
添加成功以后终端会显示出App的deployment keys。
日后也可以通过命令查看App的keys。
$ code-push deployment list CodePush-iOS -k
这个key需要填入到前面的config.xml
中。
iOS:
<platform name="ios">
<preference name="CodePushDeploymentKey" value="PIfa8aEs6IMrTBpRxrV61CfqCb895da83381-9533-42a3-bf08-f7d84dac3918" />
</platform>
用命令列出AppCenter上注册的App
$ code-push app ls
在web的js代码中添加codePush.sync()
触发热更新。我在index.js
的deviceready
事件中添加。
onDeviceReady: function() {
this.receivedEvent('deviceready');
console.log('=========【codePush.sync()】'); //打印一下确认被调用
codePush.sync(); //添加这段代码触发热更新
}
需要在index.html文件的
下添加下面元素。没有深入考究具体作用,应该是为了让App能够访问更新的存储网站 <meta http-equiv="Content-Security-Policy" content="default-src https://codepush.azurewebsites.net 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *" />
找到一份关于[CP]操作的视频资料(英文) https://www.youtube.com/watch?v=znHwW6A1Joc&t=308s
在cordova项目的根目录下创建build.json
文件,配置iOS项目:
{
"ios": {
"debug": {
"codeSignIdentity": "iPhone Developer",
"automaticProvisioning": true,
"developmentTeam": "2WT78RG4ZP",
"packageType": "development"
}
}
}
修改config.xml
文件,设置项目名和widget id
。
widget id
相当于iOS 项目的bundle id。
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.easternphoenix.CodePush-iOS" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>CodePush</name>
<description>
...
</widget>
修改项目名以后,由于项目名都变更,iOS项目并不会动态刷新,需要把iOS平台删除,然后再重建。
$ cordova platform rm ios
$ cordova platform add ios
build ios项目
$ cordova build ios
在真机上run项目
$ cordova run ios
测试通过,正常运行App。
下面我会修改web的代码,然后尝试推到真机上。
把index.html
进行修改,在
<h1>Apache Cordova Haha</h1>
上添加了「Haha」
<h1>Apache Cordova Haha</h1>
在项目的platform下用xcode打开ios项目。 在模拟器上运行了一遍,观测到代码在UI上已经生效。 用模拟器运行所以真机的App不受影响。后面尝试通过[CP]推到真机上。
通过safari查看模拟器的运行,发现报错了,错误信息
[Error] Failed to load resource: The requested URL was not found on this server. (acquisition-sdk.js.map, line 0)
真机也出现了同样的情况
删除平台和plugin然后重新安装看情况怎样。 问题没有解决。
按照上面视频材料的步骤操作一次,看看情况。 下面备注尽量简短。
$ cordova create ConnectDemo
$ cd ConnectDemo
$ code-push app add ConnectDemo android cordova
$ cordova plugin add cordova-plugin-code-push
config.xml
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.easternphoenix.ConnectDemo" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name>ConnectDemo</name>
...
<platform name="android">
<allow-intent href="market:*" />
<preference name="CodePushDeploymentKey" value="jSAP6PyZUBfrwJhfK3to5d5k03AF5da83381-9533-42a3-bf08-f7d84dac3918" />
</platform>
...
index.html
<html>
<head>
...
<meta http-equiv="Content-Security-Policy" content="default-src https://codepush.appcenter.ms 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
...
</head>
...
</html>
index.js
var app = {
...
onDeviceReady: function() {
this.receivedEvent('deviceready');
codePush.sync();
},
...
};
app.initialize();
$ cordova platform add android
$ cordova run android
运行成功
在Chrome的地址栏输入:chrome://inspect
然后选择我们的App(Hello World)
App在后台成功打印出[CodePush] App is up to date.
并没有发生iOS的情况
回忆: 在配置运行android项目的时候,也出现过CodePush报错,信息大概是CodePush插件与platform不兼容。为了处理报错,反复的删除插件和platform。其中也更新了平台:
$ cordova platform update android
$ cordova platform update ios
继续尝试用CodePush更新代码到App上:
index.html
:
<html>
...
<body>
<div class="app">
<h1>Apache Cordova Haha</h1>
...
</div>
...
</body>
</html>
刷新代码
$ cordova prepare
推送更新
$ code-push release ConnectDemo ./platforms/android/app/src/main/assets/www 0.0.1
系统显示推送成功。
在chrome的console用location.reload()方法刷新页面,但App的UI并没有刷新
找到没有刷新的原因,是因为版本配置有问题,config.xml
的version是1.0.0,而前面推的是0.0.1。需要对App的版本进行修正。
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.easternphoenix.ConnectDemo" version="1.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
...
</widget>
推版本
$ code-push release ConnectDemo ./platforms/android/app/src/main/assets/www 1.0.1
在chrome再次刷新,检查到更新,但没有进行加载,信息如下:
codePushUtil.js:36 [CodePush] Checking for update. codePushUtil.js:36 [CodePush] An update is available, but it is targeting a newer binary version than you are currently running. codePushUtil.js:36 [CodePush] App is up to date.
重新配置尝试不同的版本号搭配:
config.xml
2.0.0
run
查到更新,并刷新UI
推2.0.1 没刷新UI
列出release历史
$ code-push deployment history ConnectDemo Staging
需要看看App到底装的哪个版本 查到2.0.0
code-push release命令的版本号是控制哪些个版本需要更新的。 标记2.0.1的release是不能更新到2.0.0的设备上的。 所以策略应该是,让设备安装2.0.0版本,然后推2.0.0版的更新(更新到2.0.1)。
config.xml
3.0.0
run
UI刷新到3.0.0
config.xml
3.0.1
推送3.0.0
chrome刷新web 成功检测到更新并且下载安装。关闭重启App后成功更新到新的UI
至此算测试成功(散花)
后续任务:
- 了解更新的策略和规律
- 解决研究ios的问题
- 设计建立应用CodePush的项目设计管理策略
- 还需要解决android设备的remote debug无法正常运作的问题。(模拟器实在太慢)
CodePush简介: 在SmartSolution开展之初本打算自己实施一套热更新策略。在研究良久以后才偶然发现CodePush已经提供了完整的解决方案。 CodePush原本是一套解决Cordova的热更新方案,早期还需要用户自己建立代码服务器。 发展到后来由微软提供一整套完整方案并融入到它的AppCenter平台中。AppCenter还提供了React-Native的热更新方案。除了热更新以外,还提供了App的分析工具。
回到iso项目上
remove ios platform 和 plugin,更新platform
$ cordova platform rm ios
$ cordova plugin rm ...
$ cordova platform update ios
添加platform,plugin
$ cordova platform add ios
$ cordova plugin add cordova-plugin-code-push
版本号改成0.0.1
config.xml
<?xml version='1.0' encoding='utf-8'?>
<widget id="com.easternphoenix.CodePush-iOS" version="0.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
...
<platform name="ios">
<!-- Staging -->
<preference name="CodePushDeploymentKey" value="PIfa8aEs6IMrTBpRxrV61CfqCb895da83381-9533-42a3-bf08-f7d84dac3918" />
...
</platform>
</widget>
在配置index.html
的时候发现meta http-equiv
元素下的content
值没有配https://codepush.appcenter.ms
修正后:
<meta http-equiv="Content-Security-Policy" content="default-src https://codepush.appcenter.ms 'self' data: gap: https://ssl.gstatic.com 'unsafe-eval'; style-src 'self' 'unsafe-inline'; media-src *; img-src 'self' data: content:;">
将App从设备删除,重新运行
$ cordova run ios
在safari中debug,仍然提示
[Error] Failed to load resource: The requested URL was not found on this server. (acquisition-sdk.js.map, line 0)
解决策略: 粗略研究后,没有发现有什么具体的发现。 决定另立项目重新测试。在干净的环境下重新测试。步骤上采用android项目中的方法。 先建立一个可行的案例
cordova用指定ios模拟器运行
$ cordova emulate ios --target iPhone-XR
还是报同样的错误
$ cordova emulate ios --target iPhone-XR --debug
同样失败
经查找,App包中确实是缺失了文件
.js.map
文件并不会拷贝到项目中
经研究,.js.map
文件是javascript的代码转换的信息文件。帮助调试用。
缺失并不妨碍项目的正常运行。
Safari调试中没有打印CodePush的信息是因为console中点选了Errors选项,只显示App的错误信息,CodePush事实上在正常运作。 取消选项后console正常显示。
$ code-push release-cordova MyApp ios --targetBinaryVersion "~0.0.0"
刷新成功
这份CodePush的CLI文档比较重要 CodePush Management CLI
经过研究,一般情况下,用"<="的版本号进行更新控制是比较方便的。 譬如最后一次发布的版本号是0.0.2,则用下面命令进行更新是比较合适的:
$ code-push release-cordova MyApp ios --targetBinaryVersion "<=0.0.2"
CodePush的更新操作还是比较繁琐的,一步出错很容易会出现严重的版本错乱问题,最好开发一个脚本或者web应用处理发布版本的事务。