无论怎样都要快速构建:Expo 如何优化速度(以及你也能怎么做)
新款 M4 Mac Mini、编译器缓存和预编译二进制文件正在加速 EAS 构建。了解如何借助指纹和 OTA 更新减少构建次数。
中文
复制

你需要速度。
无论你是学生,在课间发布自己的第一个应用;还是工程师,趁午休时间偷偷推进自己的副业项目;又或者身处企业团队,要为几百万用户负责——约束条件都一样。你没时间等构建。你需要立刻拿到反馈。你需要趁想法还热乎的时候把它发出去。
构建一慢,势头就断了。构建够快,你才能一直待在心流里,而好产品恰恰是在这种状态下做出来的。
我们的目标是不管你用的是哪个套餐,都给你最快的构建。**为了兑现这个承诺,我们正在采取措施,应对 Expo 前所未有的需求、Mac 硬件短缺,并扩展规模以满足企业工程师和 vibe coder 这两类用户的需要。
对于用 OpenClaw 做 AI 自动化的玩家来说,Mac Mini 是抢手货,尤其是那些内存更大的配置(内存本身早就是稀缺资源了)。如果你看过我们的构建服务器配置页面,就知道 iOS 构建跑在配置拉满的 M4 Mac Mini 上。Mac Mini 全球发货周期拉长,再加上全世界 vibe coder、独立开发者、本地商家和企业掀起的应用开发热潮,这几件事凑到一起,你自然会想知道这会不会影响 Expo 的 Build 和 Workflows 队列。
以下是我们为加快构建、扩充基础设施正在做的事:
-
首先,我们最近已经往集群里加了几十台新的 M4 Pro 和 Max Mac Mini,眼下还在继续上架,另外还有更多已经下单、正在路上。
-
我们正在采取多项措施让每次构建都更快,这意味着每个人都能跑更多构建。
-
我们最近为 SDK 54 和 55 项目部署了编译器级缓存,把你的 fastlane 和 gradlew 步骤提速最多 30%。
-
我们正在部署 Gradle 缓存,以提升 Android 构建性能。
-
我们正在为
react-native-reanimated、react-native-screens这类常用包加入预编译二进制,基本上可以消除构建这些产物所需的时间。
-
-
SDK 56 为 iOS 上最复杂的 Expo 模块提供预编译 XCFrameworks,以加快 iOS 构建速度。
我们的愿景是让每位构建者都有机会做出真正的东西。第一次用 Expo,构建飞快完成时,你能感受到。然后它再次发生,到某个时候你完全不再去想构建这件事。你相信一切都会正常工作,而且会很快。这就是我们的标准:让你不必操心基础设施,从而专注于构建美好的东西。
同样的标准也适用于我们的工具。我们的开发者工具应当帮助你充分利用每一次构建,也让你更容易发挥自己硬件的性能。
用基于指纹的工作流减少构建次数
还有什么比在启用了 ccache 和预编译 React Native 二进制的 EAS M4 Max large worker 上构建更快?干脆不构建怎么样?
即使你不需要 Expo 的 OTA Updates 来向生产应用空中推送 bug 修复,它也非常适合让你的预览应用反馈循环尽可能紧凑。大多数应用不需要在每次代码改动时都完整重新构建,因为大多数改动只涉及 JavaScript。相反,推送一次更新,只重新构建 JavaScript,让你已安装的应用下载新代码即可。
运行 eas update:configure 将应用配置为使用 EAS Update 并重新构建。你可以用动态应用配置只为预览应用启用更新(这种情况下把 updates.enabled 设为 false)。
之后,当你确定没有改动任何原生代码或依赖时,可以运行 eas update --channel preview 手动更新应用。或者,把它配置成一个 EAS workflow,在提交时自动运行,并根据原生指纹的采样结果选择构建还是更新——指纹是一种哈希,只有原生代码变化时才会改变。
把 Expo 项目连接到 Github,然后把这个 workflow 加到 .eas/workflows 文件夹:
name: Build or update preview on main push, based on fingerprint
on:
# Trigger on pushes to main branch
push:
branches: [main]
jobs:
fingerprint:
environment: preview
type: fingerprint
ios_get_build:
needs: [fingerprint]
type: get-build
params:
fingerprint_hash: ${{ needs.fingerprint.outputs.ios_fingerprint_hash }}
platform: ios
profile: preview
ios_update:
needs: [ios_get_build]
if: ${{ needs.ios_get_build.outputs.build_id }}
type: update
params:
channel: preview
platform: ios
ios_build:
needs: [ios_get_build]
if: ${{ !needs.ios_get_build.outputs.build_id }}
type: build
params:
platform: ios
profile: preview
# add the same steps for Android to handle those builds/updates, as well!
为应用加上 EAS Update,并尽可能用它来更新代码,是让每次构建发挥最大价值的好办法。
在本地构建,用于开发和测试
用 npx expo start 启动本地开发服务器、在 Expo Go 或 development build 里跑应用,大概是 Expo CLI 最常见的用法。不过必要时,Expo CLI 也能直接把应用构建并运行在模拟器或真机上。
准备工作
本地构建时,Expo CLI 会调用你已安装的 Android Studio 或 Xcode,使用其中的原生开发工具。这些工具的配置稍有不慎就会出问题,所以我们准备了一份本地构建指南,给出了经过验证的 Android 和 iOS 构建配置。注意,iOS 构建需要一台 Mac。
本地 development build
原生工具装好之后,就可以用下面的命令在模拟器上构建并运行应用:
npx expo run:android
或者
npx expo run:ios
这会为应用生成 debug build,并启动本地开发服务器(也就是 npx expo start 做的事)。也就是说,你不仅在本地完成了构建,还能在编辑 JavaScript 代码时实时重载。
第一次运行这条命令时,它还会执行 npx expo prebuild 来生成 android 和 iOS 原生目录。如果你添加了带原生代码的包,或者改动了 app.json,通常需要运行 npx expo prebuild --clean 重新生成这些目录,再运行 npx expo run:android|ios 重新构建。这大致相当于 EAS 每次构建应用时做的事。
装上 expo-dev-client 之后会更方便。这个包能把任意 debug build 变成 development build,让你可以打开任意开发服务器的 URL。development build 一旦装到模拟器上,只要原生运行时不变,就不必反复重新构建。直接运行 npx expo start,按 a 在 Android 上打开,按 i 在 iOS 上打开。
Release build
有些东西在 development build 里不太好测,启动屏尤其如此。你仍然可以用本地构建完成大量上线前的测试——构建一个独立的 release build:
npx expo run:android --variant release
或
npx expo run:ios --configuration Release
共享构建
通过 EAS,你可以把在本机构建的 Android APK 构建和 iOS 模拟器构建共享给组织内的其他开发者。运行 eas upload 手动上传构建并生成可共享的链接,或者把 EAS 配置为构建缓存提供方来自动完成这一步。之后其他开发者运行 eas build:run 即可下载并运行该构建。
设备构建
npx expo run:android|ios 还可以把构建运行在通过 USB 连接的设备上。
Android 方面,连接 Android 手机并确认已开启 USB 调试后,运行 adb devices -l 获取设备名称,再把该设备名称填入 npx expo run:android --device [device-name]。
iOS 方面,连接设备并确认已开启开发者模式,然后运行 xcrun xctrace list devices 获取设备 UDID,接着运行 npx expo run:ios --device [udid]。注意,你可能需要在 Xcode 中打开 ios 文件夹并选择你的开发团队才能完整走完这套配置(如果需要,Expo CLI 会提示你)。
如果你做的是开发构建,只要原生运行时不变,断开 USB 之后仍可继续使用同一个构建。之后运行 npx expo start 并扫描二维码即可。
生成已签名的生产构建
EAS 的凭据管理相当方便,在模拟器、仿真器或已连接设备上运行所需的简单签名配置,就足以支撑大量开发和测试工作,所以不妨把这套本地签名流程当作“紧急情况下才砸玻璃”的备用手段。不过,如果你确实需要用 EAS 生成的生产凭据在本地构建,也是有办法的。
首先,通过 eas credentials 命令下载所需的凭据。它会引导你完成各平台所需的内容(Android 的上传密钥库和 iOS 的分发证书)。然后运行 npx expo prebuild --clean 生成原生项目。如果你使用了多个应用变体,请确保环境已切换到生产变体(如果你是用 EAS 环境变量设置的,可以运行 eas env:pull 在本地设置这些变量)。
Android 端,在 Android Studio 中打开 android 文件夹,进入 Build → Generate Signed App Bundle or APK,填入刚下载的 keystore。
iOS 端,解压刚下载的凭证并安装到 Keychain。在 Xcode 中打开 ios 文件夹,在 Target 下检查 Signing and Capabilities,确认签名配置无误。重新生成 provisioning profile 可能更省事(这么做没有任何坏处)。然后运行 Product → Archive 进行构建。
结语
本地构建是工具箱里很值得添置的一件,理由很多:从本地原生代码调试,到网络访问限制,等等。它与云端 EAS Build 和 Workflows 互为补充,能在你卡住时帮你脱身,同时其余自动化流程继续在 EAS 上跑。说到自动化,现在也正是引入 fingerprints 和 EAS Update 的好时机——限制重建的频率和时机,迭代速度还能再快一截。