Expo Module 通用 README 模板:从expo-module-scripts看 Expo 原生模块的安装与文档规范
【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo
导读
本文以 Expo 官方仓库中 expo-module-scripts 的 README 模板 为主体,讲解每一个新建的 Expo 模块(Module)在发布到 npm 前,其README.md应当如何组织:从 API 文档入口、managed 与 bare 工作流的安装指引、Android/iOS 平台配置,到贡献指南的规范写法。与此同时,结合expo-module-scripts的工程化设施与expo-module-template模板,说明这份 README 是如何被自动生成、按平台裁剪(interfaces / no-android / no-ios / no-package),以及它和expo-moduleCLI 命令、prepare生命周期脚本之间的配合关系。读完本文,你将能完整读懂 Expo 模块 README 的每一个段落,并学会为自己的原生模块编写符合官方规范的安装文档。
模板在 Expo 模块工程化体系中的位置
一份由工具自动生成的 README
在 Expo 仓库中,模块的 README 不是手写的零散文档,而是由 expo-module-scripts 统一维护的模板文件,位于 packages/expo-module-scripts/templates/README.md。根据 expo-module-scripts 自身 README 的说明,运行yarn(即执行prepare脚本)后,会自动生成缺失的文件,其中包括:
.npmignore(模板见 templates/.npmignore):Expo 模块约定使用.npmignore而非package.json中的files字段来控制发布内容;README.md:即本文主角——"A default template for Unimodule installation"(Unimodule 安装指南的默认模板);tsconfig.json(模板见 templates/tsconfig.json):统一继承tsconfig.base,保证所有模块使用同一份 TypeScript 基础配置。
除了上述三件套,prepare还会同步带有@generated标记的可选文件,例如 templates/oxlint.config.mjs 与 templates/scripts/with-node.sh,其同步机制以文件内容中是否包含@generated模式为判断依据。
从模板到真实模块的渲染链路
这份README.md本质上是一份 EJS 模板:其中的${packageName}、${description}、${docName}都是占位符,会在模块脚手架生成时被真实值替换。其下游消费方是 create-expo-module 工具链:
- create-expo-module.ts 中,通过
--with-readme选项控制是否生成 README;默认情况下withReadme为false,即使用create-expo-module创建模块时 README 不会自动写入; - templateUtils.ts 将
README.md列为本地模板校验的必需文件之一。
而最终发布到 npm 的脚手架模板 expo-module-template 中,README.md 只有两行:
# <%- project.slug %> <%- project.description %>可见仓库内部存在两套 README 生成策略:expo-module-scripts维护的完整安装指南模板(用于仓库内既有模块的规范化),以及expo-module-template中的极简占位(用于新模块脚手架)。本文聚焦前者——即 templates/README.md 这份信息量最完整的模板。
模板头部:包名、描述与条件注释
模板的第一部分非常简洁:
# ${packageName} ${description}# ${packageName}:H1 标题,渲染后即为模块的 npm 包名(如expo-camera);${description}:紧随标题的包描述,通常直接复用package.json中的description字段。
紧接着是一个关键的设计:<!--- remove for interfaces --->与<!--- end remove for interfaces --->注释块。这是 Expo 模块发布流水线使用的条件渲染标记。含义如下:
- 若模块是接口包(interface package)(即仅声明 API 契约、不含实现,例如
expo-updates-interface这类*-interface包),构建工具会删除remove for interfaces之间的所有内容——包括 "API documentation" 整节; - 若模块不是接口包,则该段落完整保留。
同一机制还用于<!--- remove for no-android --->(无 Android 实现时删除 Android 配置节)与<!--- remove for no-ios --->(无 iOS 实现时删除 iOS 配置节),以及<!--- remove for no-package --->(无独立 npm 包时删除)。可以推断,Expo 的发布工具链在打包前会扫描这些标记,按包的实际平台支持情况裁剪 README,避免文档中出现无效的安装指引。这一"注释即配置"的写法,是理解整个模板结构的一把钥匙。
API documentation 节:文档入口约定
# API documentation - [Documentation for the latest stable release](https://docs.expo.dev/versions/latest/sdk/${docName}/) - [Documentation for the main branch](https://docs.expo.dev/versions/unversioned/sdk/${docName}/)这是整个模板中唯一被remove for interfaces包裹的章节,也是每个 Expo 模块 README 的"门面":
${docName}是模块在 SDK 文档体系中的短名称,渲染后指向 Expo 官方文档站的两个入口:latest(最新稳定版 SDK 文档);unversioned(main 分支对应的未定版文档)。
- 之所以接口包要移除该节,是因为接口包通常不面向最终开发者,没有独立的 SDK 文档页面,保留链接只会产生死链。
从仓库结构可以印证这一点:Expo 的版本化文档体系位于 docs/pages/versions(超过 1000 个.mdx文件),每个 SDK 模块的 API 页面正是在这一目录树中按版本维护,README 中的latest/unversioned链接正是这套文档体系的入口约定。
在 managed Expo 项目中安装
# Installation in managed Expo projects For [managed](https://docs.expo.dev/archive/managed-vs-bare/) Expo projects, please follow the installation instructions in the [API documentation for the latest stable release](#api-documentation). If you follow the link and there is no documentation available then this library is not yet usable within managed projects — it is likely to be included in an upcoming Expo SDK release.这一节传达了两条重要信息:
- managed 工作流下,安装方式不是
npm install,而是遵循官方 API 文档——因为 managed 项目(如 Expo Go、EAS Build)的依赖由 Expo SDK 统一管理,模块是否可用取决于它是否被打包进当前 SDK 版本; - 文档是否存在 = 模块是否可用的判定约定:如果
latest文档页不存在,说明该库尚未进入 managed 项目可用的 SDK 版本,很可能"将在后续 SDK 版本中包含"(it is likely to be included in an upcoming Expo SDK release)。
这段文案与 Expo 的发布节奏强相关。在仓库中可以找到佐证:bundledNativeModules.json(见 packages/expo/bundledNativeModules.json)记录了每个 SDK 版本内置的原生模块版本清单,managed 项目正是依据该清单决定哪些模块可以直接使用;而 tools/src/publish-packages 中的发布任务(如updateBundledNativeModulesFile.ts)会在发布时同步维护这份清单。因此 README 中的"没有文档 = 尚未进入 SDK"并非随意说法,而是与这套打包/发布机制一一对应。
在 bare React Native 项目中安装
前置条件:必须先装好expo包
# Installation in bare React Native projects For bare React Native projects, you must ensure that you have [installed and configured the `expo` package](https://docs.expo.dev/bare/installing-expo-modules/) before continuing.bare(裸)React Native 项目没有 SDK 的托管式依赖管理,因此需要开发者手动安装并配置expo包。仓库中对应的落地方式是 install-expo-modules 包——它提供自动化脚本,为既有 React Native 项目注入 Expo 模块基础设施(Android Gradle / iOS Pods 配置),其模板中包含了expo与expo-modules-core等必要依赖的集成步骤。
添加 npm 依赖
### Add the package to your npm dependenciesnpm install ${packageName}
这是所有 bare 项目安装 Expo 模块的唯一标准命令,渲染后即:
npm install expo-camera若使用 Yarn,等价命令为yarn add ${packageName}。安装完成之后,才轮到下面的平台配置步骤。
配置 Android:多数模块"无需额外设置"
### Configure for Android No additional setup necessary.模板在no-android与no-package/interfaces三重条件下裁剪后,对普通 Android 模块给出的结论是无需额外配置。原因在于 Expo 模块的 Android 侧采用自动链接机制:
- 从源码结构看,每个模块的 Android 实现都位于各自的
android/src/main/java/...目录(例如 expo-module-template/android 中的AndroidManifest.xml与 Kotlin 源文件),并依赖 expo-modules-autolinking(见 packages/expo-modules-autolinking)在构建期自动扫描、注册模块; - 因此在 bare 项目中使用 Gradle 构建时,只要模块被
npm install,Android 原生代码即自动纳入编译,无需开发者手写MainApplication注册代码。
这是 Expo Modules API 相较旧版 Unimodules 的一大简化,也是模板敢于写出 "No additional setup necessary." 的底气。
配置 iOS:运行npx pod-install
### Configure for iOS Run `npx pod-install` after installing the npm package.iOS 侧则必须显式执行 CocoaPods 安装。npx pod-install实际上是执行:
npx pod-install # 等价于: pod install它读取项目ios/Podfile,根据 expo-modules-autolinking 生成的模块清单安装 Pods。仓库中 pod-install 正是这一命令的工具包,其作用是在 install 阶段解析 workspace 中所有 Expo 模块的 podspec(例如模板中的 ios/{%- project.name %}.podspec),保证模块的 iOS 原生代码与 JS 侧版本一致。
需要说明的是:仅当模块包含 iOS 实现(即模板中no-ios注释被移除)时,该节才会保留;纯 Android / 纯 Web 模块不会出现这条指引。
Contributing 节:社区协作约定
# Contributing Contributions are very welcome! Please refer to guidelines described in the [contributing guide](https://github.com/expo/expo#contributing).这是模板的收尾段落,向潜在贡献者开放协作入口。Expo 仓库的贡献规范沉淀在根目录的 CONTRIBUTING.md 与 guides 目录中(后者包含《Expo JavaScript Style Guide》《Swift Style Guide》等模块开发规范),贡献者可按需查阅。
模板如何与expo-moduleCLI 及 npm 生命周期协作
理解了 README 模板的内容后,再看它在工程化流水线中的位置会更有全局感。expo-module-scripts提供一个expo-module可执行程序,常用命令如下(详见 packages/expo-module-scripts/README.md):
| 命令 | 作用 |
|---|---|
expo-module configure | 生成tsconfig.json等通用配置文件(自动生成、只读、提交到 Git) |
expo-module build | 用tsc将src编译为 JS 与.d.ts |
expo-module test | 基于 Jest + ts-jest 运行测试 |
expo-module lint | 基于 ESLint / oxlint 检查源码 |
expo-module clean | 删除 build 目录 |
expo-module prepare | npmprepare生命周期钩子,内部运行configure |
expo-module prepublishOnly | npmprepublishOnly钩子,内部运行clean+build |
在 package.json 对应的模块中,典型脚本配置为:
{ "scripts": { "build": "expo-module build", "clean": "expo-module clean", "test": "expo-module test", "prepare": "expo-module prepare", "prepublishOnly": "expo-module prepublishOnly" } }其中prepare在开发者运行yarn/npm install时触发,负责补齐 README、.npmignore、tsconfig.json、oxlint.config.mjs、with-node.sh等生成文件;prepublishOnly在发布前执行清理与编译。README 模板正是通过这条prepare链路进入每个模块的仓库目录,再随npm publish一并分发到用户手中。
与模板配套的生成文件速览
README 模板并非孤立存在,同一templates目录下的兄弟文件共同构成了模块的"标准骨架":
| 文件 | 说明 |
|---|---|
| templates/tsconfig.json | // @generated by expo-module-scripts标记,extends至expo-module-scripts/tsconfig.base,rootDir指向./src且noEmit: true(类型检查专用,编译产物由expo-module build单独产出) |
| templates/oxlint.config.mjs | 仅一行:export { default } from 'expo-module-scripts/oxlint.config.base',统一 lint 规则 |
| templates/scripts/with-node.sh | Xcode 构建阶段的 Node.js 解析辅助脚本:依次读取.xcode.env与.xcode.env.local中的NODE_BINARY,未找到时给出可执行的修复命令echo "export NODE_BINARY=\$(command -v node)" >> .xcode.env |
其中with-node.sh与 README 的 iOS 节形成了完整闭环:README 让用户执行npx pod-install安装 iOS 依赖,而with-node.sh确保 Xcode 构建脚本能正确定位 Node 可执行文件——两者都是"bare 项目跑通 Expo 模块"不可或缺的一环。
小结:按官方模板撰写模块 README 的清单
综合模板全文,可以为自己的 Expo 模块 README 提炼出一份可复用的写作清单:
- 标题与描述:H1 用 npm 包名,紧跟一句话描述;
- API 文档:给出
latest与unversioned两个文档入口;接口包(interface)需整节移除; - managed 安装:引导用户查阅 SDK API 文档,而非直接
npm install,并说明"无文档 = 未进入当前 SDK"; - bare 安装:先要求安装并配置
expo包,再npm install ${packageName}; - Android 配置:有 Android 实现时声明 "No additional setup necessary."(自动链接);
- iOS 配置:有 iOS 实现时要求执行
npx pod-install; - Contributing:附上仓库贡献指南链接;
- 平台裁剪:用
remove for interfaces / no-android / no-ios / no-package注释控制各平台章节的取舍。
这套模板的价值在于"一致性":它让 Expo 生态中上百个模块的 README 结构完全统一——正如 expo-module-scripts 的 README 开篇所言,统一的模块开发体验正是整个仓库的工程目标。开发者无论使用哪个 Expo 模块,都能在相同的位置找到相同的安装指引,这本身就是一种高质量的开发者体验设计。
【免费下载链接】expoAn open-source framework for making universal native apps with React. Expo runs on Android, iOS, and the web.项目地址: https://gitcode.com/GitHub_Trending/ex/expo
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考