NXT-FE / blog

能效通前端团队博客
MIT License
4 stars 0 forks source link

CORDOVA APP热更新 #14

Open liuxinqiong opened 6 years ago

liuxinqiong commented 6 years ago

原理

主要分为如下几步

  1. 检查
    • 检查更新时只有文件的版本会进行比较
    • 通过比较打包在手机程序里的manifest.json文件和服务器上的manifest.json文件,如果服务器上的文件有过修改,那就和手机上的文件不一致了,这时候手机应用更新manifest.json到loacalStorage里面,以便下次比较。如果两个json文件一致,那就不做任何操作。
    • 开发过程中,localstorage中manifest,last_update_time,last_update_files不要删除,否则导致更新有问题!
  2. 下载
    • 通过指定的文件服务器(server),cordova应用将按照manifest.json文件的差异下载对应的js、css或者其他文件,下载到一个指定的目录(localRoot)下面。
  3. 更新
    • 将新的清单写入localstorage,重新加载页面引导更新后的应用程序。
    • 完成数据下载之后,新的数据更新到cordova应用中,下载完成是否立马更新取决于用户的设置,具体如下:
    • loader.update(),默认true,下载完成之后立马自动重新加载完成更新。
    • loader.update(false),下载完成之后,下次启动应用之后,使用上次下载的更新。
    • CordovaAppLoader将manifest.root指向文件缓存,否则bootstrap script找不到下载的文件。

配置

插件安装

本身热更新的使用在浏览器端就可以看到效果,使用只有chrome支持的HTML5特性fileSystem实现,但是要在手机端使用,必须安装如下插件:

config配置

<access origin="cdvfile://*" />
<allow-intent href="cdvfile://*" />

依赖库

bootstrap.js

cordova-app-loader-complete.js

下载cordova-app-loader-complete.js 位于lib,是cordova-app-loader、cordova-promise-fs、bluebird三者的合体,支持不同运行环境不同策略。

cordova-app-loader-complete.js是完整的CordovaAppLoader的库和依赖。如果不引入这个会导致autoupdate.js文件报错!

autoupdate.js

功能:你的app打开和恢复的时候自动更新

缺点:a.下载文件减缓页面渲染 b.自动更新可能会打断用户

使用

manifest.json

配置基本步骤

  1. 哪些文件需要下载
  2. 哪些文件需要加载到index.html
  3. update manifest.json 这里指版本号

配置demo

//这里的文件会被下载
"files": { 
    "app": {
      "version": "698221a70985560b9a1b038b89db33c73375e0de",
      "filename": "js/app.js"
    },
    "controller": {
      "version": "698221a70985560b9a1b038b89db33c73375e0de",
      "filename": "js/controller.js"
    }
  },
//这里的文件在index.html中加载
  "load": [
    "js/controller.js",
    "js/app.js"
  ],
  "version": "ae8199a17c3c921650b60506645b1eb24229d380"

load注意事项

load加载的顺序就是index加载的顺序,在ionic应用中,我们需要将入口文件加载在最后,否则会报错

version

用来标识文件的版本,如果本地版本和服务器版本一致,则check过程中会返回false,则不会下载和更新,保持使用本地的文件。

版本号可以使用cordova-app-loader库的命令进行生成,这样生成是按照文件内容的Hash值进行生成的,在实际开发环境中,不建议使用,因为版本号没有规律,无法实现版本回滚功能!版本号可以自己进行编写!

node node_modules/cordova-app-loader/bin/update-manifest www www/manifest.json
node node_modules/cordova-app-loader/bin/update-manifest [root-directory] [manifest.json]

他将会更新被修改过文件的版本号,使用内容的hash编码。

本地版本和服务器版本

App新发布过程,服务器的manifest.json文件应该和本地的manifest.json文件保持一致,这样check过程中检查版本号为一致时便会使用本地的资源!

这里有一点需要理解的是,此时index.html中不能引入可能会被更新的资源,因为如果文件有更新时,在index.html中就会被引入新旧版本两份资源,新资源不会生效,可能还会报错!那么index.html应该引入哪些资源呢,新资源中只能引入确定不会被更新的文件

index.html配置

<script type="text/javascript" server="http://localhost:3000/cordova-app-loader/" manifest="manifest.json" src="bootstrap.js"></script>

此时程序已运行,manifest.json文件会被保存在localStorage中,以便下次进行比较。

window.BOOTSTRAP_OK

在App成功启动时加入:

window.BOOTSTRAP_OK = true;

如果不设置window.BOOTSTRAP_OK为true,在timeout时间过后,localStorage中的manifest.json会被清空,页面会重新加载,导致app回退到最初时的manifest.json状态!

开发中应该总是绑定manifest.json和files,确保你的app有默认的工厂用来还原,同时保证你的app可以离线运行。

CordovaAppLoader核心函数

* update
```js
// write manifest to localStorage and reload page:
loader.update() // returns `true` when update can be applied
// write manifest to localStorage, but DO NOT reload page:
loader.update(false)

奔溃处理

在下载的过程中,如果出现奔溃,应用将会使用最初的清单进行重启。

对于引用了静态文件,比如图片,字体文件等,常见于CSS使用url引入,此时由于CSS中会出现net::ERR_FILE_NOT_FOUND错误,从而导致热更新出错,从而自动使用最初的清单进行重启!

目前问题依旧没有完美解决,热更新会导致 CSS 引入的静态资源找不到,目前的解决办法是,使用 asset.css 管理静态资源且不纳入热更新,如果存在静态资源更新,热更新就不那么好使了!

版本回滚

每次发布的时候要记录版本,用于回滚。具体设计:

规则没有明确规定,上述是目前我司热更新版本管理规则。

Q&A

  1. app第一次发布,如果服务器没有放manifest和文件,会怎么样呢?

后台会报404错误,会读取本地manifest文件载入localstorage,保证下次可以直接从localstorage中读取!

  1. app第一次进入,如果是在没网络的情况呢?

无网络的情况下,后台会报NETWORK的错误,会读取本地manifest文件载入localstorage,保证下次可以直接从localstorage中读取!

CShame commented 6 years ago

你真棒