了解如何使用 Expo 自动链接自动链接 Expo 项目中的原生依赖。
通常,当你开发原生移动应用并想要安装第三方库时,系统会要求你将依赖添加到包管理器的清单文件中(Android 上的 build.gradle、iOS 上的 CocoaPods 的 Podfile、 iOS 上 SwiftPM 的 Package.swift)。在 Expo 和 React Native 中,你已经通过从 npm 注册表安装包来使用 package.json 文件执行此操作。由于大多数 React Native 库都附带了一些原生(特定于平台的)代码,因此安装库甚至需要配置最多三个不同的包管理器!
¥Usually, when you're developing a native mobile app and want to install a third-party library, you're asked to add the dependency to the manifest files of your package managers (build.gradle on Android, Podfile for CocoaPods on iOS, Package.swift for SwiftPM on iOS). In Expo and React Native, you already do that with your package.json file by installing the package from the npm registry. Since most of the React Native libraries come with some native (platform-specific) code, installing a library will require configuring even up to three different package managers!
Expo Autolinking 是一种自动执行此过程并将库安装过程减少到最少的机制 - 通常只需从 npm
安装软件包并重新运行 pod install
。核心实现可以在 expo-modules-autolinking
包中找到,分为三个部分:
¥Expo Autolinking is a mechanism that automates this process and reduces the library installation process to the minimum — usually just installing the package from npm
and re-running pod install
.
The core implementation can be found in the expo-modules-autolinking
package and is divided into three parts:
具有模块解析算法的通用 JavaScript CLI 工具
¥common JavaScript CLI tool with the module resolution algorithm
与 Android 平台的 Gradle 构建系统集成的代码
¥code that integrates with the Gradle build system for Android platform
与 iOS 平台的 CocoaPods 集成的 Ruby 脚本
¥Ruby script that integrates with CocoaPods for iOS platform
¥CLI commands
search
搜索是解决项目中安装的 Expo 模块的第一阶段。它的实现在所有平台之间共享。它找到所有标记为 Expo 模块的模块,并确定哪个版本具有最高优先级(以防重复)。
¥Searching is the first phase of resolving the Expo modules installed in a project. Its implementation is shared between all platforms. It finds all modules marked as Expo modules and determines which version is of the highest precedence (in case of duplicates).
-
npx expo-modules-autolinking search
上面的命令返回一个 JSON 格式的对象,其中包含已找到的依赖模块:
¥The above command returns an object in JSON format with modules that have been found as dependencies:
{
"expo-random": {
"path": "/absolute/path/to/node_modules/expo-random",
"version": "13.0.0",
"config": {
// Contents of `expo-module.config.json`
"platforms": ["ios", "android"],
"ios": { "modules": ["RandomModule"] },
"android": { "modules": ["expo.modules.random.RandomModule"] }
},
"duplicates": [] // An array of other revisions (with lower precedence) of the same module
}
// more modules...
}
resolve
解决是第二阶段,基于 search
命令的结果。它将每个搜索结果解析为具有更多(特定于平台)详细信息的对象,例如 podspec 或 build.gradle 文件的路径以及要链接的模块类。
¥Resolving is the second phase based on the results from the search
command. It resolves each search result to an object with more (platform-specific) details, such as the path to the podspec or build.gradle files and module classes to link.
-
npx expo-modules-autolinking resolve --platform <apple|android>
例如,使用 --platform apple
选项,它会返回一个 JSON 格式的对象,其中包含模块数组和平台的解析详细信息:
¥For example, with the --platform apple
option it returns an object in JSON format with an array of modules and resolved details for the platform:
{
"modules": [
{
"packageName": "expo-random",
"packageVersion": "13.0.0",
"pods": [
{
"podName": "ExpoRandom",
"podspecDir": "/absolute/path/to/node_modules/expo-random/ios"
}
],
"swiftModuleNames": ["ExpoRandom"],
"modules": ["RandomModule"],
"appDelegateSubscribers": [],
"reactDelegateHandlers": [],
"debugOnly": false
}
// more modules...
]
}
verify
通过检查是否没有重复的包来验证搜索结果,否则会显示相应的警告。
¥Verifies the search results by checking whether there are no duplicate packages, otherwise an appropriate warning is shown.
-
npx expo-modules-autolinking verify
¥Configuration
可以使用一些配置选项来自定义模块解析的行为。这些选项可以在三个不同的位置定义,从最低优先级到最高优先级:
¥The behavior of the module resolution can be customized using some configuration options. These options can be defined in three different places, from the lowest to the highest precedence:
应用的 package.json 中的 expo.autolinking
配置对象
¥expo.autolinking
config object in application's package.json
每个平台使用 expo.autolinking.ios
和 expo.autolinking.android
对象覆盖
¥per platform overrides with expo.autolinking.ios
and expo.autolinking.android
objects
提供给 CLI 命令的选项、Podfile 中的 use_expo_modules!
方法或 settings.gradle 中的 useExpoModules
函数
¥options provided to the CLI command, the use_expo_modules!
method in the Podfile or useExpoModules
function in the settings.gradle
searchPaths
相对于应用根目录的路径列表,自动链接脚本应在其中搜索 Expo 模块。它默认为从应用的根目录开始遍历 monorepo 时找到的所有 node_modules 文件夹的列表。当你的项目具有自定义结构或者你想要从不同于 node_modules 的文件夹链接本地包时很有用。
¥A list of paths relative to the app's root directory where the autolinking script should search for Expo modules. It defaults to a list of all node_modules folders found when traversing up through a monorepo, starting from the app's root directory. Useful when your project has a custom structure or you want to link local packages from folders different than node_modules.
{
"expo": {
"autolinking": {
"searchPaths": ["../../packages"]
}
}
}
与 CLI 一起使用时,你可以将搜索路径作为命令参数传递,如下所示:
¥When used with the CLI, you can pass the search paths as command arguments like this:
-
npx expo-modules-autolinking search ../../packages
exclude
要从自动链接中排除的包名称列表。即使在搜索路径中找到这些包,也不会自动链接它们。例如,你可能不想链接某些不在特定平台上使用的包,以减少二进制文件的大小。package.json 中的以下配置将从 Android 上的自动链接中排除 expo-random
:
¥A list of package names to exclude from autolinking. These packages will not be autolinked even if they are found in the search paths.
For example, you may want not to link some packages that you don't use on the specific platform to reduce the binary size.
The following config in package.json will exclude expo-random
from autolinking on Android:
{
"expo": {
"autolinking": {
"android": {
"exclude": ["expo-random"]
}
}
}
}
请注意,exclude
选项用于排除 Expo 包的自动链接。要排除任何其他包的自动链接,请在项目的根目录中创建 react-native.config.js 并应用配置,如下例所示:
¥Note that the exclude
option is for excluding the autolinking of Expo packages. To exclude the autolinking for any other packages, create react-native.config.js at the root directory of your project and apply the configuration as shown in the example below:
module.exports = {
dependencies: {
'library-name': {
platforms: {
android: null,
},
},
},
};
flags
CocoaPods 标志传递给每个自动链接的 pod。inhibit_warnings
可能是大多数开发者想要使用的唯一标志,以抑制编译自动链接模块时产生的 Xcode 警告。你可以参考 CocoaPods Podfile 文档 了解可用标志。
¥CocoaPods flags to pass to each autolinked pod. inhibit_warnings
is likely the only flag most developers want to use, to inhibit Xcode warnings produced when compiling the autolinked modules.
You can refer to the CocoaPods Podfile documentation for available flags.
use_expo_modules!({
flags: {
:inhibit_warnings => false
}
})
{
"expo": {
"autolinking": {
"ios": {
"flags": {
"inhibit_warnings": true
}
}
}
}
}
¥Common questions
¥How to set up the autolinking in my app?
使用 npx create-expo-app
命令创建的所有项目都已配置为使用 Expo 自动链接。如果你的项目是使用不同的工具创建的,请参阅 安装 Expo 模块 以确保你的项目包含所有必要的更改。
¥All projects created with the npx create-expo-app
command are already configured to use Expo Autolinking. If your project was created using different tools, please refer to Installing Expo modules to make sure your project includes all necessary changes.
¥What do I need to have in my module to make it autolinkable?
模块解析算法仅搜索根目录中 package.json 文件旁边包含 Expo 模块配置 文件 (expo-module.config.json) 的包。还需要在 platforms
数组中包含支持的平台 - 如果运行自动链接算法的平台不存在于该数组中,则只会在搜索结果中跳过它。
¥The module resolution algorithm searches only for packages that contain the Expo module config file (expo-module.config.json) at the root directory, next to the package.json file.
It's also necessary to include supported platforms in the platforms
array — if the platform for which the autolinking algorithm is run is not present in this array, it's just skipped in the search results.
¥How is it different from React Native autolinking?
Expo Autolinking 内置了对 monorepos、Yarn 工作区和传递依赖的支持。
¥Expo Autolinking comes in with built-in support for monorepos, Yarn workspaces and transitive dependencies.
即使模块解析算法更复杂,也更可靠并与节点的模块解析相匹配,它的速度也明显更快。
¥It's also significantly faster, even though the module resolution algorithm is more complex to be more reliable and match the Node's module resolution.
Expo 模块解析还能够检测重复项,这是 monorepos 中的常见问题。
¥Expo module resolution is also capable of detecting the duplicates which is a common issue in monorepos.
最后但并非最不重要的一点是,它与 Expo Modules API 提供的所有功能很好地集成。
¥Last but not least, it integrates well with all the features offered by Expo Modules APIs.