vivipure / blog

Funkun's blog.
https://funkun.hashnode.dev/
2 stars 0 forks source link

React Native 热更新 #27

Open vivipure opened 2 years ago

vivipure commented 2 years ago

前言

之前用RN开发一个移动端App,支持安卓和iOS. 开发体验是挺好的,但是也存在痛点,就是每次页面更新都需要用户手动重新安装,实在不方便。好在 RN 支持热更新功能,本文就来好好讲讲如何实现热更新。

原理

RN 支持热更新的原理很简单。RN的界面是由JS开发,使用原生进行渲染的。打包后会生成一份JS的文件,在应用启动时,就会执行JS渲染页面。

当RN的页面修改或新增时,改变的只有JS. 因此更新的JS 替换 已经安装好的应用中的JS, 用户就能够使用到新的页面。

备注: 涉及到原生代码的改动,和第三方插件的原生改动 还是老老实实的重新发版本吧

所以办法就是,每次启动应用时都检查是否有最新的JS,然后下载到本地,下次启动时就能使用了。

如果全部自己实现的话,无非就是一个版本管理的CRUD, 然后再原生代码上加上版本下载更新的逻辑。

对于我的业务场景来说,就没有必要自己手动造轮子了。我直接使用 微软提供的 Code Push

如果不想使用微软的服务器,也可以自己搭建 https://github.com/lisong/code-push-server

过程

1. 安装 CodePush Cli

npm install -g appcenter-cli

2. 登录和创建应用

appcenter login

appcenter apps create -d <android_app> -o Android -p React-Native
appcenter apps create -d <iOS_app> -o iOS -p React-Native

这里需要针对 两个平台创建不同的应用,方便进行管理。

创建key

appcenter codepush deployment add -a <ownerName>/<appName> Staging
appcenter codepush deployment add -a <ownerName>/<appName> Production

使用如下命令进行查看

appcenter codepush deployment list -a <ownerName>/<appName>

3. 应用集成SDK

npm i react-native-code-push

在入口文件中对组件进行包裹

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

const codePushOptions = { checkFrequency: codePush.CheckFrequency.ON_APP_RESUME };
export default codePush(codePushOptions)(App)

3.1 iOS集成

首先别忘了更新依赖

cd ios
pod install

需要引入 CodePush, 我在 AppDelegate.mm 中不起作用,直接在AppDelegate.h引用

#import <CodePush/CodePush.h>

然后修改 AppDelegate.mm,更改读取JS bundle 的地方

- return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
+ return [CodePush bundleURL];

Info.plist 新增变量 CodePushDeploymentKey,填入之前申请的项目key

如果想配置多环境的话可以看这篇文章: https://github.com/microsoft/react-native-code-push/blob/master/docs/multi-deployment-testing-ios.md

3.2 android 集成

修改 android/setting.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

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();
        }
    };

在strings.xml 中填入 key

 <resources>
     <string name="app_name">AppName</string>
     <string moduleConfig="true" name="CodePushDeploymentKey">DeploymentKey</string>
 </resources>

安卓多环境文档: https://github.com/microsoft/react-native-code-push/blob/master/docs/multi-deployment-testing-android.md

4 发布更新

执行命令进行发布更新

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

然后在 CodePush 的后台就能看到刚才推送的更新了。

5. 注意点

  1. 版本号要规范,三位版本号
  2. 默认推送是 Staging ,可以通过 -d 直接推送 Production

总结

配置过程大概就这些了,配置好后就能享受丝滑的更新了。也正是因为这个特性,在做技术选型时,RN比Flutter的优势还是挺大的。