原生项目升级助手

编辑页面

查看你需要对原生项目进行的所有更改的逐文件差异,以将它们升级到下一个 Expo SDK 版本。


For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.

如果你管理自己的原生项目(以前称为 bare workflow),要升级到最新的 Expo SDK,你必须对原生项目进行一些更改。找出哪些原生文件发生了变化,以及需要在每个文件中更新什么内容,可能是一个复杂的过程。

以下指南提供了用于比较你项目当前 SDK 版本和你想升级到的目标 SDK 版本之间原生项目文件差异的 diff。你可以根据项目所使用的 expo 包版本,使用它们对项目进行修改。本页中的工具与 React Native Upgrade Helper 类似。不过,它们是围绕使用 Expo 模块及相关工具链的项目设计的。

想要完全避免升级原生代码?请查看 Continuous Native Generation (CNG),了解 Expo Prebuild 如何在构建前生成你的原生项目。

升级原生项目文件

一旦你升级了 Expo SDK 版本和相关依赖,请使用下面的 diff 工具了解你需要对原生项目做出的更改,并使其与当前 Expo SDK 版本保持一致。

选择你的起始 SDK 版本目标 SDK 版本以查看生成的 diff。然后,通过复制粘贴或手动修改项目文件,将这些更改应用到你的原生项目中。

From SDK version:

To SDK version:

Native code changes from SDK 54 to 55

