由于 RN 横跨多个技术栈,所以把它跑起来反而成了难事。
要研究一项技术,最怕 “顺利运行起来” 这么起码的事都成为逾越不过去的障碍,相信很多同学根据官方 Setting up the development environment · React Native 文档操作,未能顺利启动项目,对之前纯 Web 前端的工程师来说,应该是很大概率的。
能够顺利运行 RN 项目后,即使没法儿走通完整的工作流闭环,如不会打包、推送到应用商店等等,也能够搞明白其中组件、API、架构一类,那时 “走通工作流闭环” 也成了顺其自然的事儿。
本文囊括了大体的 React Native 工作流闭环:项目环境、创建、启动、调试、打包、安装。
没有相关痛苦经历的同学,请帮忙检阅这篇文章,权当作温故罢了。😜
使用最新版 React Native 搭建 iOS 项目参见《最新版 React Native iOS 项目搭建纪实》。
本文如果没能帮你成功搭建、启动 RN Android 项目,无论是 Intel 芯片或者 Apple Silicon(M1 / M2)芯片的电脑,加我微信(8 个 "欧"):iyoooooooo,拉你入群一起交流。避免一万个哈姆雷特的问题,正好查漏补缺,继续完善这篇文章。
第一阶段:环境
下述环境是可以成功运行项目的,供参考、检查。RN 项目搭建的关键也在于环境。
macOS
macOS Monterey 12.6.1(Intel)
网络
全局科学上网,最好是千兆网速。
react-native
react-native v0.70.6 @react-native-community/cli v9.3.2
Package Manager
npm v9.1.2,JavaScript 包管理器。推荐 NPM + PNPM。参阅《pnpm 是凭什么对 npm 和 yarn 降维打击的》。
OpenSSL@1
export LDFLAGS=“-L/usr/local/opt/openssl@1.1/lib”
export CPPFLAGS=“-I/usr/local/opt/openssl@1.1/include”
export PATH=“/usr/local/opt/openssl@1.1/bin:$PATH”
这个版本完全是为了安装需要 OpenSSL@1 系列的软件准备的,可以通过 Homebrew 安装 OpenSSL@1 系列最新版本,但需要在 ~/.bashrc
中暴露上述环境变量,如果使用了 ZSH,在 ~/.zshrc
中设置即可。注意,路径中的 “openssl@1.1”,替换为自己系统中实际的名称,可以到 /usr/local/opt
根目录查找。
执行 exec $SHELL
重载命令行会话后,运行 openssl version -d
可获取 openssl 配置文件的位置。想要获取其它信息,运行 openssl version -help
即可,会输出如下提示,
Usage: version [options]
Valid options are:
-help Display this summary
-a Show all data
-b Show build date
-d Show configuration directory
-e Show engines directory
-f Show compiler flags used
-o Show some internal datatype options
-p Show target build platform
-r Show random seeding options
-v Show library version
OpenSSL@3
使用 Homebrew 安装(brew install openssl@3
)。
这个版本并不需要配置到环境变量中,只是在构建项目时,有些模块会用到,比如,
可以忽略这里的图示是 Xcode,而非 Android Studio,注意关键点:有些模块可能会用到 openssl@3。
防止有其它场景需要将它配置到环境变量中,所以这里也将配置方式贴出来,注意,使用 Bash 就在 ~/.bashrc
中暴露环境变量,如果使用了 ZSH,在 ~/.zshrc
中设置即可,
openssl@3 is keg-only, which means it was not symlinked into /usr/local,
because macOS provides LibreSSL.
If you need to have openssl@3 first in your PATH, run:
echo 'export PATH="/usr/local/opt/openssl@3/bin:$PATH"' >> ~/.zshrc
For compilers to find openssl@3 you may need to set:
export LDFLAGS="-L/usr/local/opt/openssl@3/lib"
export CPPFLAGS="-I/usr/local/opt/openssl@3/include"
版本管理器
具体安装方式见各自官网。
nvm 0.39.1,Node 版本管理器。
运行时
“node v18.12.1”,使用 NVM 安装,安装后的位置在 $HOME/.nvm/versions/node/v18.12.1/bin/node
,可以通过 which node
指令检查,另外软链(ln -s $(which node) /usr/local/bin
)到 /usr/local/bin/node
位置,防止构建 iOS 应用时有些包需要使用到这个软链。
“openjdk 11.0.17 2022-10-18 LTS”,使用 Homebrew 安装,不推荐手动安装。
Android SDK
通过 Android Studio IDE 安装 Android SDK 是比较便利的,启动 Android Studio,点击下图图示菜单即可进入 SDK、NDK 管理界面,
注意,在接下来初始化的项目中,./android/build.gradle
文件声明了需要的 Android SDK 版本,
buildscript {
ext {
buildToolsVersion = "31.0.0"
minSdkVersion = 21
compileSdkVersion = 31
targetSdkVersion = 31
if (System.properties['os.arch'] == "aarch64") {
// For M1 Users we need to use the NDK 24 which added support for aarch64
ndkVersion = "24.0.8215888"
} else {
// Otherwise we default to the side-by-side NDK version from AGP.
ndkVersion = "21.4.7075529"
}
}
repositories {
google()
mavenCentral()
}
dependencies {
classpath("com.android.tools.build:gradle:7.2.1")
classpath("com.facebook.react:react-native-gradle-plugin")
classpath("de.undercouch:gradle-download-task:5.0.1")
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
所以,通过 Android Studio 下载的 SDK、NDK,它们的版本至少不要比 ./android/build.gradle
文件中声明的版本低。
本文这一步还看不到这份文件,因为项目还没初始化。这份文件来自 React Native 0.70.6。
为了快速操作,直接按照下述列表操作即可,
- SDK Platforms > Android 12.0(S) API Level 31 Revision 1
- SDK Tools > Android SDK Bild-Tools 31.0.0
- SDK Tools > NDK > 最新版本
- SDK Tools > Android SDK Command-line Tools 8.0 (或最新版本)
- SDK Tools > Android Emulator 31.3.13 (或最新版本)
- SDK Tools > Android SDK Platform-Tools 33.0.3 (或最新版本)
确保这些都选中后,点击 “Apply” 即开始下载、安装。注意,最好是在科学上网环境下。
但 Android Studio 不会帮忙设置环境变量 ANDROID_SDK
、ANDROID_SDK_ROOT
、ANDROID_HOME
、ANDROID_NDK
、NDK_HOME
等,需要手动设置一下,在 ~/.bashrc
中暴露下述环境变量,如果使用了 ZSH,在 ~/.zshrc
中设置即可。
# android sdk
export ANDROID_SDK=$HOME/Library/Android/sdk
export ANDROID_SDK_ROOT=$HOME/Library/Android/sdk
export ANDROID_HOME=$HOME/Library/Android/sdk
export PATH=$PATH:$ANDROID_HOME/emulator
export PATH=${PATH}:${ANDROID_HOME}/tools
export PATH=${PATH}:${ANDROID_HOME}/tools/bin
export PATH=$PATH:$ANDROID_HOME/platform-tools
# android ndk
export ANDROID_NDK=/Users/iyowei/Library/Android/sdk/ndk/25.1.8937393
export NDK_HOME=/Users/iyowei/Library/Android/sdk/ndk/25.1.8937393
编辑器
Android Studio Dolphin | 2021.3.1 Patch 1,对 RN 项目构建、打包、修改原生部分等,在 Android Studio 中操作。
Visual Studio Code,平常修改 React 相关代码,也是主要的工作位置。
模拟器
可以按图示创建安卓模拟器。
注意!SDK 使用 v31 的话,模拟器系统也得使用 >= V31 的 Android API。建议多创建几个模拟器,使用不同版本的 Android API。
待接下来项目创建好之后,可以在项目根目录运行 npx react-native info
检查 RN 可识别出来的 SDK 及版本。
其它
具体安装方式见官网。
Watchman 2022.11.14.00,使用 Homebrew 安装即可。
第二阶段:初始化项目
初始化项目前,确保当前系统应用了上述环境,一一检查一遍,否则创建项目环节就会失败,比如,初始化项目时会检查。
使用 npx react-native init --npm joker
指令初始化初始化项目。这里强制使用 NPM 包管理器,如此不破坏 npm 使用习惯,不会引入新的学习成本,如果不介意学习成本,可以无障碍引入比 Yarn 性能更好的包管理器:PNPM。参阅《pnpm 是凭什么对 npm 和 yarn 降维打击的》。
目前并不会对项目内容做过多修改,重心:成功运行起来。
第三阶段:启动项目前准备工作
检查开发环境
进入项目根目录,执行 npx react-native doctor
指令主动检查开发环境,
Common
✓ Node.js
✓ npm
✓ Watchman - Used for watching changes in the filesystem when in development mode
Android
✓ JDK
✓ Android Studio - Required for building and installing your app on Android
✓ Android SDK - Required for building and installing your app on Android
✓ ANDROID_HOME
iOS
✓ Xcode - Required for building and installing your app on iOS
✓ CocoaPods - Required for installing iOS dependencies
● ios-deploy - Required for installing your app on a physical device with the CLI
✓ .xcode.env - File to customize Xcode environment
如果有问题,可以根据指令的提示自动修复开发环境。
最后,运行 npx react-native info
输出开发环境信息,再确认一遍,
System:
OS: macOS 12.6.1
CPU: (8) x64 Intel(R) Core(TM) i7-4870HQ CPU @ 2.50GHz
Memory: 265.16 MB / 16.00 GB
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 18.12.1 - ~/.nvm/versions/node/v18.12.1/bin/node
Yarn: 1.22.10 - ~/.nvm/versions/node/v18.12.1/bin/yarn
npm: 9.1.2 - ~/.nvm/versions/node/v18.12.1/bin/npm
Watchman: 2022.11.14.00 - /usr/local/bin/watchman
Managers:
CocoaPods: 1.11.3 - /Users/iyowei/.rvm/gems/ruby-2.7.5/bin/pod
SDKs:
iOS SDK:
Platforms: DriverKit 22.1, iOS 16.1, macOS 13.0, tvOS 16.1, watchOS 9.1
Android SDK:
API Levels: 31
Build Tools: 30.0.3, 31.0.0
System Images: android-31 | Google APIs Intel x86 Atom_64
Android NDK: 25.1.8937393
IDEs:
Android Studio: 2021.3 AI-213.7172.25.2113.9123335
Xcode: 14.1/14B47b - /usr/bin/xcodebuild
Languages:
Java: 11.0.17 - /usr/bin/javac
npmPackages:
@react-native-community/cli: Not Found
react: 18.1.0 => 18.1.0
react-native: 0.70.6 => 0.70.6
react-native-macos: Not Found
npmGlobalPackages:
*react-native*: Not Found
都符合预期,才可以继续推进。
启动模拟器
这是安卓模拟器的启动方式之一,从 Android Studio 启动界面操作,点击设备管理窗口里具体模拟器的 “播放” 按钮即可运行模拟器,
安卓模拟器启动成功(即:模拟器的系统已成功开机)后,在命令行运行 adb devices
指令检查是否识别到了这个模拟器。一般是没有问题的。
其实也可以不预先启动模拟器,只是节省时间而以,如果不在乎这点时间损耗,也可以直接跳过这一步。
这是在打开项目后的 Android Studio 中启动、切换模拟器或真机设备的位置。
启动 Metro
待模拟器启动成功后,进入项目根目录,在单独的命令行会话中,执行 npx react-native start
指令启动 Metro 服务。
强烈建议手动启动 Metro 服务,虽然 RN 项目在启动时会自动化这个操作,但是失败的情况是会有的。
第四阶段:启动项目
准备好了开发环境,模拟器也打开了,启动好了 Metro,都没问题,就可以启动项目。
推荐用 Android Studio IDE 构建、运行项目,而非命令行。
启动 Android Studio,打开项目中 android 根目录即可。Android Studio 会自动识别项目启动方式,并选择一款已经创建好的模拟器,这些可以在右上角工具栏看到。
注意,此时千万不要直接运行项目,否则模拟器中会报错,并且在 Logcat 栏目中看到如下报错,根据接下来的步骤操作即可,
- 先停止调试;
- 停止 Metro 服务;
- 再运行
npx react-native clean --include 'android,metro,watchman'
; - 在命令行中运行
adb reverse tcp:8081 tcp:8081
指令,导通模拟器与 Metro 服务之间的流量; - 重启 Metro 服务;
- 重新启动项目;
这时候才能顺利运行项目。
不推荐通过命令行(npx react-native run-android --port 8081
)的方式运行项目,缘由目前是我自己猜的:某些文件的编译由 IDE 来负责,而非命令行,前者的权限能做更多命令行不能及的事。另外,上手 RN 项目的纯前端同学对原生部分不太了解,原生相关的事让 IDE 操作,会得多。
一般来说,Android Studio 在 RN 开发活动中,就是充当了构建、发布、编辑原生代码的作用,实际编写 React 的过程还是在 VS Code 这类编辑器中。
之后,第二次启动,或是开发中的不停重启,推荐先前清理缓存再启动应用,
npx react-native clean --include 'android,metro,watchman'
清理 Android 构建、Watchman 缓存、Metro 缓存;- 清空模拟器数据,参见下图;
模拟器出现异常,可清理模拟器缓存,或者直接删除模拟器好了,重建。
如果需要让项目从全新的状态重新来过,除了要完成上述清理缓存的事情,还可以将 android、metro、watchman、npm 的缓存以及后两者安装的依赖全部清空,之后再重新安装,
npx react-native clean --include 'android,metro,npm,watchman,yarn'
;npm i
/yarn install
,看项目使用的是哪一款;
清缓存到了这一步,不妨重启系统后,再运行项目,🤪。
第五阶段:Flipper 调试
Flipper 不仅提供了 JS 的调试工具,还集成了 react-devtools、网络监测、崩溃监测、模拟器管理等工具。如果只是调试 JS 的话,也可以使用借助 Google Chrome 开发者工具实现,这里不赘述,因为操作很简单。
Flipper 需要单独安装,但是使用它还需要配置一下环境:fb-idb、OpenSSL。
安装 fb-idb 前需要先部署好 Python >= 3.6 环境,实测安装最新 Python 也是可以的。推荐使用 pyenv 安装 Python,这是 Python 的版本管理工具。pyenv 的安装方式具体参见 官方文档。
前面的开发环境也提到了 OpenSSL,Flipper 直接沿用,但是可能会报 “Can’t open /usr/lib/ssl/openssl.cnf” 错误,一般是因为不存在这个文件,创建它就好了。先查找(find / -iname openssl.cnf
)系统内其它位置有没有 openssl.cnf 文件,有的话复制到 /usr/lib/ssl/openssl.cnf
,没有的话,就拷贝 OpenSSL 项目里的 openssl.cnf 文件模板。
现在启动 Flipper,打开的界面上可能会报一些警告。暂时先不管这些。找到 Flipper 左下角,顺序 “点击左下角设置按钮 -> Settings” 操作打开如下界面,并按照下图所示配置 Flipper。IDB 可执行未见的位置通过 which idb
指令获得。设置好之后,点击 “Apply and Restart” 即可。
重启 Flipper 后,点击左下角 “Seup Doctor” 按钮(图标按钮,鼠标放上去就可以看到提示),检查 Flipper 的运行环境是否准备妥当,全部通过的话,如下图所示。
到这里,可以开始正常使用 Flipper 了。一般来说,先启动项目的 Metro 服务,再打开 Flipper,Flipper 会立马识别出来虚拟机或真机设备,之所以能够识别,就是因为 fb-idb 的作用:链接 iOS 与 Flipper 的桥梁。
第六阶段:真机调试
首先,将手机开启开发者模式。不同的安卓手机,菜单位置不同,菜单名称也不太一样,可能是 “开发者选项”、“开发者模式”、“开发者”,所以直接进入设置程序,搜索 “开发者” 关键字即可。进入 “开发者” 菜单后,将 USB、WIFI 两种调试方式都启用。
连接手机、Android Studio 的方式有俩:有线、WIFI。
确保手机启用开发者模式,电脑上 Android Studio 是打开的,用数据线连接后,Android Studio 会识别出来,并显示在设备列表中。
WIFI 会有个扫码配对的过程,根据二维码底部的提示按步骤操作即可找到安卓手机内 “使用二维码配对设备” 菜单的位置,其实就在 “无线调试” 菜单内。
配对成功后,直接显示在设备列表中,并且自动选中。
注意,先不要点击 “启动” 按钮。
在真机调试前,无论有线、无线,有两件事要先准备好,才会顺利在真机上运行应用,模拟器调试也是,
- 启动 Metro 服务;
- 在单独的命令行会话中执行
adb reverse tcp:8081 tcp:8081
,从设备转发请求到电脑上的 Metro 服务;
这两件事完成了,点击 “启动” 按钮,配合 Flipper 一起使用,即可开始真机调试。
第七阶段:生成安装包
如果只是生成一个调试用安装包,找到 Android Studio 菜单栏,顺序操作 “Build -> Build Bundle(s) / APK(s)… -> Build APK(s)”,然后等待构建成功,右下角会有个气泡提示打包成功,并提供了打开安装包位置的按钮。
如果要打包一个正式安装包 / 发行包,会多个生成签名秘钥的过程。
先在项目 ./android/app/
目录下生成签名秘钥,
keytool -genkeypair -v -storetype PKCS12 -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
这条命令会要求你输入密钥库(keystore)和对应密钥的密码,然后设置一些发行相关的信息,都是接下来为应用签名时要用到的。生成秘钥的位置可以不在 ./android/app/
中。
签名配置,包括密码,都可以在 Gradle 配置文件中明文声明,官方文档 提供了配置的方式,但本文不采用这种做法,还是通过编辑器以非明文的方式配置。
用 Android Studio 打开项目中的 “./android” 目录。并且将文件树栏目切换为 “Project” 模式。
找到 Android Studio 菜单栏,顺序操作 “Build -> Generate Signed Bundle / APK…”,此时会打开如下弹窗,
生成发行 AAB 包,就选择 “Android App Bundle”,生成安装包,就选择 APK。本文选择生成 APK。两者接下来的操作是可以相互沿用的。点击下一步,会要求提供签名秘钥,
将刚才执行秘钥生成指令中的信息、输入的密钥库(keystore)和对应密钥的密码填入对话框即可。
点击下一步,在 “Build Variants” 里选中 “release”,
点击完成,等待构建成功,右下角会有个气泡提示打包成功,并提供了打开安装包位置的按钮。关闭气泡,还可以在右下角 EventLog 窗体里看到。
点击 “lacate” 文字按钮,打开安装包位置,
把这个安装包发送到手机上即可安装。注意,上次安装和下次安装各使用了不同的秘钥,这样会导致秘钥冲突,一定要保持秘钥一致。
RN 提供了命令行的打包方式,参见 官方文档,但同 “第四阶段:启动项目” 保持一致,推荐使用 Android Studio 编辑器提供的方式打包。
结语
到这里,大体的工作流闭环就走完了:项目环境、创建、启动、调试、打包、安装。“发布到应用商店” 的部分,本文暂不赘述。
RN 技术中虽然使用 React 那一套来开发界面,但为了不牺牲原生样式、体验,并且确保真正原生渲染,这导致底层渲染界面的原理、实现方式与浏览器不同,所以不能期望 RN 的开发方式会和 Web 开发完全一致,一定会有出入。在正式投入开发前,需要提前认识到这一点,不要 Web 的那一套牵绊,站在原生的角度,重新学习那些组件怎么使用、样式怎么编写、有哪些特性兼容性问题等等。
Facebook 对 RN 的 严重依赖,以及越来越多的重要科技巨头 使用 它,意味着 RN 将在可预见的未来继续蓬勃发展。
附言一
打算将我的笔记都以文章的形式发布出来,与大家分享,更多(80%)还是想交流,集思广益,另外也想结识些志趣相投的新朋友,好朋友,🫵🏼,我知道你就在那儿,快联系我吧!😬(微信:iyoooooooo)