React Native的加载启动机制:
RN会将一系列资源打包成js bundle文件,系统加载js bundle文件,解析并渲染。所以,RN热更新的根本原理就是更换js bundle文件,并重新加载,新的内容就完美的展示出来了。
目前RN热更新的做法主要有以下3种,这里我们详细介绍微软的codepush方式,同时它也是主流的做法。
差量热更新
http://blog.csdn.net/szy406469533/article/details/75663722
http://blog.csdn.net/u013718120/article/details/55096393
热更新(Pushy)
http://blog.csdn.net/yzx0xyz/article/details/79056882?%3E
http://blog.csdn.net/xiangzhihong8/article/details/73201421
https://www.cnblogs.com/fishbay/archive/2017/07/18/7198782.html
微软codepush方式
》》CodePush简介
CodePush 是微软提供的一套提供给 React Native 和 Cordova 开发者,直接部署移动应用更新给用户设备的云服务。CodePush 作为一个中央仓库,开发者可以推送更新 (JS, HTML, CSS and images),应用可以从客户端 SDK 里面查询更新。CodePush 可以让应用有更多的可确定性,也可以让你直接接触用户群。在修复一些小问题和添加新特性的时候,不需要经过二进制打包,可以直接推送代码进行实时更新。
CodePush 可以进行实时的推送代码更新:
直接对用户部署代码更新
管理 Alpha,Beta 和生产环境应用
支持 React Native 和 Cordova
支持JavaScript 文件与图片资源的更新
》》步骤
1、安装code push 的 react native的SDK
npm install --save react-native-code-push@latest
安装完后,link连接
方式一:react-native link react-native-code-push
方式二:rnpm link react-native-code-push
(先安装rnpmnpm i -g rnpm
)
2、安装code push的CLI,以及注册登录code push账号
npm install -g code-push-cli
如果安装失败,先在项目根目录下执行cp .npmrc ~/
注册
code-push register
这将会启动浏览器,要求验证Github或微软帐号。一旦验证成功,它将创建一个CodePush帐号跟你的Github或MSA相连,并生成一个访问密钥(Access Key),然后你可以拷贝/粘贴到CLI(它会提示你这样做)
如果没有自动打开浏览器,检查设置默认的浏览器
如果已经注册过,使用code-push login
登录
3、注册应用(不同平台使用不同的名字)
code-push app add <appName> <os> <platform>
如:code-push app add Songshucang-iOS ios react-native
1-如果你的App既有iOS又有Android,请为不同平台创建单独的App;
2-成功,会返回Deployment Key。
3-所有新的Apps自动会出现2个部署环境:staging代表开发版的热更新部署,用于测试更新;production代表生产版的。
4-在ios中,将staging的key复制在info.plist的CodePushDeploymentKey值中
在android中,复制在Application的getPackages的CodePush构造中。
- 关于deployment-key的设置
ps:你可以通过code-push deployment ls <APP_NAME> -k命令来查看deployment key。
1.用Xcode 打开项目 ➜ Xcode的项目导航视图中的PROJECT下选择你的项目 ➜ 选择Info页签 ➜ 在Configurations节点下单击 + 按钮 ➜ 选择Duplicate "Release ➜ 输入Staging(名称可以自定义);
2.然后选择Build Settings页签 ➜ 单击 + 按钮然后选择添加User-Defined Setting
3.然后输入CODEPUSH_KEY(可自定义),把相关的Key添加进去
4、在 js中加载 CodePush模块
后台请求更新,执行如下代码:
import codePush from "react-native-code-push";
...
@codePush
export default class App extends Component {
componentDidMount{
codePush.sync()
}
...
}
》如果可以更新,CodePush会在后台静默地将更新下载到本地,等待APP下一次启动的时候应用更新,以确保用户看到的是最新版本。
》如果更新是强制性的,更新文件下载好之后会立即进行更新。
》如果你期望更及时的获得更新,可以在每次APP从后台进入前台的时候去主动的检查更新,执行如下代码:
componentDidMount{
AppState.addEventListener("change", (newState) => {
newState === "active" && codePush.sync();
});
}
5、发布更新RN的bundle到微软服务器
CodePush支持两种发布更新的方式:一是通过code-push release-react
简化方式,二是通过code-push release
的复杂方式。
o 简化方式
这种方式将打包和发布合二为一,大大简化了操作流程,建议使用。
code-push release-react <appName> <platform>
[--bundleName <bundleName>] 指明生成JS Bundle的文件名
[--deploymentName <deploymentName>] 部署环境名:Staging(临时环境)、Production(生产环境)
[--description <description>] 更新内容描述
[--development <development>] 指明是否要生成一个非最小化,开发的JS bundle文件。默认是false,禁用警告提示并且bundle文件是最小化的。
[--disabled <disabled>] 指明一个版本更新是否可以被用户下载。如果没有指定,版本更新是有效的(如:用户将要下载的那一刻你的应用称为`同步`)。如果你想发布一个更新但不是立即生效,那么这个参数是有价值的,直到你明确用[补丁]发布,当你要让用户能够下载(如:公告博客上线)。
[--entryFile <entryFile>] 指明相对应用根目录的路径入口JavaScript 文件。
[--mandatory] 更新是否强制性(true、false)
[--sourcemapOutput <sourcemapOutput>] 指明生成的JS bundle 的sourcemap写入的相对路径。如果没有指定,sourcemaps文件不会生成。
[--targetBinaryVersion <targetBinaryVersion>] app的版本号,如果没有指定,默认使用Info.plist中的version值
[--rollout <rolloutPercentage>]
指定可以接收这次更新的用户百分比(在1-100的数字)如果没有设置这个参数,它会设置为100。
o 复杂方式
发布更新之前,需要将js与图片资源打包成 bundle;
在工程目录里,新增 bundle文件夹;
在工程根目录,运行命令,打包;
react-native bundle --platform 平台 --entry-file 启动文件 --bundle-output 打包js输出文件
--assets-dest 资源输出目录 --dev 是否调试
打包bundle结束后,就可以通过CodePush发布更新了。在终端输入:
code-push release <应用名称> <Bundles所在目录> <对应的应用版本> --deploymentName: 更新环境
--description: 更新描述 --mandatory: 是否强制更新
如:code-push release gameApp ./bundles/index.android.bundle 1.0.6 --deploymentName Production --description "1.支持文章缓存。" --mandatory true
6、查看发布的历史记录
code-push deployment history MyProjectIOS Staging
7、iOS 端代码
#import "CodePush.h"
...
#ifdef DEBUG
jsCodeLocation = [[RCTBundleURLProvidersharedSettings]jsBundleURLForBundleRoot:@"index.ios"fallbackResource:nil];
#else
jsCodeLocation = [CodePush bundleURL];
#endif
资料
https://www.jianshu.com/p/fa362da953c7 *
http://blog.csdn.net/u013718120/article/details/78344866
https://www.jianshu.com/p/9e3b4a133bcc?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation * *
https://www.jianshu.com/p/e1a9302cfdff
http://blog.csdn.net/u011886447/article/details/78715407 * *
http://blog.csdn.net/u011886447/article/details/79052797?%3E
http://blog.csdn.net/dounine/article/details/78529106 * *
https://www.jianshu.com/p/67de8aa052af * *
https://www.jianshu.com/p/6e96c6038d80?from=timeline * *
http://blog.csdn.net/u014041033/article/details/73497708 *
https://github.com/rccoder/blog/issues/27
https://www.cnblogs.com/Master-W/p/7232569.html
官网
https://github.com/Microsoft/code-push/blob/master/cli/README-cn.md
https://github.com/Microsoft/react-native-code-push
实现了完整bundle包的基本热更新,但是这只是热更新的一部分,还有很多方面可以优化,比如:多模块的多bundle热更新、bundle拆分差量更新、热更新的异常回退处理、多版本bundle的动态切换、bundle的更新和apk的更新相结合等等,这也是之后继续研究学习的方向。
持续更新... ...