Framework (OSS). Guide for creating and writing Expo native modules and views using the Expo Modules API (Swift, Kotlin, TypeScript). Covers module definition DSL, native views, shared objects, config plugins, lifecycle hooks, autolinking, and type system. Use when building or modifying native modules for Expo. Not for migrating an existing Swift module from the definition DSL to the Expo Modules API 2.0 macros; use expo-migrate-module (from the expo-experiments plugin) for that.
撰寫 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 建立 scaffold 與 add-platform-support 工作流程、預設值與特殊情況
native-module.md 模組定義 DSL:Name、Function、AsyncFunction、Property、Constant、Events、型別系統、共享物件
native-view.md 原生檢視元件:View、Prop、EventDispatcher、檢視生命週期、基於 ref 的函式
lifecycle.md 生命週期鉤子:模組、iOS App/AppDelegate、Android Activity/Application 監聽器
config-plugin.md 設定外掛:修改 Info.plist、AndroidManifest.xml、在原生程式碼中讀取值
module-config.md expo-module.config.json 欄位、檔案放置位置與自動連結行為
快速開始
建議使用 create-expo-module 而非手動建立原生模組檔案與目錄。實務上,最佳路徑通常是先建立 scaffold,再在其上建構。Scaffold 會設定預期的目錄結構、expo-module.config.json、podspec 或 Gradle 檔案、TypeScript 繫結以及獨立的範例應用程式流程。
如果現有 Expo 模組只需要另一個平台,請使用 create-expo-module add-platform-support,而非手動複製原生目錄。
在建立 scaffold 或擴充模組前,請參閱 references/create-expo-module.md。其中涵蓋:
- 本地模組 vs 獨立模組
--platform、--features、--barrel、--package-manager與非互動模式expo.autolinking.nativeModulesDiradd-platform-support的行為與特殊情況
建議工作流程
- 先選擇 scaffold 類型:
- 本地模組:適用於單一應用程式
- 獨立模組:適用於重複使用、monorepo 或發布
- 確定需要的原生
expo-module功能。- 根據使用者指示判斷哪些功能 scaffold 會有幫助。
- 可用功能:
Constant、Function、AsyncFunction、Event、View、ViewEvent、SharedObject
- 有目的地建立 scaffold:
- 傳入明確的 slug 或路徑
- 刻意選擇
--platform,而非依賴預設值 - 使用
--features選擇程式碼範例,並在下一步修改為實際實作。
- 將產生的範例程式碼替換為實際實作。
- 若之後加入新平台,優先使用
add-platform-support,而非手動複製檔案。
實用 Scaffold 規則
- 功能範例是選擇加入的。若未選擇任何功能,新建立的 scaffold 模組可能非常精簡。
ViewEvent隱含View。- 本地模組預設不會產生
index.tsbarrel。僅在需要時使用--barrel。 - 在非互動式本地 scaffold 中,請明確傳入位置 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" "<具體可操作的意見>"
僅在您有具體且可操作的內容時才提交。請盡可能提供相關背景資訊。