android/app/build.gradle
MODIFIED
1111react {
1212 entryFile = file(["node", "-e", "require('expo/scripts/resolveAppEntry')", projectRoot, "android", "absolute"].execute(null, rootDir).text.trim())
1313 reactNativeDir = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile()
14 hermesCommand = new File(["node", "--print", "require.resolve('react-native/package.json')"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/sdks/hermesc/%OS-BIN%/hermesc"
14 hermesCommand = new File(["node", "--print", "require.resolve('hermes-compiler/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsolutePath() + "/hermesc/%OS-BIN%/hermesc"
1515 codegenDir = new File(["node", "--print", "require.resolve('@react-native/codegen/package.json', { paths: [require.resolve('react-native/package.json')] })"].execute(null, rootDir).text.trim()).getParentFile().getAbsoluteFile()
1616
1717 enableBundleCompression = (findProperty('android.enableBundleCompression') ?: false).toBoolean()
android/app/src/main/AndroidManifest.xml
MODIFIED
1<manifest xmlns:android="http://schemas.android.com/apk/res/android">
1<manifest xmlns:android="http://schemas.android.com/apk/res/android"
2 xmlns:tools="http://schemas.android.com/tools">
23
34 <uses-permission android:name="android.permission.INTERNET"/>
45 <!-- OPTIONAL PERMISSIONS, REMOVE WHATEVER YOU DO NOT NEED -->
56 <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
67 <uses-permission android:name="android.permission.VIBRATE"/>
78 <!-- These require runtime permissions on M -->
8 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
9 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
9 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" tools:replace="android:maxSdkVersion"/>
10 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="32" tools:replace="android:maxSdkVersion"/>
1011 <!-- END OPTIONAL PERMISSIONS -->
1112
1213 <queries>
1920 </queries>
2021
2122 <application android:name=".MainApplication" android:label="@string/app_name" android:icon="@mipmap/ic_launcher" android:roundIcon="@mipmap/ic_launcher_round" android:allowBackup="false" android:theme="@style/AppTheme" android:supportsRtl="true">
22 <activity android:name=".MainActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true">
23 <activity android:name=".MainActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|screenLayout|uiMode|smallestScreenSize" android:launchMode="singleTask" android:windowSoftInputMode="adjustResize" android:theme="@style/Theme.App.SplashScreen" android:exported="true">
2324 <intent-filter>
2425 <action android:name="android.intent.action.MAIN"/>
2526 <category android:name="android.intent.category.LAUNCHER"/>
android/app/src/main/java/com/helloworld/MainApplication.kt
MODIFIED
66import com.facebook.react.PackageList
77import com.facebook.react.ReactApplication
88import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
9import com.facebook.react.ReactNativeHost
109import com.facebook.react.ReactPackage
1110import com.facebook.react.ReactHost
1211import com.facebook.react.common.ReleaseLevel
1312import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint
14import com.facebook.react.defaults.DefaultReactNativeHost
1513
1614import expo.modules.ApplicationLifecycleDispatcher
17import expo.modules.ReactNativeHostWrapper
15import expo.modules.ExpoReactHostFactory
1816
1917class MainApplication : Application(), ReactApplication {
2018
21 override val reactNativeHost: ReactNativeHost = ReactNativeHostWrapper(
22 this,
23 object : DefaultReactNativeHost(this) {
24 override fun getPackages(): List<ReactPackage> =
25 PackageList(this).packages.apply {
26 // Packages that cannot be autolinked yet can be added manually here, for example:
27 // add(MyReactNativePackage())
28 }
29
30 override fun getJSMainModuleName(): String = ".expo/.virtual-metro-entry"
31
32 override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
33
34 override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
35 }
36 )
37
38 override val reactHost: ReactHost
39 get() = ReactNativeHostWrapper.createReactHost(applicationContext, reactNativeHost)
19 override val reactHost: ReactHost by lazy {
20 ExpoReactHostFactory.getDefaultReactHost(
21 context = applicationContext,
22 packageList =
23 PackageList(this).packages.apply {
24 // Packages that cannot be autolinked yet can be added manually here, for example:
25 // add(MyReactNativePackage())
26 }
27 )
28 }
4029
4130 override fun onCreate() {
4231 super.onCreate()
android/gradle/wrapper/gradle-wrapper.properties
MODIFIED
11distributionBase=GRADLE_USER_HOME
22distributionPath=wrapper/dists
3distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
3distributionUrl=https\://services.gradle.org/distributions/gradle-9.0.0-bin.zip
44networkTimeout=10000
55validateDistributionUrl=true
66zipStoreBase=GRADLE_USER_HOME
android/gradlew
MODIFIED
11#!/bin/sh
22
33#
4# Copyright © 2015-2021 the original authors.
4# Copyright © 2015 the original authors.
55#
66# Licensed under the Apache License, Version 2.0 (the "License");
77# you may not use this file except in compliance with the License.
ios/HelloWorld/AppDelegate.swift
MODIFIED
1import Expo
1internal import Expo
22import React
33import ReactAppDependencyProvider
44
5@UIApplicationMain
6public class AppDelegate: ExpoAppDelegate {
5@main
6class AppDelegate: ExpoAppDelegate {
77 var window: UIWindow?
88
99 var reactNativeDelegate: ExpoReactNativeFactoryDelegate?
1919
2020 reactNativeDelegate = delegate
2121 reactNativeFactory = factory
22 bindReactNativeFactory(factory)
2322
2423#if os(iOS) || os(tvOS)
2524 window = UIWindow(frame: UIScreen.main.bounds)
ios/Podfile
MODIFIED
77def ccache_enabled?(podfile_properties)
88 # Environment variable takes precedence
99 return ENV['USE_CCACHE'] == '1' if ENV['USE_CCACHE']
10
10
1111 # Fall back to Podfile properties
1212 podfile_properties['apple.ccacheEnabled'] == 'true'
1313end
1414
15ENV['RCT_NEW_ARCH_ENABLED'] ||= '0' if podfile_properties['newArchEnabled'] == 'false'
1615ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] ||= podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR']
17ENV['RCT_USE_RN_DEP'] ||= '1' if podfile_properties['ios.buildReactNativeFromSource'] != 'true' && podfile_properties['newArchEnabled'] != 'false'
18ENV['RCT_USE_PREBUILT_RNCORE'] ||= '1' if podfile_properties['ios.buildReactNativeFromSource'] != 'true' && podfile_properties['newArchEnabled'] != 'false'
16ENV['RCT_USE_RN_DEP'] ||= '1' if podfile_properties['ios.buildReactNativeFromSource'] != 'true'
17ENV['RCT_USE_PREBUILT_RNCORE'] ||= '1' if podfile_properties['ios.buildReactNativeFromSource'] != 'true'
18ENV['RCT_HERMES_V1_ENABLED'] ||= '1' if podfile_properties['expo.useHermesV1'] == 'true'
1919platform :ios, podfile_properties['ios.deploymentTarget'] || '15.1'
2020
2121prepare_react_native_project!
package.json
MODIFIED
22 "name": "expo-template-bare-minimum",
33 "description": "This bare project template includes a minimal setup for using unimodules with React Native.",
44 "license": "0BSD",
5 "version": "54.0.50",
5 "version": "55.0.26",
66 "main": "index.js",
77 "scripts": {
88 "start": "expo start --dev-client",
1111 "web": "expo start --web"
1212 },
1313 "dependencies": {
14 "expo": "~54.0.33",
15 "expo-status-bar": "~3.0.9",
16 "react": "19.1.0",
17 "react-native": "0.81.5"
14 "expo": "~55.0.14",
15 "expo-status-bar": "~55.0.5",
16 "react": "19.2.0",
17 "react-native": "0.83.4"
1818 }
1919}
2020