阅读 595

Taro React Native 端开发流程

本篇主要讲解 Taro React Native 端 环境安装-开发-调试-打包-发布 原理及流程,React Native 开发前注意事项请看 开发前注意

简介

Taro 移动端的开发基于 Facebook 的开源项目 React Native,Taro3.x 将不再锁定 React Native 版本,用户可在项目中自行安装 >=0.60 版本的 React Native,对于 0.59 版本将在后续调研后决定是否兼容。 整体设计图如下: 其大致流程:

  1. @taro/cli 中通过 registerPlatform 注册 rn 平台;
  2. yarn dev:rn 获得编译配置,转为 babel.config.js 及 metro.config.js 配置;
  3. 所有 React Native 不支持的语法及配置,通过编译配置支持;
  4. 通过编译配置与 @tarojs/taro-rn-transformer 生成 React Native 的入口文件 index.ts
  5. 入口文件引入 @tarojs/taro-runtime-rn 使用createReactNativeApp 进行包装;
  6. 页面文件引入 @tarojs/taro-runtime-rn 使用createPageConfig 进行包装;
  7. 启动 metro bunlder
  8. 在 React Native Shell 工程中运行 react-native run-ios 或 react-native run-android 加载 index.bundle

搭建开发环境

搭建 Android 开发环境

必须安装的依赖有:

  • Node
  • React Native 命令行工具
  • Watchman (可以快速捕捉文件的变化从而实现实时刷新)
  • JDK Java Development Kit
  • Android Studio 虽然你可以使用任何编辑器来开发应用(编写js代码),但你仍然必须安装 Android Studio 来获得编译 Android 应用所需的工具和环境。

Node, Watchman

我们推荐使用 Homebrew 来安装 Node 和 Watchman。在命令行中执行下列命令安装:

brew install node
brew install watchman
复制代码

如果你已经安装了 Node,请检查其版本是否在 v8.3 以上。安装完 Node 后建议设置 npm 镜像以加速后面的过程(或使用科学上网工具)

Java Development Kit

React Native 需要 Java Development Kit [JDK] 1.8(暂不支持 1.9 及更高版本)。你可以在命令行中输入

javac -version来查看你当前安装的 JDK 版本。如果版本不合要求,则可以到 官网 下载。

Android Studio 开发环境

如果你之前没有接触过 Android 的开发环境,那么请做好心理准备,这一过程相当繁琐。请 万分仔细地阅读下面的说明,严格对照文档进行配置操作。

注:请注意!!!国内用户必须必须必须有稳定的科学工具,否则在下载、安装、配置过程中会不断遭遇链接超时或断开,无法进行开发工作。某些上网工具可能只提供浏览器的代理功能,或只针对特定网站代理等等,请自行研究配置或更换其他软件。总之如果报错中出现有网址,那么 99% 就是无法正常上网。
如果是 socks5 代理 ,如下这样设置其实并没有什么卵用

#systemProp.socks.proxyHost=127.0.0.1
#systemProp.socks.proxyPort=8016
#systemProp.https.proxyHost=127.0.0.1
#systemProp.https.proxyPort=8016
#systemProp.https.proxyHost=socks5://127.0.0.1
#systemProp.https.proxyPort=8016
复制代码

正确设置方法应该是这样:
org.gradle.jvmargs=-DsocksProxyHost=127.0.0.1 -DsocksProxyPort=8016
修改 $HOME/.gradle/gradle.properties 文件,加入上面那句,这样就可以全局开启 gradle 代理

安装 Android Studio

首先下载和安装 Android Studio。国内用户可能无法打开官方链接,请自行使用搜索引擎搜索可用的下载链接。或者直接点击

安装界面中选择"Custom"选项,确保选中了以下几项:

  • Android SDK
  • Android SDK Platform
  • Performance (Intel ® HAXM) (AMD 处理器看这里)
  • Android Virtual Device

然后点击"Next"来安装选中的组件。

如果选择框是灰的,你也可以先跳过,稍后再来安装这些组件。

安装完成后,看到欢迎界面时,就可以进行下面的操作了。

安装 Android SDK

Android Studio 默认会安装最新版本的 Android SDK。目前编译 React Native 应用需要的是 Android 6.0 (Marshmallow) 版本的 SDK(注意 SDK 版本不等于终端系统版本,RN 目前支持 android 4.1 以上设备)。你可以在 Android Studio 的 SDK Manager 中选择安装各版本的 SDK。

你可以在 Android Studio 的欢迎界面中找到 SDK Manager。点击 "Configure",然后就能看到 "SDK Manager"。

image

SDK Manager 还可以在 Android Studio 的 "Preferences" 菜单中找到。具体路径是 Appearance & Behavior → System Settings → Android SDK

