Taro React Native 重大更新来了,全方位降低上手成本,提升开发体验。全流程自动化,让开发者摆脱原生环境配置,专注前端开发。
背景
Taro 3.2.0 正式版本发布至今,已过去半年。在此期间,有不少社区开发者已经使用上 Taro 来开发 APP 了。看到社区的使用量越来越多,开发团队也是收获满满。
同时我们也收到了很多来自开发者的反馈,主要集中于开发环境配置复杂、组件和 API 的完善度不够及使用上的 BUG 等。对于组件和 API 的完善度及使用上的 BUG,我们都是尽可能地及时地处理并发布新版本。然而,对于开发者反馈的开发环境配置的问题,却很难复现及解决。
首先 Android + iOS + React Native + Taro,4个技术的各种环境配置,会让很多开发者望而却步。其次开发者面对的环境问题千奇百怪,很多问题难以通过远程协助解决。不少开发者在调研阶段,因为无法顺利运行,便放弃了使用。对于一个跨平台框架来说,主要目的是提效,而非给开发者带来更多困难。开发环境配置问题的解决,显得尤为重要。
这次我们从以下三个方向去优化整个开发流程,全面降低上手成本,让 Taro 开发 APP,变得无比轻松。
- 为 Taro 提供 react-native 模板,项目的初始化,只需要几个命令。
- 与 GitHub Actions 进行集成,不再需要本地安装原生开发环境,打包及发布交给 CI 去做。
- 提供 Taro Playground APP,可以通过应用商店或者 GitHub 下载安装,进行项目调试。
react-native 开发模板
目前使用 Taro 开发 React Native APP 时,我们需要一个原生壳工程,在另外一个仓库[1]。对于新手来说,通常会造成一些困惑:
- 没有接触过 React Native 开发的开发者首先需要理解 React Native 的开发流程,然后完成两个仓库的初始化。
- 两个仓库都需要安装依赖,并且需要保持某些依赖版本的一致性。当有依赖更新时,需要在两个仓库中进行操作,非常容易遗漏。
- 项目依赖原生的运行环境。开发者经常遇到安装过程报错,无法运行的场景。一些依赖包的下载需要切换源或依赖特定网络环境。
这些问题对新手入门很不友好,为此我们提供了一个初始化模板[2]。初始化项目使用 taro init [project]
选择 react-native 模板。
初始化完成后,便可使用进入开发。以下为一些常用命令:
# 更新相关依赖。在初始化完成后或 Taro 版本更新后执行,用于同步 peerDependencies。
$ yarn upgradePeerdeps
# 打包 js bundle 及静态资源。在初始化完成后执行,用于打包默认使用的 bundle。
$ yarn build:rn --platform ios
# 启动 bundle server
$ yarn start
# 启动 iOS
$ yarn ios
# 启动安卓
$ yarn android
具体操作可以查看录屏:
通过模板方式进行初始化的项目,有几个优势:
- Taro 仓库与壳工程仓库进行整合,不再需要管理双仓库。当然习惯双仓库模式的开发者,仍然可以正常使用。
- 当 Taro 进行升级时,可以通过执行
yarn upgradePeerdeps
进行依赖同步。这里我们将 Taro 依赖的 React Native 相关库写入了 peerDependencies 中,然后通过 install-peerdeps 去完成依赖的同步。 - 集成了 GitHub Actions,可通过 workflow 完成 APP 的打包。
GitHub Actions
要解决开发环境的各种问题,通常的做法就是提供一个稳定的环境用于打包发布,在企业里是各种 CI/CD 平台。但对于开源项目来讲,就需要一个公开的平台,每个人都能使用,当然最好是免费的。于是我们想到了 GitHub Actions。
GitHub Actions 是 GitHub 提供的持续集成服务,于 2018 年 10 月推出。功能非常强大,并且免费(每月有限额),同时私有仓库也能够使用,非常契合我们的需求。
通过模板初始化的项目,可在 .github/workflows
目录中看到 4 个文件。分别为 iOS 和 Android 的 release 包和 debug 包的打包工作流。模板为了简化过程,设置为通过 git push
即可触发打包,可根据自身情况,配置合适自身业务场景的工作流。打包生成的产物可以在 Artifacts 中找到,也可以使用 softprops/action-gh-release@v1
action,将产物发布到项目的 Release 中。
这样一来新手便可以不需要关注原生环境以及 APP 打包的问题。开发时,可以安装 debug 包加载本地的 jsbundle,进行调试。发布时,交给 CI 进行打包,产物再提交到应用市场,整个过程完全不需要 AS 与 XCode。当然这里还有一些必要配置需要做,比如 APP 的签名等,将在后面的章节讲解。
GitHub Actions 功能非常强大,Taro 就用它来做打包发布等工作,可参考文档[3]或查看资料做进一步探索,做点有趣的事情。
GitHub Actions 配置
在 Taro 项目模板里面我们提供了一个 CI 脚本模板,开发者仍然需要进行一些配置,才能够开始打包。下面是打包 Android APP 的基础配置说明,iOS 同理:
配置打包的环境变量
env:
APP_ID: com.taro.demo # 应用 ID
APP_NAME: Taro Demo # 应用名称
VERSION_NAME: 1.0.0 # 应用版本号
VERSION_CODE: 10 # 用于应用市场、程序内部识别版本,判断新旧版本,一般递增处理
KEYSTORE_FILE: debug.keystore # 签名文件
KEYSTORE_PASSWORD: android # 密码
KEYSTORE_KEY_ALIAS: androiddebugkey # 别名
KEYSTORE_KEY_PASSWORD: android # 别名的密码通过 github secrets 管理秘钥配置
通常我们不应该把密钥等敏感信息直接写在配置文件中,而是置于加密信息中。在 GitHub Actions 中,可以使用加密机制进行处理[4]。如图,在
setting
->secret
配上 CI 需要的 secret。然后在 workflow 中通过相应变量进行使用,如${{secrets.DEBUG_KEYSTORE_PASSWORD}}
。
壳工程 GitHub Actions 方案
对于壳工程与项目工程分开的场景,利用 CI 命令将两个项目进行合并也可以实现打包自动化。具体流程如下:
壳工程和业务项目合并
因为 GitHub Actions 只能在当前项目下进行操作,所以需要将壳工程(taro-native-shell)合并到项目工程下。
合并项目和壳工程的 package.json
在有原生依赖的情况下,必须保证壳工程和业务项目的原生依赖版本一致,不然打包可能会报错。
安装依赖
在业务项目工程下安装合并后的 package.json 依赖。
软链依赖
将安装到业务项目下的依赖软链至壳工程项目 node_module 下。
ln -s ./node_modules ./taro-native-shell/node_modules
业务项目编译
执行
taro/cli build:rn
编译命令,打包生成 jsbundle 与静态资源。将编译产物移动到原生壳工程
rn: {
appName: 'taroDemo',
output: {
ios: './ios/main.jsbundle',
iosAssetsDest: './ios',
android: './android/app/src/main/assets/index.android.bundle',
androidAssetsDest: './android/app/src/main/res',
iosSourcemapOutput: './ios/main.map',
androidSourcemapOutput: './android/app/src/main/assets/index.android.map',
},
}taro 编译 rn 输出静态资源,需要将资源移到原生项目中。
编译原生 APP
到 ios 和 android 目录里分别执行对应的打包命令。
上传 APP
将打包后的 APP 进行上传,提供下载链接。
# iOS
- name: Upload iOS Products
uses: actions/upload-artifact@v2
with:
name: app-${{ env.BUILD_TYPE }}
path: |
${{ github.workspace }}/ios/taroDemo.ipa
${{ github.workspace }}/ios/taroDemo.app.dSYM.zip# Android
- name: Upload Android Products
uses: actions/upload-artifact@v2
with:
name: app-${{ env.BUILD_TYPE }}
path: ${{ github.workspace }}/android/app/build/outputs/apk/${{ env.BUILD_TYPE }}/app-${{ env.BUILD_TYPE }}.apk在 iOS 侧,release workflow 还集成了上传至 APP Store 命令:
- name: Upload app to App Store Connect
env:
APP_STORE_CONNECT_USERNAME: ${{ env.APP_STORE_CONNECT_USERNAME }}
APP_STORE_CONNECT_PASSWORD: ${{ env.APP_STORE_CONNECT_PASSWORD }}
run: |
cd ios
xcrun altool --upload-app -t ios -f "taroDemo.ipa" -u "$APP_STORE_CONNECT_USERNAME" -p "$APP_STORE_CONNECT_PASSWORD"
上面整个流程对于开发者来说理解成本太高,配置过于繁琐,所以我们将前 6 个步骤封装成一个 GitHub action[5],开发者只需要添加一些配置项就能完成上面的流程。
- name: taro-native-publish
uses: shinken008/taro-native-publish@0.4.0
with:
REPO: ${{ env.SHELL_REPO }}
REPO_REF: ${{ env.SHELL_REPO_REF }}
REPO_PATH: taro-native-shell
BUILD_CMD: yarn build:rn
IOS_BUNDLE: ios/main.jsbundle
IOS_ASSETS: ios
ANDROID_BUNDLE: android/index.android.bundle
ANDROID_ASSETS: android
PLATFORM: android
对应的需要拉取的另一个仓库的配置:
env:
# 壳工程
SHELL_REPO: NervJS/taro-native-shell
# 壳工程ref
SHELL_REPO_REF: 0.63.2
# 壳工程目录
SHELL_REPO_PATH: taro-native-shell
配置介绍:
- REPO: 壳工程地址
- REPO_REF: 壳工程分支
- SHELL_REPO_PATH: 壳工程目录
- IOS_BUNDLE: 编译 iOS 后的 js bundle 地址
- IOS_ASSETS: 编译 iOS 后的其他静态文件(图片等)地址
- ANDROID_BUNDLE: 编译 Android 后的 js bundle 地址
- ANDROID_ASSETS: 编译 Android 后的其他静态文件(图片等)地址
- PLATFORM:编译的目标平台 ios/android
模板提供的 iOS 打包方案
iOS APP 的打包过程相对繁琐,这里我们直接使用了一个优秀的工具 fastlane[6]。fastlane 是一个为 iOS 和 Android 开发者提供的工具,可以自动执行繁琐的任务,如生成屏幕截图、处理配置文件和发布应用程序。
打包过程中的 info plist 文件修改、版本号修改、签名设置都可以交给 fastlane 去处理,经过 fastlane 的封装,开发者处理这些繁琐的任务,只需要添加几行配置即可。
但是要让 fastlane 在 GitHub Actions 使用,还需要几步操作。因为证书(Certificate)与描述文件(Provisioning Profiles)并不存储在项目仓库中,而每次工作流都是发生在随机的主机上的,这就需要我们在打包前,先将证书与描述文件导入到当前主机中。
Release 证书的导入过程如下:
将证书的
p12
文件转成base64
字符串。cat Certificates.p12 | base64 | pbcopy
将第一步内容保存在项目的
secret
中,key
为RELEASE_SIGNING_CERTIFICATE_P12_DATA
将
p12
文件的密码保存在项目的secret
中,key
为RELEASE_SIGNING_CERTIFICATE_PASSWORD
将
secret
内配置的相关信息导入到主机中。security import <(echo $SIGNING_CERTIFICATE_P12_DATA | base64 --decode) \
-f pkcs12 \
-k build.keychain \
-P $SIGNING_CERTIFICATE_PASSWORD \
-T /usr/bin/codesign
描述文件的导入过程,与证书的导入过程类似,均已封装在 workflow 中。
要将生成的 ipa 文件上传至 testflight 或者 APP Store 上,还需要提供用户名(APP_STORE_CONNECT_USERNAME)与密码(APP_STORE_CONNECT_PASSWORD),可参考文档进行生成[7]。
至于证书与描述文件的生成,可查阅 iOS 开发相关文章[8],这里不再赘述。fastlane 配置的更多细节可查看 ios/fastlane/Fastfile
文件。
模板提供的 Android 打包方案
Android 的打包过程相对简单,直接调用 gradlew
命令即可。除了配置 APP 的基础信息,还需要为应用进行签名。可参考 Android 应用签名相关文档[9],生成签名文件,置于 android/app
目录中。
签名文件也可通过命令行工具生成:
keytool -genkey -alias android -keyalg RSA -validity 99999 -keystore release.keystore
打包相关参数,通过 gradlew
的 -P, --project-prop
参数进行传入,如 ./gradlew assembledebug -Papp_id=${{ env.APP_ID }}
,其默认值在 android/gradle.properties
文件中定义。
Taro Playground APP
基于 GitHub Actions 与 Taro 模板,我们完成了项目初始化与打包过程的自动化。但对于想要体验 Taro 开发 APP 的开发者来说,仍然太过繁琐。为此,我们开发了 Taro Playground APP,并完全开源[10]。一方面可以展示组件和 API 的使用示例,另一方面提供了动态加载 jsbundle 的功能,便于开发人员进行本地代码的调试。
本地调试
开发者可以在 Taro Playground 仓库的 Releases 页面进行安装包下载[11],也可扫描以下二维码安装 APP。
Android | iOS |
---|---|
Taro 工程中通过 yarn dev:rn --qr
启动 bundler server,打印包含 IP 及端口信息的二维码。通过 Taro Playground APP 扫描该二维码,即可加载 jsbundle 进行调试,需要保证手机与电脑处于同一个局域网中。
具体操作可以查看录屏:
示列代码
Taro Playground 项目提供了较全面的示例代码,开发者可以参考,避免一些可能遇到的坑,如有问题,欢迎 pr。
总结
通过上述多方面的优化,极大地降低了使用 Taro 开发 APP 的成本。大部分场景下,只需要掌握 Taro 和 React Native,再加上一些配置,即可完成 APP 的开发与发布。
使用过程中,如遇任何问题,可添加 "58技术小秘书" 或 "Taro 小助手" 为好友,备注 "Taro RN",加入官方交流群寻求帮助。
后续,我们还将带来支持 React Native 的 Taro UI 以及包含详细教程的技术小册,尽请期待。
同时我们也在征集社区优秀使用案例,欢迎开发者提交案例到案例仓库中[12]。
相关链接
[1] 壳工程地址:https://github.com/NervJS/taro-native-shell
[2] 模板源码地址:https://github.com/NervJS/taro-project-templates/tree/v3.4/react-native
[3] GitHub Action 文档:https://docs.github.com/cn/actions
[4] GitHub Action 加密机制:https://docs.github.com/cn/actions/reference/encrypted-secrets
[5] Taro React Native Publish Action:https://github.com/shinken008/taro-native-publish
[6] fastlane官网:https://docs.fastlane.tools
[7] AppleID 密码生成:https://support.apple.com/en-us/HT204397
[8] 使用 GitHub Action 发布 iOS 应用:https://betterprogramming.pub/deploy-an-ios-app-to-testflight-or-the-app-store-using-github-actions-c4d7082b1430
[9] 安卓签名文件生成:https://developer.android.com/studio/publish/app-signing#generate-key
[10] Taro Playground 源码:https://github.com/wuba/taro-playground
[11] Taro Playground APP 下载:https://github.com/wuba/taro-playground/releases
[12] Taro 案例提交:https://github.com/NervJS/taro-user-cases