React Native 插曲 打离线包和CodePush发布更新

用了两天才搞定了这些琐碎的操作,从真机调试到利用CodePush进行热更新。。。知道最后才发现一个血的教训:即使用了CodePush,本地也必须要有一个离线包才行,即本地需要打包一个main.jsbundle放进项目中,才可以成功运行。

首先,讲React Native的发布更新,这就涉及到React Native的热更新主要是怎么工作的,关键在于bundle的更新
我们先来看看ReactNative是怎么处理bundle文件(bundle文件用于资源管理)的。可以有如下两种方式:
1、app发版时,将bundle文件内置到app中,同时将图片和js文件内置到app中(Android和iOS处理的不同)
2、app在合适的时机,加载服务端最新的bundle文件

下面一张流程图简单介绍ReactNative的热更新机制:
(参考自:http://blog.csdn.net/codetomylaw/article/details/52115704

ReactNative的热更新.png

一、打离线包(打包bundle文件内置到app中)

离线包即本地存着一个离线包,保证没有网络的时候程序不会报错。
1、将js代码打包到jsbundle文件中
在index.ios.js所在目录下,执行以下命令(文件名自定义,使用codepush的时候最好命名为默认的main.jsbundle):

//  无图片资源等
react-native bundle --entry-file index.ios.js --platform ios --bundle-output main.jsbundle

//  有图片资源
react-native bundle --entry-file index.ios.js --platform ios --bundle-output index.ios.bundle --platform ios --dev false --assets-dest ./  

//  或者放bundle文件夹里(注意要先保证bundle文件夹存在!!!) 
react-native bundle –entry-file index.ios.js –bundle-output ./bundle/iosBundle/index.ios.jsbundle –platform ios –assets-dest ./bundle/iosBundle –dev false 

/*
entry-file: RN的入口文件
bundle-out: 输出bundle文件的输出路径(bundle文件名和oc里面的代码要对应)
asset-dest:输出的asset资源目录
*/

2、添加到项目中。
在xcode中添加assets【必须用Create folder references的方式,添加完是蓝色文件夹图标】和index.ios.jsbundle(或者main.jsbundle、命名不同)

网上参考的放bundle文件夹的目录结构和项目结构如下:


bundle文件夹的目录结构和项目结构(自网上).png

参考自:https://segmentfault.com/a/1190000004189538

个人利用第一句命令创建的包,目录如下:


离线包目录结构.png

3、修改AppDelegate.m文件(只使用离线包不使用热更新的情况)

//  URLForResource根据第一步对应的名字对应修改
jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"index.ios" withExtension:@"jsbundle"];

4、模拟器或者真机调试都没有问题。

顺带列举下ios打包可能遇到的问题(虽然我都没遇到哈):
1)离线包如果开启了chrome调试,会访问调试服务器,而且会一直loading出不来。
2)如果bundle的名字是main.jsbundle,app会一直读取旧的,改名就好了。。。非常奇葩的问题,我重新删了app,clean工程都没用,就是不能用main.jsbundle这个名字。
3)必须用Create folder references【蓝色文件夹图标】的方式引入图片的assets,否则引用不到图片
4)执行bundle命令之前,要保证相关的文件夹都存在

二、使用CodePush实现热更新

1. 环境准备(Mac)

1)安装Code-push cli

$ npm install -g code-push-cli

2) 注册CodePush账户

$ code-push register

执行以上命令将会自动打开如下图所示的注册页面:

注册页面.png

可以使用github或者Microsoft帐户注册(本文使用GitHub账户进行注册),注册成功后将会生成如下图所示相应的access token:

access token.png

按照提示在终端输入刚生成的access token(会自动登录):

输入access token.png

3)添加CodePush应用

$ code-push app add XXX      //xxx 为你要热部署的app name

结果如下:


添加CodePush应用.png

2. 安装CodePush

在项目更目录(或者说package.json所在目录)执行以下语句安装CodePush,会自动对应修改package.json内容。

npm install --save react-native-code-push

效果如下:

安装CodePush.png

3. 集成code-push 到工程文件

CodePush集成到项目中,一般有三种方法:
RNPM、CocoaPods 、"Manual"

详细可参考CodePush的Github:
https://github.com/Microsoft/react-native-code-push

下文分别对其接入方法进行简单介绍:
个人感觉按情况分,如果是将React Native集成到原生项目中的项目,因为本身应该有用到cocoaPods,所以推荐使用cocoaPods接入,比较方便简单。
如果是纯React Native项目,则可以考虑手动接入。