在 SDK Manager 中选择 "SDK Platforms"选项卡,然后在右下角勾选 "Show Package Details"。展开 Android 6.0 (Marshmallow) 选项,确保勾选了下面这些组件(重申你必须使用稳定的上网工具,否则可能都看不到这个界面):

  • Android SDK Platform 28
  • Intel x86 Atom_64 System Image(官方模拟器镜像文件,使用非官方模拟器不需要安装此组件)

然后点击"SDK Tools"选项卡,同样勾中右下角的"Show Package Details"。展开"Android SDK Build-Tools"选项,确保选中了 React Native 所必须的 23.0.1 版本。你可以同时安装多个其他版本,然后还要勾选最底部的 Android Support Repository

image

最后点击"Apply"来下载和安装这些组件。

image

配置 ANDROID_HOME 环境变量

React Native 需要通过环境变量来了解你的 Android SDK 装在什么路径,从而正常进行编译。

具体的做法是把下面的命令加入到 ~/.bash_profile 文件中:

~表示用户目录,即/Users/你的用户名/,而小数点开头的文件在 Finder 中是隐藏的,并且这个文件有可能并不存在。可在终端下使用vi ~/.bash_profile命令创建或编辑。如不熟悉 vi 操作,请点击 这里 学习。

如果你不是通过Android Studio安装的sdk,则其路径可能不同,请自行确定清楚

export ANDROID_HOME=$HOME/Library/Android/sdk  
export PATH=$PATH:$ANDROID_HOME/tools  
export PATH=$PATH:$ANDROID_HOME/platform-tools  
复制代码

如果你的命令行不是 bash,而是例如 zsh 等其他,请使用对应的配置文件。

使用 source $HOME/.bash_profile 命令来使环境变量设置立即生效(否则重启后才生效)。可以使用 echo $ANDROID_HOME 检查此变量是否已正确设置。

请确保你正常指定了 Android SDK 路径。你可以在 Android Studio 的 "Preferences" 菜单中查看 SDK 的真实路径,具体是Appearance & Behavior → System Settings → Android SDK

准备 Android 设备

你需要准备一台 Android 设备来运行 React Native Android 应用。这里所指的设备既可以是真机,也可以是模拟器。Android 官方提供了名为 Android Virtual Device(简称 AVD)的模拟器。此外还有很多第三方提供的模拟器如 Genymotion、BlueStack 等。一般来说官方模拟器免费、功能完整,但性能较差。第三方模拟器性能较好,但可能需要付费,或带有广告。

使用 Android 真机

你也可以使用 Android 真机来代替模拟器进行开发,只需用 usb 数据线连接到电脑,然后遵照 在设备上运行 这篇文档的说明操作即可。

使用 Android 模拟器

你可以在 Android Studi 打开 "AVD Manager" 来查看可用的虚拟设备,它的图标看起来像下面这样:

image

如果你刚刚才安装 Android Studio,那么可能需要先 创建一个虚拟设备。点击"Create Virtual Device...",然后选择所需的设备类型并点击"Next"。

image

选择 "x86 Images" 选项卡,这里可以看到你之前已安装过的镜像文件。必须先安装镜像文件才能创建对应的虚拟设备。

image

如果你还没有安装 HAXM(Intel 虚拟硬件加速驱动),则先按 这篇文档 说明来进行安装。

image

然后点击 "Next" 和 "Finish" 来完成虚拟设备的创建。

搭建 iOS 开发环境

必须安装的依赖有:Node、Watchman 和 React Native 命令行工具以及 Xcode。 虽然你可以使用任何编辑器来开发应用(编写 js 代码),但你仍然必须安装 Xcode 来获得编译 iOS 应用所需的工具和环境。

Node, Watchman

我们推荐使用 Homebrew 来安装 Node 和 Watchman。在命令行中执行下列命令安装:

brew install node
brew install watchman
复制代码

如果你已经安装了 Node,请检查其版本是否在 v8.3 以上。 安装完 Node 后建议设置 npm 镜像以加速后面的过程(或使用上网工具)。

注意:不要使用 cnpm!cnpm 安装的模块路径比较奇怪,packager 不能正常识别!

设置 npm 镜像:

npm config set registry https://registry.npm.taobao.org --global
npm config set disturl https://npm.taobao.org/dist --global
复制代码

或者使用 nrm

$ nrm ls
* npm ----- https://registry.npmjs.org/
cnpm ---- https://r.cnpmjs.org/
taobao -- https://registry.npm.taobao.org/
nj ------ https://registry.nodejitsu.com/
skimdb -- https://skimdb.npmjs.com/registry


$ nrm use cnpm //switch registry to cnpm

Registry has been set to: https://r.cnpmjs.org/
复制代码

Watchman 则是由 Facebook 提供的监视文件系统变更的工具。安装此工具可以提高开发时的性能(packager 可以快速捕捉文件的变化从而实现实时刷新)。

Yarn

