参考了官方文档 ,和Sean Chase 大神的Implementing Cordova Hot Code Push in Your Ionic App
最近做了热更新,遇到了很多坑,记录一下
在PS: 文章大部分是本人手工翻译的,会有点儿僵硬,有不对的地方请指出
使用的官方推荐的cordova-hot-code-push
[TOC]
运行环境
- ionic --version : 4.0.5
- cordova --version: 8.0.0
注意事项
- 热更新最好不要弹出框让用户选择,这样很容易被苹果爸爸拒绝。所以最好悄悄的自动下载和更新。详情参考
- 打包时注意在
--prod
环境下执行cordova-hcp build
Update workflow
开始操作之前,不妨看看ionic热更新的原理,毕竟磨刀不误砍柴工,出了问题可以更好的排查
流程图如下:
图片来源官方文档- 用户打开APP
- 初始化插件,同时在后台线程启动 update loader
- update loader 从
config.xml
中获取config-file
(当然也可以在代码中或其他配置文件中配置),然后从这个链接指定的url来加载JSON数据。 然后拿加载的配置中release
版本与当前installed的release
相比较。如果两者不同,就需要进行下一步操作 - update loader 根据 APP配置文件
cordova-hcp.json
中的content_url
来加载 manifest file。 用它来比对,相对于上个release,有哪些更新了 - update loader 下载
content_url
地址对应的 updated/new 中的所有文件 - 如果一切顺利,将会发出更新已经准备完毕,可以安装的通知
- 更新安装后,app将会被重定向到APP的首页
How web project files are stored and updated
每个Cordova 项目都有一个 www
文件夹,用来存放所有的web文件。 当执行了 cordova build
,www
会被拷贝到平台指定的www
文件夹下
- Android平台拷贝到:
platforms/android/assets/www
- iS 平台拷贝到:
platforms/ios/www
这些文件将随APP一起打包。 我们不能更新它们,因为它们是只读文件。因此,首先要将这些文件宝贝到 external storage。 因为不想在拷贝这些文件的时候阻塞用户操作—将从打包的资源文件里显示index page。当以后的每一次启动/更新 ,都将从 external storage中加载index page
如果更新中包含有新添加的插件或者一些原生的代码,此时你需要在App Store发布新的版本。
同时,需要增加build version。 在现在启动时,热更新插件会检查build version是否改变,如果是,就会重新安装www
文件夹到external 文件夹中。
当你开发app的时候,会感到迷惑: 做些改动,启动app,但是看到的还是旧内容。现在你该恍然大明白了吧: 更新插件用的是external storage 中的web项目的version。可以用如下方式重置缓存:
- 手动卸载app,重装
- 增加build version,强制插件重装
www
文件夹。你可以更改config.xml中的
android-versionCode
或ios-CFBundleVersion
来达到该目的。 - 安装 local development add-on, 这个插件可以帮你完成任务。它会自动增加版本号。不过xcode9下,它会报bug,因为它是用swift编译的,需要你更改一些代码,会有点儿蛋疼。
也许你已经注意到了,在www
文件中有一个 chcp.json
文件,文件中有一个 release
字段,这个是用来定义web内容的version的。它是必须要有的字段,而且在每个release
中必须是惟一的。它有CLI生成,格式如:yyyy.MM.dd-HH.mm.ss
(i.e., 2015.09.01-13.30.35
).
更新插件会为每一个release
在external storage 创建一个同名的文件夹,同时把所有的web相关文件放入其中。它是项目的基地址。这种方式可以解决如下几个问题:
- 文件缓存问题。例如:在iOS中css文件被
UIWebView
缓存,即使reload了index page,新的样式也不会被显示。这时你必须杀掉APP,或者用一些奇淫技巧来改变css的url - 不会出现更新的内容被已存在的内容污染混淆,因为每次
release
更新用的是完全不同的文件夹 - 如果被污染了,我们还可以 rollback 到上一个版本
例如,假设当前我们的APP运行着 2015.12.01-12.01.33
版本。 意味着:
- 所有的web内容都存储在
/sdcard/some_path/2015.12.01-12.01.33/www/
文件夹下。包括Cordova指定的文件 - index page显示的是
/sdcard/some_path/2015.12.01-12.01.33/www/index.html
过了一阵,我们发布了新的版本: 2016.01.03-10.45.01
。首先,更新插件会在设备上加载它,同时:
- 一个新的文件夹在external storage 中创建:
/sdcard/some_path/2016.01.03-10.45.01/
. - 其中
update
文件夹被创建 :/sdcard/some_path/2016.01.03-10.45.01/update/
- 所有
chcp.manifest
中标记的新的或变更的文件都将放置在update
文件夹中 - 这部分release会被下载到应用内部,并做好安装准备
当安装更新时:
- 更新插件拷贝当前版本(正显示给用户的)的
www
文件夹到新版本 release的文件夹。例如,拷贝所有/sdcard/some_path/2015.12.01-12.01.33/www/
下的文件到/sdcard/some_path/2016.01.03-10.45.01/www/
中 - 拷贝
update
目录下的新文件,更新的文件以及配置文件到www
目录中。例如:/sdcard/some_path/2016.01.03-10.45.01/update/
->/sdcard/some_path/2016.01.03-10.45.01/www/
- 移除
/sdcard/some_path/2016.01.03-10.45.01/update/
目录,我们已经不再需要它了 - 从新release中加载index page:
/sdcard/some_path/2016.01.03-10.45.01/www/index.html
此时更新插件将会从新release目录中加载index page,以前的release的将会作为备份以防万一。
Step1 Create the Application
通过命令行创建新的ionic空白项目
ionic start chcp-example blank
cd .\chcp-example
Step2 Install Plugins
这里不用官方推荐的内置服务器,此处选择更灵活的 lite-server
, 通过它提供的服务器来更新APP。 我们需要
-
将
lite-server
全局安装 -
并添加iOS和Android平台支持
-
安装 Cordova Hot Code Push plugin
-
安装cordova-hot-code-push-cli
npm install -g lite-server
ionic cordova platform add android
ionic cordova plugin add cordova-hot-code-push-plugin
npm install -g cordova-hot-code-push-cli
Step3 Initializing the Hot Code Plugin Configuration
首先,在命令行执行 cordova-hcp init
按照提示输入信息,不用担心Amazon相关的信息,可以不用填写
chcp-example>cordova-hcp init
Running init
Please provide: Enter project name (required): chcp-example
Please provide: Amazon S3 Bucket name (required for cordova-hcp deploy):
Please provide: Path in S3 bucket (optional for cordova-hcp deploy):
Please provide: Amazon S3 region (required for cordova-hcp deploy): (us-east-1)
Please provide: IOS app identifier:
Please provide: Android app identifier:
Please provide: Update method (required): (resume) start
Please provide: Enter full URL to directory where cordova-hcp build result will be uploaded: http://youserverip:3000/updates
Project initialized and cordova-hcp.json file created.
If you wish to exclude files from being published, specify them in .chcpignore
Before you can push updates you need to run "cordova-hcp login" in project directory
此时,你可以看到项目根目录新生成了一个文件 cordova-hcp.json
,内容大概如下:
{
"name": "chcp-example",
"ios_identifier": "",
"android_identifier": "",
"update": "start",
"content_url": "http://youserverip:3000/updates"
}
编辑 config.xml
文件,因为要悄悄的自动下载和安装,所以要打开自动下载和自动安装配置。
<chcp>
<config-file url=”http://youserverip:3000/updates/chcp.json"/
<auto-download enabled=”true” />
<auto-install enabled=”true” />
</chcp>
Step4 Writing Application Logic
先在 /chcp-example/src/app/app.module.ts
文件中引入 HotCodePush
在 /chcp-example/src/app/app.component.ts
文件中添加更新逻辑。
upgradeUrl = "your content file url"
constructor(
private hotCodePush: HotCodePush,
config: ConfigurationService,
) {
this.upgradeUrl = config.getValue<string>('upgradeUrl')
}
checkUpgrade() {
const options = {
'config-file': this.upgradeUrl,
}
this.log.debug(methodName, this.upgradeUrl)
this.hotCodePush.fetchUpdate(options).then(
data => {
this.log.debug(methodName, data)
this.installUpgrade()
},
error => {
this.log.debug(methodName, error)
},
)
}
installUpgrade() {
this.hotCodePush.installUpdate().then(
data => {
},
error => {
},
)
}
Step5 Build and Run in the Android/iOS
cordova prepare ios
cordova-hcp build
cordova run ios --device
Step6 Applying Updated Application Logic
让APP在手机或模拟器上继续running, 现在改动home.html
文件中的文字
更改完毕后再次执行如下命令:
cordova prepare ios
cordova-hcp build
更新后的代码会在 www
文件夹下生成信息的文件
Step7 Providing the Updated Code
在与项目文件夹chcp-example
平级处创建 lite-server
的目录chcp-example-server
,并创建子其目录updates
— 这是用来放将要发布的代码更新。
用命令行来启动lite-server
chcp-example-server>lite-server
因为是在本机测试,需要将你的手机与电脑连接到同一个局域网中,然后手机的网络代理设置成电脑的ip+端口号3000. iOS的具体设置
将 www
文件夹中的所有内容拷贝到 updates
文件夹中。
回到手机上的APP,然后手动杀掉它。然后重新打开,3秒内白屏一闪, 改动就可以看到了。
更多阅读:
网友评论