使用 patch-project

了解如何使用 patch-project 在 Expo 项目中创建、生成、应用和保存原生更改。


注意:patch-project 是一项实验性功能。

patch-package 是一款 Expo 配置插件和命令行接口 (CLI) 工具,可在运行 npx expo prebuild 后生成并应用补丁以保留原生更改。此工具对于希望保留自定义设置而无需了解如何编写配置插件的原生应用开发者非常有用,它可以有效地生成与 持续的原生生成 (CNG) 兼容的自动化解决方案。

¥patch-package is an Expo config plugin and command-line interface (CLI) tool that generates and applies patches to preserve native changes after running npx expo prebuild. This tool is useful for native app developers who want to preserve customizations without needing to know how to write a config plugin, effectively generating an automatic solution that works with Continuous Native Generation (CNG).

本指南解释了如何使用 patch-project、何时使用它以及它的局限性。

¥This guide explains how to use patch-project, when to use it, and its limitations.

patch-project 如何工作

¥How patch-project works

patch-project 使用一种受 Git 启发的方法来生成和自动应用补丁。使用此命令行工具需要在你的项目中执行以下步骤:

¥patch-project uses an approach to generate and automatically apply patches, which is inspired by Git. Using this command line tool requires the following steps in your project:

安装

¥Installation

要开始使用,你需要在项目中安装该工具:

¥To get started, you need to install the tool in your project:

Terminal
npx expo install patch-project

此命令会自动将 patch-project 配置插件添加到你的 应用配置

¥This command will automatically add the patch-project config plugin to your app config:

app.json
{ "expo": { "plugins": [ "patch-project" %%placeholder-start%% ...%%placeholder-end%% ] } }

从现有自定义项生成补丁

¥Generate patches from existing customizations

假设你手动修改了项目中的原生目录(android 和 ios)。要为这些原生目录生成补丁,你可以运行以下命令:

¥Let's assume you manually modified native directories (android and ios) in your project. To generate patches for these native directories, you can run the following command:

Terminal
npx patch-project
注意:如果你想要为特定平台生成补丁,可以使用 --platform 选项并运行 npx patch-project --platform androidnpx patch-project --platform ios

这些补丁生成后会保存在 cng-patches 目录中。

¥These patches, when generated, are saved in the cng-patches directory.

.
app.jsonwith patch-project plugin
cng-patches
  android+eee880ad7b07965271d2323f7057a2b4.patchpatch for android directory
  ios+eee880ad7b07965271d2323f7057a2b4.patchpatch for ios directory
package.json
...other project files

每个文件都将以平台名称作为前缀,后跟校验和值。例如:

¥Each file will be prefixed with a platform's name followed by a checksum value. For example:

ios+eee880ad7b07965271d2323f7057a2b4.patch

在预构建期间应用补丁

¥Apply patches during prebuild

生成补丁后,它们会在随后运行 npx expo prebuild 命令时自动应用。patch-project 配置插件可以检测现有补丁并应用它们来恢复你的自定义设置。

¥Once you have generated patches, they are automatically applied when subsequently running the npx expo prebuild command. The patch-project config plugin detects the existing patches and applies them to restore your customizations.

何时使用 patch-project

¥When to use patch-project

你可以在以下场景中使用 patch-project

¥You can use patch-project in the following scenarios:

  • 迁移现有的 React Native 应用(由于包含大量原生自定义内容而非常复杂),并将这些原生自定义内容重新创建为配置插件将非常耗时。

    ¥Migrating existing React Native apps that are complex because they contain extensive native customizations and re-creating these native customizations as config plugins would be time-consuming.

  • 在 Expo 项目中过渡到采用持续原生生成 (CNG) 时,保留对 android 和/或 ios 目录所做的手动更改。

    ¥Preserving manual changes made to android and/or ios directories while transitioning to adopt Continuous Native Generation (CNG) in your Expo project.

  • 在编写配置插件之前需要测试原生更改时,可以快速进行原型设计。

    ¥Quick prototyping when you need to test native changes before writing config plugins.

  • 补丁将在后续运行 npx expo prebuild 命令时自动应用。这比 patch-package(通常用于为 npm 库生成补丁)等工具更有优势,因为后者不会在预构建过程中保留并自动应用补丁。

    ¥Patches are applied automatically when running the npx expo prebuild command subsequently. This is an advantage over tools like patch-package (commonly used for generating patches for npm libraries), which do not preserve and automatically apply patches during the prebuild process.

限制和注意事项

¥Limitations and considerations

补丁在 Expo SDK 版本升级期间可能会失效,原因如下:

¥Patches may become invalid during Expo SDK version upgrades because:

  • 模板和/或文件结构更改:预构建模板会随着 SDK 版本的更新而不断演变,包括原生目录中的新变化和文件更新。这将影响 cng-patches 目录中已生成的 diff,这些 diff 可能不再适用。

    ¥Template and/or file structure changes: The prebuild template evolves between SDK versions with new changes and file updates in native directories. This will affect the already generated diff in the cng-patches directory, which may no longer apply.

  • 插件冲突:CNG 补丁可能很危险,当其他插件修改相同的文件时,可能会中断。例如,如果你添加了一个新插件,它会更新 MainApplication.kt 文件,并且与你现有的补丁程序冲突,则补丁程序可能无法正确应用。在这种情况下,你可能需要重新生成补丁。

    ¥Plugin conflicts: CNG patches can be dangerous and may break when other plugins modify the same files. For example, if you add a new plugin that updates MainApplication.kt and conflicts with your existing patches, the patches may no longer apply correctly. In such cases, you may need to regenerate patches.

  • iOS .pbxproj 变更:在 iOS 项目中,将补丁应用于 .pbxproj 文件可能很脆弱,因为该文件包含 UUID,而运行像 npx expo prebuild --clean 这样的命令可能会更改这些 ID。例如,如果你添加了一个小部件扩展或进行了其他项目配置更改,基于补丁程序的方法可能无法可靠地工作。你可以查看生成的 cng-patches/ios-* 文件,并仅保留必要的补丁。尽可能减少补丁程序的使用可以降低应用补丁程序时失败的风险。

    ¥iOS .pbxproj changes: In iOS projects, applying patches to .pbxproj files can be fragile since this file contains UUIDs and running a command like npx expo prebuild --clean can change these IDs. For example, if you're adding a widget extension or making other project configuration changes, patch-based approaches may not work reliably. You can review the generated cng-patches/ios-* and keep only the necessary patch. Having the patch as minimal as possible would reduce the risk of failures when applying patches.

建议每次 SDK 升级后重新生成补丁。

¥It is recommended to regenerate patches after each SDK upgrade.