在当前混合开发盛行的 Android 项目中,越来越多的团队将 React Native(以下简称 RN)作为 UI 层的补充组件。而如何高效、稳定地将 RN 工程的 JS Bundle 自动同步到原生项目中,并完成打包,成为一项重要的工程实践。

今天,我们将通过一个实际案例,一步步打造一个“能判断是否有提交变更、自动生成 JS Bundle、并集成到原生 APK 构建流程”的脚本,彻底告别手动操作,让你从容应对构建上线流程!

✅ 背景需求

在我们的项目中,存在两个工程:

  • A 工程:Android 原生项目,用于最终打包 APK;

  • B 工程:React Native 项目,负责业务模块的 JS 编写和资源管理。

需求如下:

当 A 工程执行打包时,先判断 B 工程是否有 Git 提交变更,如果有,则生成 JS Bundle 并拷贝到 A 工程中,再执行 APK 打包。

注意,这个流程必须自动化处理,不能依赖人工判断或手动复制。

✅ 技术要点

  • Git 提交变更检测:通过记录上一次提交的 commit hash,判断是否有更新;

  • 自动拉取 B 工程:如果首次执行,还没有拉取 RN 项目,则自动 clone;

  • 自动生成 JS Bundle:调用react-native bundle命令生成资源;

  • 拷贝资源文件:将生成的 bundle 和 assets 拷贝到 A 工程对应目录;

  • 执行 A 工程打包命令

  • 支持 Gradle/CI 工具集成

完整终极脚本:pre_build_rn_sync.sh
你只需要将它放在 A 工程根目录,一次配置,终身使用。

#!/bin/bash 
set -e

# ==== 配置区域 ====
A_PROJECT_DIR=$(cd "$(dirname "$0")"; pwd)
B_PROJECT_DIR="$A_PROJECT_DIR/rn_module"   # B 工程(RN)目录
B_REPO_URL="https://your.git.repo/B.git"  # ️ 替换为真实的 RN 工程仓库地址
B_BRANCH="main"                           # B 工程使用的分支
LAST_COMMIT_FILE="$A_PROJECT_DIR/.last_rn_commit"

ASSETS_DIR="$A_PROJECT_DIR/app/src/main/assets"
RES_DIR="$A_PROJECT_DIR/app/src/main/res"
# ===================

echo "==========================="
echo " [1] 检查 B 工程是否存在"
echo "==========================="

if [ ! -d "$B_PROJECT_DIR/.git" ]; then
  echo " 未找到 B 工程,正在 clone..."
  git clone -b "$B_BRANCH" "$B_REPO_URL" "$B_PROJECT_DIR"
else
  echo "✅ B 工程已存在,拉取最新代码..."
  cd "$B_PROJECT_DIR"
  git fetch origin
  git checkout "$B_BRANCH"
  git pull origin "$B_BRANCH"
fi

echo ""
echo "=============================="
echo " [2] 检查 RN 提交是否更新"
echo "=============================="

cd "$B_PROJECT_DIR"
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
LATEST_COMMIT=$(git rev-parse "$CURRENT_BRANCH")

if [ -f "$LAST_COMMIT_FILE" ]; then
  LAST_COMMIT=$(cat "$LAST_COMMIT_FILE")
else
  LAST_COMMIT=""
fi

echo " 当前分支: $CURRENT_BRANCH"
echo " 最新提交: $LATEST_COMMIT"
echo " 上次构建: $LAST_COMMIT"

if [ "$LATEST_COMMIT" != "$LAST_COMMIT" ]; then
  echo ""
  echo "================================"
  echo "⚙️  [3] 检测到更新,准备打包 JS Bundle"
  echo "================================"

  yarn install

  # 确保目标目录存在
  mkdir -p "$ASSETS_DIR"
  mkdir -p "$RES_DIR"

  npx react-native bundle \
    --platform android \
    --dev false \
    --entry-file index.js \
    --bundle-output "$ASSETS_DIR/index.android.bundle" \
    --assets-dest "$RES_DIR"

  echo "$LATEST_COMMIT" > "$LAST_COMMIT_FILE"

  echo "✅ JS Bundle 生成完成"
else
  echo "✅ 没有新提交,跳过 JS Bundle 打包"
fi

echo ""
echo "============================"
echo " [4] 开始打包 A 工程 APK"
echo "============================"

cd "$A_PROJECT_DIR"
./gradlew clean assembleRelease

echo ""
echo "✅ 全部流程完成:APK 打包成功"
使用说明
  1. 将脚本保存为pre_build_rn_sync.sh,放入 A 工程根目录;

  2. 替换脚本中的B_REPO_URL为你实际的 RN 项目地址;

  3. 赋予执行权限:

chmod +x pre_build_rn_sync.sh
  1. 使用方式:

./pre_build_rn_sync.sh
高级用法:集成到 Gradle 构建中

app/build.gradle中加入:

tasks.whenTaskAdded { task ->
    if (task.name == "preBuild") {
        task.doFirst {
            println " 正在同步 RN 工程..."
            exec {
                commandLine 'bash', "${rootDir}/pre_build_rn_sync.sh"
            }
        }
    }
}

这样,在你执行./gradlew assembleRelease的时候,系统会自动帮你检查并生成 bundle,无需再手动运行脚本。

注意事项

  • 请确保rn_module是一个合法的 RN 工程,结构完整;

  • node,yarn,npx必须已安装并在 PATH 中可用;

  • bundle-outputassets-dest目录路径要与实际项目结构匹配;

  • 若你使用 CI 工具(如 Jenkins),可直接将此脚本加入流水线前置任务。

结语

一个优雅的脚本,胜过无数的手动操作。这个脚本既能检测 Git 提交变更,又能自动化地集成 React Native 与原生工程的打包流程,极大提升了构建效率和团队协作体验

如果你也在做 Hybrid 架构,不妨收藏此脚本,或动手为团队搭建一套构建自动化流程!

如果这篇文章对你有帮助,欢迎转发、点赞或留言交流。你也可以评论告诉我你项目中遇到的实际构建问题,我将为你继续定制优化方案