likes
comments
collection
share

react-native 热更新实践

作者站长头像
站长
· 阅读数 48

注:转载需要注明出处

配置appcenter

一、安装appcenter

npm install -g appcenter-cli 
/** 安装完成后 */
appcenter help
/** 如果出现帮助指令说明安装成功 */

二、appcenter login

在控制台执行

appcenter login

执行后在打开的浏览器选择一种登陆方式登陆(打开的网页需要挂代理)

登陆成功后会获得token,将token 填入控制台完成登陆。

react-native 热更新实践

登陆成功后

执行

appcenter profile list

查看登陆信息是否正确。

三、在appcenter 上创建不同平台的app

    appcenter apps create -d <appDisplayName> -o <operatingSystem> -p <platform>

只考虑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 <ownerName>/RNDemoiOS Staging 
appcenter codepush deployment add -a <ownerName>/RNDemoiOS Production
//android
appcenter codepush deployment add -a <ownerName>/RNDemoAndroid Staging
appcenter codepush deployment add -a <ownerName>/RNDemoAndroid Production

以上shell命令都会返回成功的提示

执行一下语句

//自行替换
ownername appName appcenter codepush deployment list -a <ownerName>/<appName> -k

react-native 热更新实践

到这里appcenter 配置过程完成

4、出现的问题以及踩的坑

  • appcenter login 的网页需要挂代理
  • 在appcenter.ms/apps 网站上没找到地方看上传的包以及部署分支,不知道是不是姿势不对
5、更多

详细的api详见

github.com/microsoft/a…

learn.microsoft.com/zh-cn/appce…

安装 react-native-code-push 及配置

一、安装

执行

yarn add react-native-code-push cd ios && pod install

二、React Native 0.60及以上版本插件安装配置(iOS)

此处只针对react-native 0.60 版本及以上配置

  1. 确保已安装必须的CocoaPods依赖项
  2. 打开AppDelegate.m文件,并为 CodePush 标头添加导入语句:
#import <CodePush/CodePush.h>

AppDelegate.m (注意:#import 必须在FB_SONARKIT_ENABLED 前面,否则ios archive 会报错)

#import "AppDelegate.h" 
#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h> 
//** 引入热更新 
#import <CodePush/CodePush.h>
#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h> 
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h> 
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>

  1. 找到这一行
return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
  1. 替换为
return [CodePush bundleURL];
  1. 增加部署的key值到 info.plist中。key值详见上方1.3
<key>CodePushDeploymentKey</key>
<string>xxx</string>

到这里ios就配置完成了

更多的内容以及配置react-native 版本0.6以下的详见

github.com/microsoft/r…

三、React Native 0.60及以上版本插件安装配置(Android)

  1. 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')
  1. 在你的android/app/build.gradle
... 
apply from: "../../node_modules/react-native/react.gradle" 
//添加这一行 apply
from: "../../node_modules/react-native-code-push/android/codepush.gradle" 
...
  1. 通过以下更改,更新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();
        }
    };
}
  1. 将部署的key加入到strings.xml
<resources>
    <string name="app_name">AppName</string> 
    //xxx 是部署的key 
    <string moduleConfig="true" name="CodePushDeploymentKey">xxx</string>
</resources>

到这里安卓配置就完成了

更多的配置

github.com/microsoft/r…

四、遇到的问题以及踩的坑

  • xcode 运行项目到模拟器的时候报错

Could not build module 'Foundation'

解决方案: 更新mac系统到最新,更新xcode版本到最新

  • xcode archive 项目打包时提示:

use of undeclared identifier 'CodePush'

解决方案:#import 必须在FB_SONARKIT_ENABLED 前面,否则ios archive 会报错

react-native 项目代码

一、react-native 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 (
            <View>
                <TouchableOpacity onPress={this.onButtonPress}>
                    <Text>Check for updates</Text>
                </TouchableOpacity>
            </View>
        )
    }
}

MyApp = codePush(codePushOptions)(MyApp);

二、快速验证代码

替换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 (
    <SafeAreaView style={backgroundStyle}>
      <View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
        <TouchableOpacity onPress={check}>
          <Text>Check for updates</Text>
        </TouchableOpacity>
        <Text>当前版本1.1.1</Text>
        <TouchableOpacity onPress={clear} style={{marginTop: 20}}>
          <Text>clear updates</Text>
        </TouchableOpacity>
        {/** 校验图片 */}
        {/* <Image source={testImg} style={{width: 100, height: 100}} /> */}
        {/** 验证视频 */}
        {/* <Video
          source={consultant}
          resizeMode="cover"
          paused={false}
          repeat
          style={{width: 200, height: 200}}
        /> */}
      </View>
    </SafeAreaView>
  );
};

export default CodePush(App);

三、遇到的问题以及踩到的坑

  • 在react-native-cli 初始化时,抛出错误

cli.init(root, projectName);

原因是0.7以上版本的react-native 不支持 基于react-native-cli创建

于是锁定到目前用的版本 0.67.5

npx react-native init demoOnline --template react-native-template-typescript --version 0.67.5

创建成功

推送更新

一、上传你的jsbudle包到codepush,发布更新

appcenter codepush release-react -a <ownerName>/<appName> 

//example 
appcenter codepush release-react -a <ownerName>/MyApp-iOS
appcenter codepush release-react -a <ownerName>/MyApp-Android

发布成功会提示

react-native 热更新实践 此时你就可以测试一下热更新问题

二、遇到的问题以及踩到的坑

  • codepush 推送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包名和项目名一致

实际使用效果

一、效果

效果如图,图片资源和视频资源也测试过,完全没有问题

参考文档

juejin.cn/post/706595…

github.com/microsoft/r…

github.com/microsoft/a…

learn.microsoft.com/zh-cn/appce…

转载自:https://juejin.cn/post/7194783242279616569
评论
请登录