Ignite 项目 app 目录结构全解:入口文件、模块划分与内置组件体系
【免费下载链接】igniteInfinite Red's battle-tested React Native project boilerplate, along with a CLI, component/model generators, and more! 9 years of continuous development and counting.项目地址: https://gitcode.com/GitHub_Trending/ig/ignite
导读
本文以 Infinite Red 出品的 React Native 样板工程 Ignite 为对象,系统拆解其app目录的整体结构:从唯一入口文件app.tsx的启动流程,到 components、config、i18n、context、navigators、screens、services、theme、utils 等各子目录的职责划分与内部实现。读完本文,你将掌握 Ignite 工程中业务代码的组织范式,理解启动链路上字体加载、国际化、导航恢复、安全区与错误处理等关键环节,并能在自己的 Ignite 项目中快速定位与扩展对应模块。
一、app 目录:你 90% 时间所在的战场
在 Ignite 样板工程中,app目录承载了绝大部分业务代码。官方文档的定位非常直白:"The vast majority of your code will live in theappfolder. This is where you'll spend most of your time."(绝大多数代码都放在app目录,这里是你投入大部分时间的地方)。
打开 boilerplate/app 可以看到,该目录下只有一个顶层文件 app.tsx,其余全部是子目录,分别管理不同类型的代码:
| 目录 | 职责 | 详细文档 |
|---|---|---|
app.tsx | 应用主入口,负责应用启动引导 | app.tsx.md |
components | 可复用的内置 UI 组件(轻量设计系统) | Components.md |
config | 开发/生产环境配置文件 | Config.md |
devtools | Reactotron 等开发工具配置 | Devtools.md |
i18n | 国际化(i18n)配置与翻译文件 | Internationalization.md |
context | React Context 提供者与状态管理 | Context.md |
navigators | React Navigation 导航器定义 | Navigation.md |
screens | 应用的主要屏幕 | Screens.md |
services | 服务层,如 API 客户端 | Services.md |
theme | 主题文件(颜色、字体、间距等) | Theming.md |
utils | 工具函数与自定义 Hooks | Utils.md |
这个"入口文件 + 分类目录"的扁平结构是 Ignite 多年实战沉淀出的组织范式:目录即模块边界,职责清晰,新成员可以迅速定位到对应模块。
二、app.tsx:应用启动的总指挥
2.1 与根目录 index.tsx 的分工
app.tsx 是应用的真正业务入口,但要注意它不是Expo/React Native 的进程入口。项目根目录的index.tsx才是原生层启动入口,它只负责完成 splash screen 初始化后立即加载app/app.tsx。二者分工如下:
- 根目录 index.tsx:Expo/React Native 原生入口,负责注册根组件;
app/app.tsx:业务入口,承载应用的初始化与启动引导逻辑。
2.2 启动时承担的职责
从 app.tsx 源码 可以看出,App组件集中处理了以下启动任务:
- 加载字体:通过
expo-font的useFontsHook 加载customFontsToLoad(定义于 theme/typography.ts); - 初始化国际化:调用
initI18n()初始化 i18next,随后加载date-fns的 locale(loadDateFnsLocale()); - 恢复导航状态:通过
useNavigationPersistence(storage, NAVIGATION_PERSISTENCE_KEY)从本地存储恢复上次的导航状态; - 确保一切就绪后再展示界面:在导航状态恢复、i18n 初始化完成、字体加载成功(或加载失败)之前,组件返回
null,不渲染任何内容,此时用户看到的是原生层设置的背景色; - 设置安全区提供者:用
SafeAreaProvider(react-native-safe-area-context)包裹全局,并传入initialWindowMetrics; - 渲染错误边界与错误屏:由导航器层面接入的错误处理体系兜底;
- 启用深链接(Deep Linking):基于
expo-linking的Linking.createURL("/")生成前缀,配合路由映射配置注入AppNavigator的linking属性。
2.3 关键配置解读
源码中定义了导航状态持久化键与 Web 端深链接路由映射(app.tsx#L36-L57):
export const NAVIGATION_PERSISTENCE_KEY = "NAVIGATION_STATE" const prefix = Linking.createURL("/") const config = { screens: { Login: { path: "" }, Welcome: "welcome", Demo: { screens: { DemoShowroom: { path: "showroom/:queryIndex?/:itemIndex?" }, DemoDebug: "debug", DemoPodcastList: "podcast", DemoCommunity: "community", }, }, }, }可以看到 DemoShowroom 屏幕支持:queryIndex?与:itemIndex?两个可选路径参数,这为 Web 端分享链接与演示路由提供了基础。启动渲染结构(app.tsx#L96-L114)为SafeAreaProvider → KeyboardProvider → AuthProvider → ThemeProvider → AppNavigator,其中AuthProvider与键盘控制器(react-native-keyboard-controller)分别负责鉴权上下文与键盘避让。
:::tip 开发模式下app.tsx顶部还会通过require("./devtools/ReactotronConfig.ts")加载 Reactotron 调试配置,前提是 metro 的inlineRequires保持开启。 :::
三、components:内置的轻量设计系统
components 目录内置了一套可高度定制的组件集,官方将其定位为"轻量设计系统"——强调灵活性与可定制性,优先于开箱即用的强大程度。它适用于完全自定义的设计风格;如果你需要现成的成熟 UI 方案,也可搭配 UI Kitten、RN Elements 等第三方库。
各组件要点与典型用法如下(详细文档见 Components.md):
- AutoImage:React Native
Image的封装,自动缩放图片以适配容器。<AutoImage source={{ uri: "https://..." }} />,详见 AutoImage.md; - Button:基于
TouchableOpacity的按钮,支持text/tx(国际化键)、preset、style、textStyle等属性,也可通过 children 自定义内容,详见 Button.md; - Card:用于纵向展示相关信息的容器,支持
preset、verticalAlignment、heading、content、footer及各自的样式与文本属性,详见 Card.md; - Checkbox / Radio / Switch:三种布尔值选择组件,均支持
value、onValueChange、labelTx、labelStyle、containerStyle,其中 Switch 还支持accessibilityMode="icon",分别见 Checkbox.md、Radio.md、Switch.md; - EmptyState:无数据时的占位引导组件,可配置图片(
imageSource)、标题、正文与按钮,见 EmptyState.md; - Header:屏幕顶栏,承载导航按钮与标题,支持
leftIcon/rightIcon、onLeftPress/onRightPress,见 Header.md; - Icon:图标渲染组件,支持
icon、color、size、containerStyle与onPress,见 Icon.md; - Screen:屏幕容器,统一处理滚动、安全区与键盘避让,如
<Screen preset="scroll">,见 Screen.md; - Text:增强版文本组件,加入国际化(
tx/txOptions)与属性预设(preset="header"),见 Text.md; - TextField:由
TextInput与标签组成的输入框,支持value、onChangeText、labelTx、placeholderTx、forwardedRef等,见 TextField.md。
当内置组件无法满足需求时,可借助 Ignite CLI 的组件生成器创建自定义组件:
npx ignite-cli generate component MyCustomButton生成器会在app/components下创建MyCustomButton.tsx,对应的模板位于 ignite/templates/component/NAME.tsx.ejs,其生成逻辑可查看 src/tools/generators.ts。
四、config:开发与生产环境配置
config 目录根据是否处于__DEV__模式,在开发与生产配置之间切换导入:
- config.base.ts:开发与生产共享的配置,例如
exitRoutes——用于标记哪些路由属于"退出路由"(用户可从该路由退出应用); - config.dev.ts:开发专属配置,例如指向开发环境的 API URL;
- config.prod.ts:生产专属配置;
- index.ts:按模式导出对应配置的入口。
⚠️安全提醒:这些配置文件不应被 gitignore。与服务端不同,客户端应用最终打包的是一个包含全部配置变量的 JavaScript bundle,任何下载了 App 的用户都能轻易提取其中的明文变量。官方给出的验证方法是:打包后直接在 bundle 中搜索某个配置变量值即可找到。敏感信息的安全存储方式请参考 React Native 官方安全文档。
五、devtools:Reactotron 调试配置
devtools 目录预置了 Reactotron 调试支持,同时兼容 Web 与移动端。核心文件 ReactotronConfig.ts 内置了若干实用插件与命令。
官方还提供了通过reactotron.onCustomCommand添加自定义调试命令的范式(见 Devtools.md):
reactotron.onCustomCommand({ title: "Reset Navigation State", description: "Resets the navigation state", command: "resetNavigation", handler: () => { Reactotron.log("resetting navigation state") resetRoot({ index: 0, routes: [] }) }, })注意 ReactotronClient.ts 与 ReactotronClient.web.ts 分别对应原生与 Web 平台,由平台解析自动选择。
六、i18n:多语言国际化
i18n 目录基于 i18next 搭建国际化体系,默认支持英语、阿拉伯语、韩语、法语、日语与印地语,应用启动时自动检测语言并切换。由于内置了阿拉伯语这一 RTL(从右到左)语言,后续新增任何 RTL 语言都能开箱即用。
如需移除 RTL 支持,官方给出了三步操作:
- 在 i18n/index.ts 中删除 RTL 语言导入、对应的语言对象引用,以及原生层允许/强制 RTL 的两行代码:
I18nManager.allowRTL(isRTL) I18nManager.forceRTL(isRTL)- 删除所有使用导出变量
isRTL的相关逻辑; - 将组件中的
tx="some:i18n.key"全部替换为text="Some Text"(如<Text text="Some Text" />)。
新增语言时,参照 i18next 官方文档在app/i18n/index.ts中注册对应翻译资源即可。
七、context:React Context 与状态管理
context 目录用于存放 React Context Provider 或任何你选择的状态管理方案。历史上 Ignite 曾默认内置 mobx-state-tree(MST),但随着团队项目状态管理方案的多样化,样板工程已改为默认使用简单 React Context。
当前目录内置两个示例 Context:
- AuthContext:提供演示应用的简易鉴权状态管理,通过 MMKV Hooks 持久化数据,应用通过
useAuthHook 消费; - EpisodeContext:管理演示播客屏幕中的剧集列表,提供
useEpisodesHook 用于拉取剧集并维护列表状态。
对于更复杂的应用,文档也列出了可选的状态管理方案:Redux Toolkit、MobX、MobX State Tree、Zustand、Legend State、React Query(TanStack Query)、XState 等,可按项目复杂度取舍。
八、navigators:导航体系
8.1 基础结构
Ignite 当前版本使用React Navigation v7,所有导航器位于 navigators 目录,核心文件为 AppNavigator.tsx。另有 navigationUtilities.ts 提供实用函数:getActiveRouteName、useBackButtonHandler、useNavigationPersistence等。
创建新导航器可使用 CLI 生成器:
npx ignite-cli generate navigator MyNavigator模板见 ignite/templates/navigator/NAMENavigator.tsx.ejs。
8.2 鉴权流程模式
Ignite 遵循 React Navigation 官方的 Authentication Flows 模式,示例代码如下(详见 Navigation.md):
const AppStack = () => { const { isAuthenticated } = useAuth() return ( <Stack.Navigator screenOptions={{ headerShown: false }} initialRouteName={isAuthenticated ? "Welcome" : "Login"} > {isAuthenticated ? ( <> <Stack.Screen name="Welcome" component={WelcomeScreen} /> <Stack.Screen name="Demo" component={DemoNavigator} /> </> ) : ( <> <Stack.Screen name="Login" component={LoginScreen} /> </> )} </Stack.Navigator> ) }未登录时导航器中仅包含LoginScreen;登录后LoginScreen被移出,用户进入WelcomeScreen与DemoNavigator下的各屏幕。
8.3 Tab 导航与嵌套
底部 Tab 导航定义在 DemoNavigator.tsx 中,可通过常规 navigation API 编程式切换 Tab:
navigation.navigate("DemoDebug")Tab 既可指向单个屏幕,也可指向一个嵌套的 Stack 导航器(例如"收件箱"场景:Tab 内先展示列表,点击进入消息详情):
const InboxStack = createNativeStackNavigator() function InboxStackScreen() { return ( <InboxStack.Navigator> <InboxStack.Screen name="List" component={ListScreen} /> <InboxStack.Screen name="MessageDetails" component={MessageDetailsScreen} /> </InboxStack.Navigator> ) }再以<Tab.Screen name="Inbox" component={InboxStackScreen} />将其挂入 Tab 导航器即可。
8.4 侧边抽屉导航
Ignite 内置了基于 React Native Gesture Handler 的DrawerLayout实现的抽屉导航示例,它是 RN 原生DrawerLayoutAndroid的跨平台替代方案。通过renderNavigationView属性传入侧边栏内容,可放置公司 Logo、用户头像、菜单项、退出登录等;DrawerLayout还支持自定义开关速度、遮罩位置,并提供过渡进度/状态事件。
8.5 关于 Expo Router
官方说明:团队正在评估 Expo Router(基于 React Navigation 构建),其哲学是"任何方案都必须在至少一个完整项目中验证后才进入 Ignite"。目前脚手架提供了切换到 Expo Router 的实验性选项。本仓库的 src/app/_layout.tsx 与 src/app/index.tsx 即为实验性的 Expo Router 入口示例。
九、screens:屏幕层
screens 目录存放应用的主要屏幕,每个屏幕文件以Screen.tsx结尾(如LoginScreen.tsx),也可放入子文件夹,但官方建议尽量保持扁平。
屏幕是应用交互的核心:负责渲染 UI/状态、样式、处理用户输入,并触发向其他屏幕的导航。官方还推荐将屏幕专属组件与屏幕同目录存放:例如仅登录屏使用的LoginForm可放在app/screens/login/LoginForm.tsx;若组件被多个屏幕复用,则放入components目录。这一约定可从 DemoShowroomScreen 目录下的 demos 子目录结构得到印证。
十、services:服务层与 API 客户端
services 目录放置负责特定任务的代码:API 调用、文件系统交互、推送通知等。样板工程仅内置一个 API 客户端服务,你可按需添加更多。
Ignite 刻意不对后端技术栈做绑定(REST、GraphQL、Firebase、Hasura、tRPC、Supabase 等均可),但内置了一套经过大型项目验证的 API 模式:
- HTTP 客户端:内置 apisauce——Infinite Red 维护的、基于 Axios 的轻量封装,比 RN 内置
fetch提供更顺滑的开发体验; - Api 类:定义于 services/api/index.ts,是添加后端数据获取方法的位置;配套的 apiProblem.ts 提供标准化的 API 问题/错误建模,并有 apiProblem.test.ts 测试覆盖;
- TanStack Query:官方表示正在评估,待更多项目验证后再考虑纳入。
十一、theme 与 utils:视觉体系与工具集
theme(Theming.md):集中管理应用的视觉体系,包括颜色(colors.ts 与暗色模式 colorsDark.ts)、间距(spacing.ts)、排版(typography.ts)、时间与动画(timing.ts)。主题上下文由 context.tsx 提供,支持明暗主题切换。
utils(Utils.md):存放通用工具函数与自定义 Hooks,从目录可以看到以下开箱即用的能力:
- storage:基于 MMKV 的键值存储封装(含 storage.test.ts 测试);
- useHeader.tsx:在任意屏幕便捷设置 Header 的 Hook;
- useSafeAreaInsetsStyle.ts:安全区 inset 样式计算;
- formatDate.ts、delay.ts、openLinkInBrowser.ts 等常用工具。
十二、快速上手建议
- 先读入口:通读 app.tsx,理解启动链路上字体、i18n、导航恢复、安全区与深链接的协作顺序;
- 按目录定位:新 UI 组件进
components,屏幕进screens,API 进services/api,公共函数进utils,遵循"目录即职责"的约定; - 善用生成器:用
npx ignite-cli generate快速生成 component / screen / navigator,模板见 ignite/templates; - 复用导航模式:鉴权流程、Tab 嵌套、抽屉导航均有现成示例可参考,并配合 navigationUtilities.ts 的
useBackButtonHandler、useNavigationPersistence提升开发效率。
结语
app目录是 Ignite 样板工程的心脏:一个清晰可扩展的入口文件,加上按职责划分的十个子模块,构成了经过 9 年持续迭代验证的项目组织范式。理解这套结构,不仅能让你快速上手基于 Ignite 的项目,也能为自建 React Native 工程的目录设计提供成熟参考。更多细节可继续查阅 Boilerplate.md 与各子目录的专项文档。
【免费下载链接】igniteInfinite Red's battle-tested React Native project boilerplate, along with a CLI, component/model generators, and more! 9 years of continuous development and counting.项目地址: https://gitcode.com/GitHub_Trending/ig/ignite
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考