以下是基于CodePush的热更新方案的实践,有需要的可以参考一下:
一、配置appcenter
1.1 安装appcenter
安装appcenter的命令如下:
npm install -g appcenter-cli
/** 安装完成后 */
appcenter help
/** 如果出现帮助指令说明安装成功 */
安装成功之后,登录appcenter,涉及的命令如下:
appcenter login
执行后在打开的浏览器选择一种登陆方式登陆(打开的网页需要挂代理)。
登陆成功后会获得token,将token 填入控制台完成登陆。
登陆成功后,执行如下命令可以查看登陆信息。
appcenter profile list
1.2 创建不同平台的App
创建的命令格式如下:
appcenter apps create -d -o -p
比如,下面是只考虑iOS 和Android平台。
appcenter apps create -d RNDemoAndroid -o Android -p React-Native
appcenter apps create -d RNDemoiOS -o iOS -p React-Native
接着,创建App在Staging和Production环境的部署key,命令如下。
//ios
appcenter codepush deployment add -a /RNDemoiOS Staging
appcenter codepush deployment add -a /RNDemoiOS Production
//android
appcenter codepush deployment add -a /RNDemoAndroid Staging
appcenter codepush deployment add -a /RNDemoAndroid Production
以上shell命令都会返回成功的提示。接下来,再执行一下语句。
//自行替换
ownername appName appcenter codepush deployment list -a / -k
到此,appcenter配置过程就完成了。关于Appcenter的使用和配置,可以参考下面的内容。
https://github.com/microsoft/appcenter-cli
https://learn.microsoft.com/zh-cn/appcenter/
二、react-native-code-push安装及配置
2.1 安装
安装的命令如下:
yarn add react-native-code-push cd ios && pod install
2.2 iOS配置
此处只针对react-native 0.60 版本及以上配置,配置前请确保已安装必须的CocoaPods依赖项。打开AppDelegate.m文件,并为 CodePush 标头添加导入语句:
#import
AppDelegate.m的代码如下 (注意:#import 必须在FB_SONARKIT_ENABLED 前面,否则ios archive 会报错)。
#import "AppDelegate.h"
#import
#import
#import
//** 引入热更新
#import
#ifdef FB_SONARKIT_ENABLED
#import
#import
#import
#import
#import
#import
然后替换下面的代码:
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
//替换为
return [CodePush bundleURL];
增加部署的key值到 info.plist中。
CodePushDeploymentKey
xxx
更多的内容以及配置react-native 版本0.6以下的详见内容:https://github.com/microsoft/react-native-code-push/blob/master/docs/setup-ios.md。
2.3 Android配置
打开android/settings.gradle文件,然后在结尾插入如下配置:
...
include ':app', ':react-native-code-push'
project(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')
然后,在android/app/build.gradle中添加如下配置代码:
...
apply from: "../../node_modules/react-native/react.gradle"
//添加这一行 apply
from: "../../node_modules/react-native-code-push/android/codepush.gradle"
...
打开MainApplication.java文件,然后引入以 CodePush代码。
...
// 1. Import the plugin class.
import com.microsoft.codepush.react.CodePush;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
...
// 2. Override the getJSBundleFile method in order to let
// the CodePush runtime determine where to get the JS
// bundle location from on each app start
@Override
protected String getJSBundleFile() {
return CodePush.getJSBundleFile();
}
};
}
将部署的key加入到strings.xml。
AppName
//xxx 是部署的key
xxx
更多的配置,请参考:https://github.com/microsoft/react-native-code-push/blob/master/docs/setup-android.md
2.4 遇到的问题
1,Xcode运行项目到模拟器的时候报错:Could not build module 'Foundation'。
解决办法:更新mac系统到最新,更新xcode版本到最新!!!
2,Xcode archive 项目打包时提示:use of undeclared identifier 'CodePush'
解决办法:#import 必须在FB_SONARKIT_ENABLED 前面,否则ios archive 会报错
三、React Native 项目代码
3.1 修改代码
为了实现RN的更新,我们还需要对RN项目的代码进行修改。首先,需要在项目的入口文件中引入CodePush,并添加如下逻辑:
//for class
import codePush from "react-native-code-push";
class MyApp extends Component { }
MyApp = codePush(MyApp);
//for hook
import codePush from "react-native-code-push";
const MyAp = () => { }
// 如果需要更快更新,可以将 MyApp = codePush(MyApp) 添加;
// let codePushOptions = { checkFrequency: codePush.CheckFrequency.ON_APP_RESUME };
// MyApp = codePush(codePushOptions)(MyApp);
MyApp = codePush(MyApp);
如果需要手动检查更新,也可以使用下面的代码:
let codePushOptions = { checkFrequency: codePush.CheckFrequency.MANUAL };
class MyApp extends Component {
onButtonPress() {
codePush.sync({
updateDialog: true,
installMode: codePush.InstallMode.IMMEDIATE
});
}
render() {
return (
Check for updates
)
}
}
MyApp = codePush(codePushOptions)(MyApp);
3.2 快速验证代码
下面,我提供了快速验证效果的示例代码。替换app.tsx 为以下代码可以快速验证热更新效果。
/* eslint-disable no-lone-blocks */
/* eslint-disable react-native/no-inline-styles */
import React from 'react';
import type {Node} from 'react';
import {
SafeAreaView,
Text,
Alert,
useColorScheme,
TouchableOpacity,
View,
Image,
} from 'react-native';
import testImg from './assets/test.png';
import Video from 'react-native-video';
import CodePush from 'react-native-code-push';
import consultant from './assets/video/consultant.mp4';
const App: () => Node = () => {
const backgroundStyle = {
backgroundColor: '#fff',
flex: 1,
};
const check = () => {
CodePush.sync(
{
installMode: CodePush.InstallMode.IMMEDIATE,
},
(status: CodePush.SyncStatus) => {
console.log(status, CodePush.SyncStatus);
switch (status) {
case CodePush.SyncStatus.UP_TO_DATE:
{
Alert.alert('已经是最新版本');
}
break;
case CodePush.SyncStatus.DOWNLOADING_PACKAGE:
{
Alert.alert('正在下载更新包');
}
break;
case CodePush.SyncStatus.UPDATE_INSTALLED:
{
Alert.alert('最新版本已安装');
}
break;
case CodePush.SyncStatus.UPDATE_IGNORED:
{
Alert.alert('更新已忽略');
}
break;
case CodePush.SyncStatus.CHECKING_FOR_UPDATE:
{
Alert.alert('正在检查更新');
}
break;
default:
break;
}
console.log(status);
},
() => {},
);
};
const clear = () => {
CodePush.clearUpdates();
};
return (
Check for updates
当前版本1.1.1
clear updates
{/** 校验图片 */}
{/* */}
{/** 验证视频 */}
{/* */}
);
};
export default CodePush(App);
四、推送更新
首先,上传jsbudle包到codepush,执行发布更新命令:
appcenter codepush release-react -a /
//example
appcenter codepush release-react -a /MyApp-iOS
appcenter codepush release-react -a /MyApp-Android
发布成功会收到成功的提示。
在操作的过程中,遇到了一个推送jsbudle 错误。
appcenter codepush release-react -a 1256003290-qq.com/RNDemoIOS --plist-file-prefix "ios/orange"
/**error message */
/**Command 'codepush release-react -a 1256003290-qq.com/RNDemoIOS' failed with exception "Unable to find either of the following plist files in order to infer your app's binary version: "ios/reactnativecli/Info.plist", "ios/Info.plist". If your plist has a different name, or is located in a different directory, consider using either the "--plist-file" or "--plist-file-prefix" parameters to help inform the CLI how to find it." */
appcenter codepush release-react -a 1256003290-qq.com/RNDemoIOS
/** Command 'codepush release-react -a 1256003290-qq.com/RNDemoIOS' failed with exception "Unable to find either of the following plist files in order to infer your app's binary version: "ios/reactnativecli/Info.plist", "ios/Info.plist". If your plist has a different name, or is located in a different directory, consider using either the "--plist-file" or "--plist-file-prefix" parameters to help inform the CLI how to find it."*/
appcenter codepush release-react -a 1256003290-qq.com/RNDemoIOS -p"ios/orange/info.plist"
/** Command 'codepush release-react -a 1256003290-qq.com/RNDemoIOS -p ios/orange/info.plist' failed with exception "Unable to find either of the following pbxproj files in order to infer your app's binary version: "ios/reactnativecli.xcodeproj/project.pbxproj", "ios/project.pbxproj"."*/
发现怎么执行,codepush 都表示路径不对,找不到info.plist。最后发现codepush 去的包名是从package.json的name,他会按照这个去找路径下的配置文件,我的包名恰好和项目名不一致,导致了问题。然后,修改package包名和项目名一致后就可以了。