(因为我测试用的是原生集成项目,所以就使用了cocoaPods)

方式一:cocoaPods接入

1)修改Podfile文件:(自己注意路径哈)

pod 'CodePush', :path => './node_modules/react-native-code-push'

2)执行命令行更新pod:

pod install 
//  或者 
pod install --verbose --no-repo-update

方式二:手动接入

1)将react-native-code-push文件夹中 CodePush.xcodeproj 直接拉入项目中Libraries中

CodePush.xcodeproj 拉入项目.png

2)在Link Binary With Libraries中添加Libraries/CodePush.xcodeproj /Products中的libCodePush.a以及libz.tbd。

Link Binary With Libraries.png

3)在Build Settings的Header Search Paths那一项中加入(路径要注意)

$(SRCROOT)/../node_modules/react-native-code-push

Header Search Paths.png

方式三:RNPM接入

好像是官方推荐使用最简单的方式,不过没有试过哈
1)安装rnpm

$ npm -g install rnpm xcode

2)使用

$ rpm link

4. 修改项目配置

1)在命令行下使用code-push deployment ls <AppName> --displayKeys 查出Staging的值,在info.plist文件中添加CodePushDeploymentKey并且把Staging的值填入。
2)在Info.plist中将Bundle versions string, short的值修改为1.0.0(或者其它,结构一样为x.x.x,且和之后code push更新的版本要对应)

info.plist配置.png

5. 修改OC代码和JS代码

1)在加载 js bundle的类中 修改代码

a)首先,引入头文件:

#import "CodePush.h"

b)然后修改jsCodeLocation值:

//该文章是讨论在Release下进行相关的操作,如果是debug版本加上如下代码,系统在运行时候会自动切换。
NSURL *jsCodeLocation;
    
#ifdef DEBUG
    jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index.ios" fallbackResource:nil];
#else
    jsCodeLocation = [CodePush bundleURL];
#endif

//如果本地js离线包不是命名main.jsbundle,需要对CodePush进行相应设置
jsCodeLocation = [CodePush bundleURLForResource:@"index"];
2)在js文件中(该项目文件是index.ios.js) 修改代码

a)引入对应头文件

import codePush from "react-native-code-push";

b)在componentDidMount调用sync方法,当你的App启动的时候会在后台更新

componentDidMount(){
    codePush.sync();
  }

6. 发布更新

1)发布更新 (JavaScript-only)

当你修改js文件的时候,并且想立刻发布。则仅仅需要以下的操作:

  1. 将你修改的js文件(当前文件是index.ios.js)打包为二进制文件,放入指定的地方(当前位置为根目录)。
react-native bundle --platform ios --entry-file index.ios.js --bundle-output codepush.js --dev false
  1. 将二进制文件push到staging 环境中
code-push release [--deploymentName ] [--description ]  [--mandatory]
eg:
code-push release NativeTest codepush.js 1.0.0

// 上面代码运行有问题的话,试试把codepush.js后缀改成codepush.jsbundle。。好像目前版本和我上年底的要求不同了

2)发布更新 (JavaScript + images)

  1. –assets-dest 就是你放图片的位置(当前仅仅是做测试,实际上最好建个文件夹专门存入相关图片)
react-native bundle --platform ios --entry-file index.ios.js --bundle-output ./main.jsbundle --assets-dest ./<img 地址>
// main.jsbundle 为自定义名字的bundle名
  1. push bundle文件
code-push <release/debug> <projectName(与注册的app同名)><bundle文件名> <版本号>
eg:
code-push release NativeTest main.jsbundle 1.0.0

到这一步的时候,正常来说,该配置的都配置了,试着更新一个版本push到codepush上,运行下项目,就会出现效果。
注意:如果出现找不到main.jsbundle的报错,很大的原因就是没有在本地打个离线包,详细参考这篇文章的第一部分。(曾经因为这个原因,我看着报错发呆了好久,上网也找不到任何说法😂)

Q&A

  1. CodePush更新规则


    CodePush更新规则.png
  2. 更新后都需要重启才能看到最新的变化 再次进入后要等一会。TODO:还要验证后确定稳定时机。
  3. 查看历史上传过的版本:

code-push deployment history NativeTest Staging

查看历史上传过的版本.png

更多的CodePush相关命令推荐参考以下几篇文章:
Code Push 热更新使用详细说明和教程
app实现热更新codepush
以及CodePush的Github:
https://github.com/Microsoft/react-native-code-push

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容