Yarn 是 Facebook 提供的替代 npm 的工具,可以加速 node 模块的下载。React Native 的命令行工具用于执行创建、初始化、更新项目、运行打包服务(packager)等任务。

npm install -g yarn
复制代码

安装完 yarn 后同理也要设置镜像源:

yarn config set registry https://registry.npm.taobao.org --global
yarn config set disturl https://npm.taobao.org/dist --global
复制代码

安装完 yarn 之后就可以用 yarn 代替 npm 了,例如用 yarn 代替 npm install 命令,用 yarn add 某第三方库名代替 npm install 某第三方库名。

CocoaPods

CocoaPods 是用 Ruby 编写的包管理器。从 0.60 版本开始 react native 的 iOS 版本需要使用 CocoaPods 来管理依赖。你可以使用下面的命令来安装 cocoapods。

sudo gem install cocoapods
复制代码

或者使用 brew 来安装

brew install cocoapods
复制代码

另外目前最新版本似乎不能在 ruby2.6 版本以下安装,意味着如果你使用的 macOS 版本低于 10.15 (Catalina) 则无法直接安装。可以尝试安装较旧一些的版本。如sudo gem install cocoapods -v 1.8.4
参考 issue 链接  github.com/CocoaPods/C…

要了解更多信息,可以访问 CocoaPods 的官网

Xcode

React Native 目前需要 Xcode 9.4 或更高版本。你可以通过 App Store 或是到 Apple 开发者官网 上下载。这一步骤会同时安装 Xcode IDE、Xcode 的命令行工具和 iOS 模拟器。

Xcode 的命令行工具

启动 Xcode,并在 Xcode | Preferences | Locations 菜单中检查一下是否装有某个版本的 Command Line Tools。Xcode 的命令行工具中包含一些必须的工具,比如 git 等。

image

开发

启动 Metro Bundler Server


$ yarn dev:rn     # 使用 yarn 的方式启动rn(要安装了yarn后)
$ npm run dev:rn  # 使用 npm 的方式启动
$ npm run taro dev:rn --port 8081
$ =====================================================
$ taro build --type rn --watch --port 8081 # 仅限全局安装
$ npx taro build --type rn --watch # npx 用户也可以使用
复制代码

运行上面的命令,Taro 将会开始编译文件,启动本地 Metro Server,如果编译没有报错,会在 8081 端口启动 Metro Bundler(负责打包 jsbundle): Taro 将会开始编译文件.png
这时,在浏览器输入 http://127.0.0.1:8080,可以看到如下页面:
image
image.png 这时,在浏览器输入 https://127.0.0.1:8081/index.bundle?platform=ios&dev=true 会触发对应终端平台的 js bundle 构建。 构建完成后,浏览器会显示构建后的 js 代码

Note:进入下一步之前请确保 Metro Bundler Server 正常启动,即浏览器能正常访问访问 jsbundle。

启动应用

目前支持0.60以上的RN版本, 以及 Taro3 (支持 Taro 3.2.0-beta.4及以上版本,以下版本请使用 0.63.2 版本)

Taro React Native 壳子 和 React Native init 的工程的区别是,移除了 index.js,集成了 react-native-unimodules
如已有原生项目,需自行集成,请参考 react-native-unimodules Readme。

如果上一步的编译和 Metro Bundler Server 启动没问题,接下来就可以启动应用了。

开发者可以自行整合 React Native (0.60+) 到原生应用,同时为了方便大家开发和整合,Taro 将 React Native 工程中原生的部分剥离出来,单独放在一个工程里面 NervJS/taro-native-shell / 0.63.2,你可以把它看成是 React Native iOS/Android 空应用的壳子。

首先将应用代码 clone 下来,放在根目录 下,然后将其名字改为 react-native-shell

git clone git@github.com:NervJS/taro-native-shell.git
git clone https://github.com/NervJS/taro-native-shell.git
复制代码

然后 cd react-native-shell,使用 yarn 或者 npm install 安装依赖。

工程目录如下:

➜  react-native-shell git:(master) ✗ tree -L 1
.
├── LICENSE
├── README.md
├── android     // Android 工程目录
├── ios         // iOS 工程目录
├── node_modules
├── package.json
└── yarn.lock
复制代码

Android

在 taro-native-shell/android 目录下,你就可以看到 React Native 的工程代码。

使用 React Native 命令启动

react-native run-android
复制代码

Android 模拟器会自行启动,并访问 8081 端口获取 js bundle,这时 Metro Bundler 终端会打印一下内容:

BUNDLE [android, dev] ./index.js ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 100.0% (1/1), done.
复制代码

在真实设备上运行

