
Folo 移动端开发实战指南从 Expo 工程搭建到源码架构解析【免费下载链接】follow Folo is the AI RSS Reader项目地址: https://gitcode.com/GitHub_Trending/fol/followFolo 移动端apps/mobile是 Folo AI RSS Reader 的 iOS/Android 客户端基于 Expo 与 React Native 构建把订阅、发现与 AI 能力统一进一条无干扰时间线。本文以 apps/mobile/README.md 为主体骨架结合仓库内真实源码与配置系统性讲解其快速上手、运行目标、目录结构与工程配置帮助读者从零跑通开发环境并读懂移动端代码组织方式。定位一个多内容形态的信息聚合客户端Folo 移动端作为 Folo 的客户端实现核心价值是把散落在 RSS 订阅源、动态内容与发现信息流里的内容聚合到同一时间线。按仓库 README 的产品定位其特性包括自定义信息中枢面向内容发现的信息聚合入口AI 能力如翻译、摘要等对应src/modules/ai/模块动态内容支持文章、视频、图片、音频等多元内容形态$POWER 创作者经济集成作为产品的社区经济层能力跨平台支持iOS 与 AndroidREADME 标注 Android 仍在开发中/WIP现代 UI 与原生质感依赖 NativeWind Apple UIKit 色彩体系实现。从依赖清单apps/mobile/package.json可以看到为实现音视频播放、后台任务与推送工程引入了expo-video支持后台播放与画中画、react-native-track-player、expo-notifications、expo-background-task等能力组件。技术栈与版本基线README 声明基于 Expo SDK 52而当前仓库实际锁定在更新的基线。结合 apps/mobile/package.json 可确认关注点实际版本/实现Expoexpo ~57.0.4入口src/main.tsx包名follow/mobile版本0.5.7React Nativereact-native 0.86.0React 19.2.7样式方案NativeWind4.2.6 TailwindCSS3.4.17状态管理Jotai2.20.1与 Zustand5.0.14并存服务端状态TanStack Querytanstack/react-query 5.x及持久化适配导航自定义 Stack/底部 Tab 导航容器基于react-native-screens见下文国际化i18next/react-i18next支持 en/ja/zh-CN/zh-TW/fr-FR数据本地化expo-sqliteapps/mobile/src/database/工程以 pnpm workspace 组织pnpm-workspace.yaml移动端大量复用follow/*系列内部包components、constants、store、utils、shared等与桌面端共享代码。需要说明README 将导航描述为基于 Expo Router但查看当前入口 src/main.tsx 可以发现实际运行的是src/lib/navigation下自定义的RootStackNavigation/BottomTabProvider/TabRoot组合构建在 react-native-screens 之上。阅读源码时以入口文件的实际导入为准。快速开始环境准备与启动命令README 的起步流程非常精简共三步。下面给出可直接执行的操作序列并逐个说明每个命令在 package.json 脚本表中的真实定义。# 1. 启用 Corepack如尚未启用用于锁定 pnpm 版本 corepack enable # 2. 在 monorepo 根目录安装依赖推荐在仓库根目录执行 pnpm install # 3. 启动 Expo 开发服务器 pnpm run dev其中pnpm run dev实际转发到npm run start而start的定义是expo start --dev-client——也就是说默认走Expo Dev Client模式而非 Expo Go。这一差异对跑在哪个平台影响很大README 强调需使用Development build开发构建包才能完整测试原生特性。相关脚本定义如下截取自 apps/mobile/package.json 的scripts字段命令实际定义用途pnpm run devnpm run start启动开发服务器pnpm run iosexpo run:ios在 iOS 模拟器构建并运行pnpm run ios:deviceexpo run:ios --device在真机 iOS 设备运行pnpm run androidexpo run:android在 Android 模拟器构建运行pnpm run start:cleanexpo start --dev-client --clear清空 Metro 缓存后启动pnpm run webexpo start --web以 Web 方式启动需配合 react-native-webpnpm run typechecktsc --noEmit全量 TypeScript 静态检查关于环境要求README 建议启用 Corepack若改动原生模块导致需要重新生成ios/、android/目录可参考 apps/mobile/AGENTS.md 中记录的pnpm expo prebuild --clean。首次原生构建前请确认本地具备 XcodeiOS与 Android SDK/模拟器Android。运行目标与平台说明README 列出的可运行目标是理解该工程最直接的一页地图iOS Simulatorpnpm run ios最常用的日常开发目标iOS Devicepnpm run ios:device真机联调用于验证推送、Apple 登录等真机能力Android Emulatorpnpm run androidAndroid 侧已具备完整构建链app.config中定义了is.follow包名、自适应图标与 google-services.json但按 README 定位Android 功能完善度仍标注为 WIPDevelopment build当涉及原生模块、推送、音频后台播放等能力时必须使用编译出的开发构建包而非 Expo Go。目录结构与模块划分README 只给出了src/modules与src/screens两层的示意。结合仓库实际展开移动端src/目录比 README 描述得更丰富apps/mobile/src/ ├── main.tsx # 应用真实入口注册根组件 ├── App.tsx # 根组件会话/推送/新手引导副作用容器 ├── types/ # 全局类型含当前支持语言等常量 ├── atoms/ # 原子状态定义 ├── components/ # 跨模块 UI 组件含 layouts、ui 等子目录 ├── constants/ # 常量 ├── database/ # expo-sqlite 本地库封装 ├── hooks/ # 通用 React Hooks ├── icons/ # 图标组件mgc 系列与仓库 icons/ 目录对应 ├── initialize/ # 启动期初始化管线 ├── lib/ # 基础设施API client、auth、i18n、navigation、query-client ├── modules/ # 业务功能模块feature modules ├── polyfill/ # 全局 Polyfill ├── providers/ # 全局 Provider 聚合 ├── screens/ # 页面按 (stack)/(tabs)/(modal)/(headless) 分组 ├── store/ # 全局 store ├── theme/ # 主题与色彩 ├── sitemap.tsx # 站内路由/导航注册表 └── global.cssREADME 中src/modules是特性模块层仓库实际已落地的主要子模块包括ai翻译/摘要等 AI 能力、discover发现流、entry-content/entry-list条目详情与列表、feed/list/subscription订阅源管理、login登录配合better-auth/expo、onboarding新手引导、player音频播放器、rsshubRSSHub 接入、settings、otaOTA 更新、debug调试面板仅在__DEV__显示、review-prompt应用评分引导与spotlight等。screens/则保留了类似文件路由的分组习惯(stack)下再分(tabs)主 Tab、entries、feeds、recommendation等页面另有(modal)、(headless)分组以及独立的OnboardingScreen与PlayerScreen。入口与主流程从 main.tsx 到 App.tsxsrc/main.tsx 是理解整个应用的起点。它依次完成引入global.css与 polyfill并通过cssInterop让Image、LinearGradient支持 className 式样式NativeWind 与 expo 组件的桥接向follow/store/context注入authClient、queryClient、followApi即authClientContext/queryClientContext/apiContext三个provide调用实现桌面端/移动端共享 store 上下文enableFreeze(true)开启 react-native-screens 的冻结优化initializeApp()走初始化管线registerSitemap()注册导航映射initializeI18n()初始化国际化最终registerRootComponent注册根组件根组件RootComponent以OtaProvider → RootProviders → BottomTabProvider → RootStackNavigation的层级包裹四个主 Tab 分别是 IndexTabScreen首页、SubscriptionsTabScreen订阅、DiscoverTabScreen发现、SettingsTabScreen设置每个 Tab 配有 i18n 标题与对应的选中/未选中图标。src/App.tsx 则承担启动副作用通过usePrefetchSessionUser预取会话未登录时跳转destination.Login()同时挂载角标刷新useUnreadCountBadge、Android 返回键处理useBackHandler、Intent 处理、新手引导useOnboarding、消息推送 Token 更新与消息监听useMessaging并用react-native-sheet-transitions的ScaleableWrapper实现底部弹层出现时的缩放交互动画。工程配置解析profile、Runtime Version 与 OTA 通道移动端真正的配置中枢不在 app.json而在 apps/mobile/app.config.base.ts。该文件按PROFILE环境变量动态组装 ExpoConfig是本工程最具复读价值的实战内容之一。Profile 与渠道映射const iconPathMap { production: resolve(__dirname, ./assets/icon.png), development: resolve(__dirname, ./assets/icon-dev.png), ios-simulator: resolve(__dirname, ./assets/icon-dev.png), preview: resolve(__dirname, ./assets/icon-staging.png), }profile 可选值及其含义PROFILE图标对应的 expo 更新渠道productionicon.pngproductiondevelopmenticon-dev.pngdevelopmentios-simulatoricon-dev.pngdevelopmentpreviewicon-staging.pngpreviewe2e-android/e2e-ios-simulatoricon-staging.pngpreview渠道名同时用于 OTA 请求头expo-channel-name把打包环境与可收到的 OTA 更新批次绑定起来。Runtime Version 解析规则export const resolveRuntimeVersion ({ isDevelopment, packageVersion, otaRuntimeVersionOverride }) { if (isDevelopment) return 0.0.0-dev if (otaRuntimeVersionOverride) { if (!semverPattern.test(otaRuntimeVersionOverride)) { throw new Error(Expected OTA_RUNTIME_VERSION to be a plain x.y.z version, got ${otaRuntimeVersionOverride}) } return otaRuntimeVersionOverride } return packageVersion }即开发环境固定为0.0.0-devCI 可通过OTA_RUNTIME_VERSION覆盖必须是标准x.y.z语义化版本否则直接取package.json版本号保证原生运行时版本与应用版本严格对齐——这正是 Code Push/Expo Updates 保证原生代码兼容性的关键。OTA 与签名updates: { url: https://ota.folo.is/manifest, requestHeaders: { expo-channel-name: channelName }, codeSigningCertificate: ./code-signing/certificate.pem, codeSigningMetadata: { keyid: main, alg: rsa-v1_5-sha256 }, checkAutomatically: NEVER, },OTA 服务端由仓库内apps/otamanifest 服务承载代码签名证书位于 apps/mobile/code-signing/certificate.pemalg: rsa-v1_5-sha256说明 OTA 包使用 RSA 签名校验。checkAutomatically: NEVER表示不自动检查更新改由客户端在src/modules/ota/中按需拉取——仓库同样在ota模块中提供了 UI 层面的更新提示对应 OTA provider。平台配置要点iOSbundle idis.follow支持 Apple 登录Info.plist 声明新闻类 App 分类、后台音频模式UIBackgroundModes: [audio]、可打开的 URL schemebilibili/youtube本地化覆盖 en/ja/zh-CN/zh-TW/fr-FRAndroid包名同为is.follow自适应图标主色#FF5C00接入google-services.jsonFirebaseURL scheme[follow, folo]配合expo-linking与src/lib/navigation/biz/Destination.ts实现外部跳转路由。配置插件链app.config.base.ts的plugins数组展示了项目如何用 Expo Config Plugin 定制原生工程expo-build-propertiesiOS deployment target 16.4、静态链接 RNFB 系 Firebase 模块、expo-video后台播放 画中画、expo-notifications后台远程通知、expo-media-library相册读写权限文案、expo-splash-screen以及仓库自研插件with-follow-assets.js把out/rn-web产物拷贝进 App Bundle 的 Assets、with-follow-ios-resources.js、with-gradle-jvm-heap-size-increase.js、with-android-jdk-21.js、with-android-manifest-plugin.js等。非生产 profile 还会追加android-trust-user-certs.js便于调试环境信任用户证书。初始化管线与后台能力README 未展开的启动初始化逻辑集中在 apps/mobile/src/initializeindex.ts会串起整个初始化管线hydrate.tsJotai/Zustand 状态持久化水合migration.tsexpo-sqlite 本地库的 schema 迁移analytics.tsPostHog 与 Firebase Analytics 埋点app-check.tsFirebase App Check防滥用device.ts设备信息采集react-native-device-infobackground.ts/player.ts后台任务与音频播放初始化dayjs.ts日期库 locale 装配。这些能力与依赖清单互相印证推送走 Firebase Messagingreact-native-firebase/messagingexpo-notifications后台拉取用expo-background-task登录与会话用better-auth/expoexpo-secure-store。原生模块、自定义插件与质量保障移动端并非纯 JS 工程原生定制代码位于 apps/mobile/nativeandroid/kt 与 ios/swift 两份实现配套expo-module.config.json与 Podspec通过app.config.base.ts中的autolinking.nativeModulesDir: ./native挂载。HTML 渲染如正文阅读则放在 apps/mobile/web-app/html-renderer与expo/dom-webview配合在 WebView 内完成排版渲染。测试与发布脚本同样沉淀在 package.json 中iOS/Android 的 Maestro E2E 由e2e/run-maestro.sh驱动pnpm run e2e:ios/e2e:androidyaml 用例在 apps/mobile/e2e/flows语法校验可用e2e:doctorpnpm run update:export执行expo export生成 OTA bundleupdate:bundle对接scripts/build-ota-release.mjs走发布流水线eas-build-pre-install/eas-build-post-install处理 EAS 云构建的前置pod repo update与后置清理 Metro 缓存步骤。UI 体系NativeWind 之上的原生质感移动端样式的关键约定记录在 apps/mobile/AGENTS.mdReact Native 组件一律使用 Apple UIKit 色彩体系对应的 Tailwind 类例如背景类system-background、system-grouped-background文本类label、secondary-label填充类system-fill等语义色red/orange/mint/teal/indigo...与灰度gray到gray6会随系统明暗模式自动适配。配合react-native-uikit-colors与 packages/configs/tailwindcss 中的扩展插件移动端得以复用桌面端Electron Tailwind的近似的设计 token形成统一观感。适合继续深入的文件清单如果想沿着本文继续深入推荐按以下路径阅读源码入口与导航apps/mobile/src/main.tsx、apps/mobile/src/App.tsx工程配置apps/mobile/app.config.base.ts、apps/mobile/package.json初始化管线apps/mobile/src/initialize业务模块样例apps/mobile/src/modules/ai、apps/mobile/src/modules/player、apps/mobile/src/modules/ota原生与渲染apps/mobile/native、apps/mobile/web-app/html-renderer开发约定apps/mobile/AGENTS.md。Folo 移动端是一个Expo 工程化最佳实践样本用 PROFILE 区分多环境、以 runtime version 精确绑定 OTA、将原生定制收敛为 Config Plugin、再以 pnpm workspace 在桌面与移动端之间复用同一套数据层与组件。无论是想跑通 Folo 移动端做二次开发还是想参考一个大型 Expo monorepo 的工程组织方式apps/mobile 都值得通读。许可说明本应用以 GNU AGPL v3 授权发布完整许可信息见仓库 LICENSE 与根目录 README.md。【免费下载链接】follow Folo is the AI RSS Reader项目地址: https://gitcode.com/GitHub_Trending/fol/follow创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考