框架(开源)。使用 Expo Modules API(Swift、Kotlin、TypeScript)创建和编写 Expo 原生模块与视图的指南。涵盖模块定义 DSL、原生视图、共享对象、配置插件、生命周期钩子、自动链接和类型系统。在构建或修改 Expo 原生模块时使用。不适用于将现有 Swift 模块从定义 DSL 迁移到 Expo Modules API 2.0 宏;请使用 expo-migrate-module(来自 expo-experiments 插件)进行迁移。
编写 Expo 模块
使用 Expo Modules API 构建原生模块和视图的完整参考。涵盖 Swift (iOS)、Kotlin (Android) 和 TypeScript。
何时使用
- 创建新的 Expo 原生模块或原生视图
- 向 Expo 应用添加原生功能(相机、传感器、系统 API)
- 封装平台 SDK 以供 React Native 使用
- 构建修改原生项目文件的配置插件
- 为现有 Expo 模块添加 Android、Apple 或 Web 支持
- 编辑
expo-module.config.json、配置插件或生命周期钩子
要将现有 Swift 模块从定义 DSL 迁移到 Expo Modules API 2.0 宏(@ExpoModule、@JS、@Event),请改用 expo-migrate-module 技能(来自 expo-experiments 插件)。
参考资料
根据需要查阅以下资源:
references/
create-expo-module.md 脚手架和 add-platform-support 工作流、默认值和注意事项
native-module.md 模块定义 DSL:Name、Function、AsyncFunction、Property、Constant、Events、类型系统、共享对象
native-view.md 原生视图组件:View、Prop、EventDispatcher、视图生命周期、基于 ref 的函数
lifecycle.md 生命周期钩子:模块、iOS 应用/AppDelegate、Android Activity/Application 监听器
config-plugin.md 配置插件:修改 Info.plist、AndroidManifest.xml、在原生代码中读取值
module-config.md expo-module.config.json 字段、文件放置和自动链接行为
快速开始
优先使用 create-expo-module 而不是手动创建原生模块文件和目录。实践中,最佳路径通常是先创建脚手架,然后在其基础上构建。脚手架会设置预期的布局、expo-module.config.json、podspec 或 Gradle 文件、TypeScript 绑定以及独立的示例应用流程。
如果现有 Expo 模块只需要添加另一个平台,请使用 create-expo-module add-platform-support,而不是手动复制原生目录。
在搭建或扩展模块之前,请参阅 references/create-expo-module.md。它涵盖:
- 本地模块与独立模块
--platform、--features、--barrel、--package-manager和非交互模式expo.autolinking.nativeModulesDiradd-platform-support的行为和注意事项
推荐工作流
- 首先选择脚手架类型:
- 本地模块 用于单个应用
- 独立模块 用于复用、monorepo 或发布
- 确定需要的原生
expo-module特性。- 根据用户指令判断哪些特性脚手架有用。
- 可用特性:
Constant、Function、AsyncFunction、Event、View、ViewEvent、SharedObject
- 有目的地搭建脚手架:
- 传递明确的 slug 或路径
- 有意选择
--platform,而不是依赖默认值 - 使用
--features选择代码示例,下一步将修改这些示例以匹配实际实现。
- 将生成的示例代码替换为实际实现。
- 如果之后添加新平台,优先使用
add-platform-support而不是手动复制文件。
实用脚手架规则
- 特性示例是可选的。如果未选择任何特性,新搭建的模块可能非常精简。
ViewEvent隐含View。- 本地模块默认不生成
index.ts桶文件。仅在你需要时才使用--barrel。 - 在非交互式本地脚手架中,显式传递位置参数 slug 或路径。
--name更改原生类名,而不是文件夹名。 - 配置了
expo.autolinking.nativeModulesDir时,本地模块位于该目录下,否则位于modules/中。 - 独立模块拥有自己的包元数据、脚本,通常还有一个示例应用。本地模块则使用宿主应用的工具。
核心文件结构
Swift 和 Kotlin DSL 共享相同的结构。Swift 通常是最清晰的主要示例;有关特性细节,请查阅参考资料。
模块结构参考
Swift 和 Kotlin DSL 共享相同的结构。此处同时展示两个平台以供参考——在其他参考文件中,除非 Kotlin 模式有显著差异,否则以 Swift 作为主要语言。
Swift (iOS):
import ExpoModulesCore
public class MyModule: Module {
public func definition() -> ModuleDefinition {
Name("MyModule")
Function("hello") { (name: String) -> String in
return "Hello \(name)!"
}
}
}
Kotlin (Android):
package expo.modules.mymodule
import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition
class MyModule : Module() {
override fun definition() = ModuleDefinition {
Name("MyModule")
Function("hello") { name: String ->
"Hello $name!"
}
}
}
TypeScript:
import { requireNativeModule } from "expo";
const MyModule = requireNativeModule("MyModule");
export function hello(name: string): string {
return MyModule.hello(name);
}
expo-module.config.json
{
"platforms": ["android", "apple"],
"apple": {
"modules": ["MyModule"]
},
"android": {
"modules": ["expo.modules.mymodule.MyModule"]
}
}
注意:iOS 仅使用类名;Android 使用完全限定类名(包名+类名)。所有字段请参阅 references/module-config.md。
提交反馈
如果您在此技能中遇到错误、误导性或过时的信息,请报告以便 Expo 改进:
npx --yes submit-expo-feedback@latest --category skills --subject "expo-module" "<可操作的反馈>"
仅在您有具体且可操作的内容需要报告时提交。请尽可能包含相关上下文。