按照以下步骤设置您的设备:

  • 使用一根 USB 电缆将您的设备连接到您的开发机器。如果您是在 Windows 上开发,可能需要为您的设备 安装相应的 USB 驱动程序

  • 按照以下步骤操作,在 Developer options 中启用 USB debugging。 首先,您必须启用开发者选项:

    1. 打开 Settings 应用。
    2. (仅在 Android 8.0 或更高版本上)选择 System。
    3. 滚动到底部,然后选择 About phone。
    4. 滚动到底部,点按 Build number 7 次。
    5. 返回上一屏幕,在底部附近可找到 Developer options。
    6. 打开 Developer options,然后向下滚动以找到并启用 USB debugging。

按照以下步骤操作,在您的设备上运行应用:

  1. 在 Android Studio 中,点击 Project 窗口中的 app 模块,然后选择 Run > Run(或点击工具栏中的 Run )。

2. 在 Select Deployment Target 窗口中,选择您的设备,然后点击 OK

在模拟器上运行

按照以下步骤操作,在模拟器上运行应用:

  1. 在 Android Studio 中,点击 Project 窗口中的 app 模块,然后选择 Run(或点击工具栏中的 Run )。
  2. 在 Select Deployment Target 窗口中,点击 Create New Virtual Device。
  3. 在 Select Hardware 屏幕中,选择电话设备(如 Pixel),然后点击 Next。
  4. 在 System Image 屏幕中,选择具有最高 API 级别的版本。如果您未安装该版本,将显示一个 Download 链接,因此,请点击该链接并完成下载。
  5. 点击 Next。
  6. 在 Android Virtual Device (AVD) 屏幕上,保留所有设置不变,然后点击 Finish。
  7. 返回到 Select Deployment Target 对话框中,选择您刚刚创建的设备,然后点击 OK。

Android Studio 会在模拟器上安装并启动应用

iOS

使用 React Native 命令启动

$ cd ios & pod install
$ cd .. 
$ react-native run-ios
复制代码

⚠️注意: pod install 过程不可省略。

iOS 模拟器会自行启动,并访问 8081 端口获取 js bundle,这时 Metro Bundler 终端会打印以下内容:

BUNDLE  [ios, dev] ./index.js ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ 100.0% (1/1), done.
复制代码

使用 Xcode 启动

iOS 的启动比较简单,使用 Xcode 打开 ios 目录,然后点击 Run 按钮就行。 这里需要注意的是 jsBundle 的 moduleName,默认的 moduleName 为 "taroDemo",需要和 config/index.js 里面配置 rn 的 appName 字段保持一致。

const config = {
  ...
  rn: {
    appName: 'taroDemo',
  }
  ...
}
复制代码

该配置在 AppDelegate.m 文件中。

#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

#import <UMCore/UMModuleRegistry.h>
#import <UMReactNativeAdapter/UMNativeModulesProxy.h>
#import <UMReactNativeAdapter/UMModuleRegistryAdapter.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>

static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

@interface AppDelegate () <RCTBridgeDelegate>
 
@property (nonatomic, strong) UMModuleRegistryAdapter *moduleRegistryAdapter;
 
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#ifdef FB_SONARKIT_ENABLED
  InitializeFlipper(application);
#endif
  
  self.moduleRegistryAdapter = [[UMModuleRegistryAdapter alloc] initWithModuleRegistryProvider:[[UMModuleRegistryProvider alloc] init]];

  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"taroDemo"
                                            initialProperties:nil];

  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  [super application:application didFinishLaunchingWithOptions:launchOptions];
  return YES;
}

- (NSArray<id<RCTBridgeModule>> *)extraModulesForBridge:(RCTBridge *)bridge
{
    NSArray<id<RCTBridgeModule>> *extraModules = [_moduleRegistryAdapter extraModulesForBridge:bridge];
    // If you'd like to export some custom RCTBridgeModules that are not Expo modules, add them here!
    return extraModules;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}
@end
复制代码

更多资料,可以查看 Xcode 文档:Building Your App

现有问题

部分应用对包大小敏感,觉得集成 react-native-unimodules 后包大小增加太多。

可以通过配置 exclude 您不需要的包:use_unimodules!(exclude: [‘expo-face-detector’])addUnimodulesDependencies([exclude: ['expo-face-detector']])

具体可以参考:Reducing App Size In Future?

安卓应用闪退并报错:java.lang.NoSuchMethodError: No static method loadLibrary(Ljava/lang/String;)V in class Lcom/facebook/soloader/SoLoader; or its super classes
参考:github.com/NervJS/reac…

react-native run-android 的时候提示红字:找不到 index.android.bundle
保证在手机电脑在同一局域网,然后运行一下:adb reverse tcp:8081 tcp:8081,然后重新运行。

iOS 报错:_reactNative.UIManager.getViewManagerConfig is not a function
参考:github.com/NervJS/reac…

react-native 在新版 Xcode(10+)中运行出现的常见问题
参考:github.com/NervJS/taro…

文章分类
前端
文章标签