Expo Module 通用 README 模板:从 `expo-module-scripts` 看 Expo 原生模块的安装与文档规范
2026/9/11 13:04:04 网站建设 项目流程

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;默认情况下withReadmefalse,即使用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 &mdash; it is likely to be included in an upcoming Expo SDK release.

这一节传达了两条重要信息:

  1. managed 工作流下,安装方式不是npm install,而是遵循官方 API 文档——因为 managed 项目(如 Expo Go、EAS Build)的依赖由 Expo SDK 统一管理,模块是否可用取决于它是否被打包进当前 SDK 版本;
  2. 文档是否存在 = 模块是否可用的判定约定:如果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 配置),其模板中包含了expoexpo-modules-core等必要依赖的集成步骤。

添加 npm 依赖

### Add the package to your npm dependencies

npm install ${packageName}

这是所有 bare 项目安装 Expo 模块的唯一标准命令,渲染后即:

npm install expo-camera

若使用 Yarn,等价命令为yarn add ${packageName}。安装完成之后,才轮到下面的平台配置步骤。

配置 Android:多数模块"无需额外设置"

### Configure for Android No additional setup necessary.

模板在no-androidno-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 buildtscsrc编译为 JS 与.d.ts
expo-module test基于 Jest + ts-jest 运行测试
expo-module lint基于 ESLint / oxlint 检查源码
expo-module clean删除 build 目录
expo-module preparenpmprepare生命周期钩子,内部运行configure
expo-module prepublishOnlynpmprepublishOnly钩子,内部运行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、.npmignoretsconfig.jsonoxlint.config.mjswith-node.sh等生成文件;prepublishOnly在发布前执行清理与编译。README 模板正是通过这条prepare链路进入每个模块的仓库目录,再随npm publish一并分发到用户手中。

与模板配套的生成文件速览

README 模板并非孤立存在,同一templates目录下的兄弟文件共同构成了模块的"标准骨架":

文件说明
templates/tsconfig.json// @generated by expo-module-scripts标记,extendsexpo-module-scripts/tsconfig.baserootDir指向./srcnoEmit: true(类型检查专用,编译产物由expo-module build单独产出)
templates/oxlint.config.mjs仅一行:export { default } from 'expo-module-scripts/oxlint.config.base',统一 lint 规则
templates/scripts/with-node.shXcode 构建阶段的 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 提炼出一份可复用的写作清单:

  1. 标题与描述:H1 用 npm 包名,紧跟一句话描述;
  2. API 文档:给出latestunversioned两个文档入口;接口包(interface)需整节移除;
  3. managed 安装:引导用户查阅 SDK API 文档,而非直接npm install,并说明"无文档 = 未进入当前 SDK";
  4. bare 安装:先要求安装并配置expo包,再npm install ${packageName}
  5. Android 配置:有 Android 实现时声明 "No additional setup necessary."(自动链接);
  6. iOS 配置:有 iOS 实现时要求执行npx pod-install
  7. Contributing:附上仓库贡献指南链接;
  8. 平台裁剪:用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),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询