尧图精选

React Native 架构实战:Expo 路由、认证、离线优先与原生集成的生产级模式——agents 仓库 react-native-architecture 技能全解

🕒 发布时间:2026/9/10 13:04:49 📁 来源:尧图网络
React Native 架构实战Expo 路由、认证、离线优先与原生集成的生产级模式——agents 仓库 react-native-architecture 技能全解【免费下载链接】agentsMulti-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity项目地址: https://gitcode.com/GitHub_Trending/agents24/agents本篇技术指南以 agents 仓库中frontend-mobile-development插件的react-native-architecture技能为核心系统拆解六个可直接复用的生产级 React Native / Expo 架构模式Expo Router 导航、认证流程、离线优先数据层、原生模块集成、平台特定代码与列表性能优化并覆盖从 EAS 云构建到应用商店提交、OTA 更新的完整发布链路。读完本文你将获得一套可复制、可运行的 TypeScript 工程骨架以及支撑其落地的源码级原理依据可直接套用到电商、社交、企业移动端等真实项目。技能定位渐进式披露的 React Native 架构知识库该技能位于 plugins/frontend-mobile-development/skills/react-native-architecture/ 目录下遵循 Agent Skills 规范详见 docs/agent-skills.md的**渐进式披露Progressive Disclosure**三层结构组织知识元数据层SKILL.md的 YAML frontmatter 声明技能名称与激活条件指令层SKILL.md正文承载核心概念、快速启动与最佳实践资源层references/details.md 存放详细模式与完整可运行示例仅在顶层指令不足时按需加载。SKILL.md的 frontmatter 明确给出了技能的能力边界与激活时机--- name: react-native-architecture description: Build production React Native apps with Expo, navigation, native modules, offline sync, and cross-platform patterns. Use when developing mobile apps, implementing native integrations, or architecting React Native projects. ---其典型使用场景When to Use包括启动新的 React Native / Expo 项目、实现复杂导航模式、集成原生模块与平台 API、构建离线优先应用、优化 React Native 性能以及为移动端发布搭建 CI/CD。SKILL.md同时声明当顶层导航指令不足时应读取references/details.md——这正是本文要深入展开的主体。工程基础目录结构与 Expo 技术选型推荐的项目结构SKILL.md给出了一套以功能与关注点分离为原则的目录骨架与details.md中的各个模式一一对应src/ ├── app/ # Expo Router screens │ ├── (auth)/ # Auth group │ ├── (tabs)/ # Tab navigation │ └── _layout.tsx # Root layout ├── components/ │ ├── ui/ # Reusable UI components │ └── features/ # Feature-specific components ├── hooks/ # Custom hooks ├── services/ # API and native services ├── stores/ # State management ├── utils/ # Utilities └── types/ # TypeScript types关键设计决策app/目录即路由Expo Router 以文件系统作为路由表(auth)、(tabs)等括号目录表示路由分组Route Group不产生 URL 路径段仅用于组织布局hooks/与services/分离数据获取React Query hooks与原生能力封装haptics、biometrics、notifications分层解耦便于测试与替换components/ui与components/features分层通用 UI 基元与业务组件隔离支撑跨页面复用。Expo vs Bare React Native如何选型SKILL.md给出的对比表是架构决策的第一道关口FeatureExpoBare RNSetup complexityLowHighNative modulesEAS BuildManual linkingOTA updatesBuilt-inManual setupBuild serviceEASCustom CICustom native codeConfig pluginsDirect access从该对比可以得出选型倾向团队需要快速迭代、OTA 热更新、托管构建EAS时优先选 Expo需要直接编写 Swift/Kotlin 原生代码或深度定制原生工程时再考虑 Bare RN。技能体系内的details.md模式均建立在 Expo 生态之上expo-router、expo-secure-store、expo-haptics、expo-local-authentication、expo-notifications 等与本仓库中 mobile-developer.md 强调的Expo SDK 50 with development builds and EAS services能力保持一致。快速启动创建项目与安装依赖# Create new Expo project npx create-expo-applatest my-app -t expo-template-blank-typescript # Install essential dependencies npx expo install expo-router expo-status-bar react-native-safe-area-context npx expo install react-native-async-storage/async-storage npx expo install expo-secure-store expo-hapticsnpx expo install会自动选择与当前 SDK 兼容的依赖版本避免手工对齐版本带来的构建问题。上述依赖恰好覆盖了details.md六个模式所需的全部基础库路由expo-router、安全存储expo-secure-store、离线缓存async-storage与触感反馈expo-haptics。项目根布局是后续所有 Provider 的挂载点// app/_layout.tsx import { Stack } from expo-router import { ThemeProvider } from /providers/ThemeProvider import { QueryProvider } from /providers/QueryProvider export default function RootLayout() { return ( QueryProvider ThemeProvider Stack screenOptions{{ headerShown: false }} Stack.Screen name(tabs) / Stack.Screen name(auth) / Stack.Screen namemodal options{{ presentation: modal }} / /Stack /ThemeProvider /QueryProvider ) }Provider 的嵌套顺序有讲究QueryProvider在最外层保证数据层先于 UI 就绪(tabs)与(auth)作为两个互斥的路由分组并列modal屏幕以presentation: modal声明模态呈现方式。Pattern 1Expo Router 导航——Tab 布局、动态路由与编程式导航details.md的第一个模式完整展示了 Tab 导航、动态路由与编程式导航三种能力。带主题的 Tab 布局// app/(tabs)/_layout.tsx import { Tabs } from expo-router import { Home, Search, User, Settings } from lucide-react-native import { useTheme } from /hooks/useTheme export default function TabLayout() { const { colors } useTheme() return ( Tabs screenOptions{{ tabBarActiveTintColor: colors.primary, tabBarInactiveTintColor: colors.textMuted, tabBarStyle: { backgroundColor: colors.background }, headerShown: false, }} Tabs.Screen nameindex options{{ title: Home, tabBarIcon: ({ color, size }) Home size{size} color{color} /, }} / Tabs.Screen namesearch options{{ title: Search, tabBarIcon: ({ color, size }) Search size{size} color{color} /, }} / Tabs.Screen nameprofile options{{ title: Profile, tabBarIcon: ({ color, size }) User size{size} color{color} /, }} / Tabs.Screen namesettings options{{ title: Settings, tabBarIcon: ({ color, size }) Settings size{size} color{color} /, }} / /Tabs ) }要点解析Tabs.Screen的name必须与app/(tabs)/下的文件名一致Expo Router 据此自动建立映射screenOptions支持统一配置激活/未激活的着色tabBarActiveTintColor/tabBarInactiveTintColor、Tab 栏背景与全局隐藏 header颜色全部来自useTheme()保证暗色模式切换时 Tab 栏同步联动tabBarIcon回调接收{ color, size }直接透传给lucide-react-native图标组件无需额外样式代码。动态路由// app/(tabs)/profile/[id].tsx - Dynamic route import { useLocalSearchParams } from expo-router export default function ProfileScreen() { const { id } useLocalSearchParams{ id: string }() return UserProfile userId{id} / }[id]方括号文件名即动态段。useLocalSearchParams{ id: string }()通过泛型获得类型安全的参数解析/profile/123会命中该屏幕并将id解析为123。编程式导航// Navigation from anywhere import { router } from expo-router // Programmatic navigation router.push(/profile/123) router.replace(/login) router.back() // With params router.push({ pathname: /product/[id], params: { id: 123, referrer: home }, })与声明式Link相比router单例适合在事件回调、异步流程后触发跳转。router.replace用于替换当前历史栈典型场景是登录成功后防止返回登录页带参数跳转时pathname使用[id]占位语法params中的其余键如referrer会作为查询参数附加。Pattern 2认证流程——Context SecureStore 路由守卫第二个模式给出了一个端到端可用的认证骨架AuthProvider统一管理登录态expo-secure-store持久化令牌useSegments监听当前路由段实现声明式路由守卫。// providers/AuthProvider.tsx import { createContext, useContext, useEffect, useState } from react import { useRouter, useSegments } from expo-router import * as SecureStore from expo-secure-store interface AuthContextType { user: User | null isLoading: boolean signIn: (credentials: Credentials) Promisevoid signOut: () Promisevoid } const AuthContext createContextAuthContextType | null(null) export function AuthProvider({ children }: { children: React.ReactNode }) { const [user, setUser] useStateUser | null(null) const [isLoading, setIsLoading] useState(true) const segments useSegments() const router useRouter() // Check authentication on mount useEffect(() { checkAuth() }, []) // Protect routes useEffect(() { if (isLoading) return const inAuthGroup segments[0] (auth) if (!user !inAuthGroup) { router.replace(/login) } else if (user inAuthGroup) { router.replace(/(tabs)) } }, [user, segments, isLoading]) async function checkAuth() { try { const token await SecureStore.getItemAsync(authToken) if (token) { const userData await api.getUser(token) setUser(userData) } } catch (error) { await SecureStore.deleteItemAsync(authToken) } finally { setIsLoading(false) } } async function signIn(credentials: Credentials) { const { token, user } await api.login(credentials) await SecureStore.setItemAsync(authToken, token) setUser(user) } async function signOut() { await SecureStore.deleteItemAsync(authToken) setUser(null) } if (isLoading) { return SplashScreen / } return ( AuthContext.Provider value{{ user, isLoading, signIn, signOut }} {children} /AuthContext.Provider ) } export const useAuth () { const context useContext(AuthContext) if (!context) throw new Error(useAuth must be used within AuthProvider) return context }这套模式的关键设计令牌用SecureStore而非 AsyncStorageexpo-secure-store将数据存入 iOS Keychain / Android Keystore适合令牌这类高敏数据AsyncStorage 仅适合非敏感缓存路由守卫是声明式的第二个useEffect监听segments[0]判断是否处于(auth)分组。未登录且不在 auth 分组时重定向到/login已登录却停留在 auth 分组时重定向到/(tabs)。isLoading为 true 时直接短路返回避免启动期闪现错误页面checkAuth三态处理有令牌则拉取用户信息令牌失效则清理存储无论成功失败最终都退出 loading 状态。finally保证isLoading必然被置为 false防止启动画面卡死自定义 Hook 带防御性校验useAuth在 Provider 外使用时直接抛错帮助尽早发现 Provider 嵌套层级错误。启动期渲染SplashScreen /替代白屏是移动端启动体验的常见做法。该模式与同插件 component-scaffold.md 中accessible、type-safe的组件生成理念相互呼应。Pattern 3离线优先——React Query 持久化、在线状态同步与乐观更新第三个模式把tanstack/react-query升级为离线优先offline-first数据层查询结果持久化到 AsyncStorage、网络状态实时同步、写操作乐观更新并支持失败回滚。Provider网络监听 持久化// providers/QueryProvider.tsx import { QueryClient, QueryClientProvider } from tanstack/react-query import { createAsyncStoragePersister } from tanstack/query-async-storage-persister import { PersistQueryClientProvider } from tanstack/react-query-persist-client import AsyncStorage from react-native-async-storage/async-storage import NetInfo from react-native-community/netinfo import { onlineManager } from tanstack/react-query // Sync online status onlineManager.setEventListener((setOnline) { return NetInfo.addEventListener((state) { setOnline(!!state.isConnected) }) }) const queryClient new QueryClient({ defaultOptions: { queries: { gcTime: 1000 * 60 * 60 * 24, // 24 hours staleTime: 1000 * 60 * 5, // 5 minutes retry: 2, networkMode: offlineFirst, }, mutations: { networkMode: offlineFirst, }, }, }) const asyncStoragePersister createAsyncStoragePersister({ storage: AsyncStorage, key: REACT_QUERY_OFFLINE_CACHE, }) export function QueryProvider({ children }: { children: React.ReactNode }) { return ( PersistQueryClientProvider client{queryClient} persistOptions{{ persister: asyncStoragePersister }} {children} /PersistQueryClientProvider ) }参数语义详解这些配置直接决定离线体验gcTime: 24h缓存数据在内存中的保留时长React Query v5 中由cacheTime更名而来。设为 24 小时意味着用户一天内反复进入页面都不需要重新请求staleTime: 5min数据在 5 分钟内被视为新鲜期间命中缓存的查询不会触发后台重新请求显著减少弱网环境的请求次数retry: 2失败自动重试 2 次兼顾弱网自愈与请求风暴控制networkMode: offlineFirst查询/变更在离线时优先走缓存不因无网络直接失败配合onlineManager的NetInfo监听网络恢复后 React Query 会自动重放待执行请求createAsyncStoragePersister将查询缓存落盘到 AsyncStorage实现杀进程重启后缓存仍在的冷启动离线能力key参数用于隔离存储命名空间。数据 Hook读stale-while-revalidate// hooks/useProducts.ts import { useQuery, useMutation, useQueryClient } from tanstack/react-query export function useProducts() { return useQuery({ queryKey: [products], queryFn: api.getProducts, // Use stale data while revalidating placeholderData: (previousData) previousData, }) }placeholderData: (previousData) previousData实现stale-while-revalidate重新拉取新数据期间先用上一次的数据渲染页面不会闪空白。写 Hook乐观更新 失败回滚export function useCreateProduct() { const queryClient useQueryClient() return useMutation({ mutationFn: api.createProduct, // Optimistic update onMutate: async (newProduct) { await queryClient.cancelQueries({ queryKey: [products] }) const previous queryClient.getQueryData([products]) queryClient.setQueryData([products], (old: Product[]) [ ...old, { ...newProduct, id: temp- Date.now() }, ]) return { previous } }, onError: (err, newProduct, context) { queryClient.setQueryData([products], context?.previous) }, onSettled: () { queryClient.invalidateQueries({ queryKey: [products] }) }, }) }乐观更新的完整闭环onMutate先cancelQueries取消在途请求避免竞态快照旧数据再以临时 idtemp- Date.now()将新条目立即写入本地缓存——用户看到的是即时反馈onError请求失败时用context?.previous快照回滚缓存界面自动恢复到提交前状态onSettled无论成败都invalidateQueries使[products]缓存失效触发一次真实的服务器数据同步。Pattern 4原生模块集成——触感、生物识别与推送通知第四个模式展示了如何通过 Expo 模块优雅封装三类高频原生能力且统一以services/目录隔离方便在 web 端降级或替换实现。触感反馈Haptics// services/haptics.ts import * as Haptics from expo-haptics; import { Platform } from react-native; export const haptics { light: () { if (Platform.OS ! web) { Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light); } }, medium: () { if (Platform.OS ! web) { Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Medium); } }, heavy: () { if (Platform.OS ! web) { Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Heavy); } }, success: () { if (Platform.OS ! web) { Haptics.notificationAsync(Haptics.NotificationFeedbackType.Success); } }, error: () { if (Platform.OS ! web) { Haptics.notificationAsync(Haptics.NotificationFeedbackType.Error); } }, };ImpactFeedbackStyleLight / Medium / Heavy用于物理碰撞类反馈按钮按下、下拉刷新NotificationFeedbackTypeSuccess / Error 等用于结果反馈。每个方法都先做Platform.OS ! web守卫因为 web 端没有原生触感 API统一出口保证调用方无需关心平台差异。生物识别认证// services/biometrics.ts import * as LocalAuthentication from expo-local-authentication; export async function authenticateWithBiometrics(): Promiseboolean { const hasHardware await LocalAuthentication.hasHardwareAsync(); if (!hasHardware) return false; const isEnrolled await LocalAuthentication.isEnrolledAsync(); if (!isEnrolled) return false; const result await LocalAuthentication.authenticateAsync({ promptMessage: Authenticate to continue, fallbackLabel: Use passcode, disableDeviceFallback: false, }); return result.success; }三阶段防御式调用先查硬件hasHardwareAsync→再查录入状态isEnrolledAsync→最后发起认证authenticateAsync。disableDeviceFallback: false允许用户在指纹/Face ID 失败后回退到设备密码避免用户被锁死。推送通知// services/notifications.ts import * as Notifications from expo-notifications; import { Platform } from react-native; import Constants from expo-constants; Notifications.setNotificationHandler({ handleNotification: async () ({ shouldShowAlert: true, shouldPlaySound: true, shouldSetBadge: true, }), }); export async function registerForPushNotifications() { let token: string | undefined; if (Platform.OS android) { await Notifications.setNotificationChannelAsync(default, { name: default, importance: Notifications.AndroidImportance.MAX, vibrationPattern: [0, 250, 250, 250], }); } const { status: existingStatus } await Notifications.getPermissionsAsync(); let finalStatus existingStatus; if (existingStatus ! granted) { const { status } await Notifications.requestPermissionsAsync(); finalStatus status; } if (finalStatus ! granted) { return null; } const projectId Constants.expoConfig?.extra?.eas?.projectId; token (await Notifications.getExpoPushTokenAsync({ projectId })).data; return token; }关键点setNotificationHandler在 App 前台时自定义通知呈现行为弹窗、声音、角标Android 8.0 强制要求通知渠道ChannelsetNotificationChannelAsync以AndroidImportance.MAX与自定义振动模式[0, 250, 250, 250]创建default渠道权限流程采用读取现状 → 按需申请 → 复核最终状态三步未授权返回null由调用方决定降级策略getExpoPushTokenAsync需要 EAS projectIdprojectId从Constants.expoConfig?.extra?.eas?.projectId读取——即eas.json之外的app.json中由 EAS 注入的配置与下文 EAS 章节形成闭环。Pattern 5平台特定代码——动画按钮、文件后缀与 Platform.select第五个模式给出一个兼具 Reanimated 动画、触感反馈与平台差异化样式的跨平台按钮并总结三种平台定制手段。// components/ui/Button.tsx import { Platform, Pressable, StyleSheet, Text, ViewStyle } from react-native import * as Haptics from expo-haptics import Animated, { useAnimatedStyle, useSharedValue, withSpring, } from react-native-reanimated const AnimatedPressable Animated.createAnimatedComponent(Pressable) interface ButtonProps { title: string onPress: () void variant?: primary | secondary | outline disabled?: boolean } export function Button({ title, onPress, variant primary, disabled false, }: ButtonProps) { const scale useSharedValue(1) const animatedStyle useAnimatedStyle(() ({ transform: [{ scale: scale.value }], })) const handlePressIn () { scale.value withSpring(0.95) if (Platform.OS ! web) { Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light) } } const handlePressOut () { scale.value withSpring(1) } return ( AnimatedPressable onPress{onPress} onPressIn{handlePressIn} onPressOut{handlePressOut} disabled{disabled} style{[ styles.button, styles[variant], disabled styles.disabled, animatedStyle, ]} Text style{[styles.text, styles[${variant}Text]]}{title}/Text /AnimatedPressable ) } // Platform-specific files // Button.ios.tsx - iOS-specific implementation // Button.android.tsx - Android-specific implementation // Button.web.tsx - Web-specific implementation // Or use Platform.select const styles StyleSheet.create({ button: { paddingVertical: 12, paddingHorizontal: 24, borderRadius: 8, alignItems: center, ...Platform.select({ ios: { shadowColor: #000, shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4, }, android: { elevation: 4, }, }), }, primary: { backgroundColor: #007AFF, }, secondary: { backgroundColor: #5856D6, }, outline: { backgroundColor: transparent, borderWidth: 1, borderColor: #007AFF, }, disabled: { opacity: 0.5, }, text: { fontSize: 16, fontWeight: 600, }, primaryText: { color: #FFFFFF, }, secondaryText: { color: #FFFFFF, }, outlineText: { color: #007AFF, }, })本模式蕴含三种平台差异化策略按粒度从粗到细平台后缀文件Button.ios.tsx/Button.android.tsx/Button.web.tsx——当 iOS、Android、Web 三端实现差异较大如完全不同的交互范式时Metro 打包器按平台自动解析同名后缀文件调用方代码无需任何分支Platform.select同一文件内按平台返回不同配置。示例中 iOS 用shadow*系列iOS 无 elevationAndroid 用elevation: 4一套样式两种平台语义运行时分支Platform.OS代码逻辑层判断如handlePressIn中 web 端跳过触感反馈。动画层面useSharedValue(1)声明共享值withSpring提供弹性动画useAnimatedStyle将共享值映射到样式——Reanimated 的动画运行在 UI 线程而非 JS 线程这是保持 60fps 的关键。注意Animated.createAnimatedComponent(Pressable)将普通组件升级为可承载动画的组件。Pattern 6列表性能优化——FlashList 与渲染节流第六个模式解决移动端最典型的性能痛点长列表滚动卡顿。方案组合是FlashList memo useCallback FastImage。// components/ProductList.tsx import { FlashList } from shopify/flash-list import { memo, useCallback } from react interface ProductListProps { products: Product[] onProductPress: (id: string) void } // Memoize list item const ProductItem memo(function ProductItem({ item, onPress, }: { item: Product onPress: (id: string) void }) { const handlePress useCallback(() onPress(item.id), [item.id, onPress]) return ( Pressable onPress{handlePress} style{styles.item} FastImage source{{ uri: item.image }} style{styles.image} resizeModecover / Text style{styles.title}{item.name}/Text Text style{styles.price}${item.price}/Text /Pressable ) }) export function ProductList({ products, onProductPress }: ProductListProps) { const renderItem useCallback( ({ item }: { item: Product }) ( ProductItem item{item} onPress{onProductPress} / ), [onProductPress] ) const keyExtractor useCallback((item: Product) item.id, []) return ( FlashList data{products} renderItem{renderItem} keyExtractor{keyExtractor} estimatedItemSize{100} // Performance optimizations removeClippedSubviews{true} maxToRenderPerBatch{10} windowSize{5} // Pull to refresh onRefresh{onRefresh} refreshing{isRefreshing} / ) }各优化点的作用FlashListshopify/flash-list替代FlatList基于单元格复用与窗口化渲染长列表内存占用显著低于 FlatList是SKILL.md最佳实践中明确推荐的选型FlashList over FlatList - Better performance for long listsmemo(ProductItem)阻止 props 未变化时列表项重渲染useCallback贯穿handlePress、renderItem、keyExtractor均稳定引用配合 memo 形成完整的重渲染抑制链路estimatedItemSize{100}FlashList 据此预估滚动窗口是其他窗口化参数生效的前提removeClippedSubviews{true}移出可视区域的子视图直接卸载减少离屏渲染开销maxToRenderPerBatch{10}与windowSize{5}控制单批渲染数量与渲染窗口大小平衡首屏速度与滚动流畅度代码中的FastImage组件承担图片加载与缓存职责实际工程中通常来自react-native-fast-image或expo-image等库details.md示例未展开其 import可按项目实际依赖引入避免列表滚动时图片解码阻塞主线程顶部下拉刷新onRefresh/refreshing与数据层无缝衔接——配合 Pattern 3 的invalidateQueries下拉即触发服务器数据同步。EAS Build Submit从云构建到应用商店与 OTA 更新details.md的最后一部分给出了完整的 EASExpo Application Services发布链路配置覆盖三种构建画像、商店提交与热更新。eas.json三套构建画像与提交配置// eas.json { cli: { version: 5.0.0 }, build: { development: { developmentClient: true, distribution: internal, ios: { simulator: true } }, preview: { distribution: internal, android: { buildType: apk } }, production: { autoIncrement: true } }, submit: { production: { ios: { appleId: youremail.com, ascAppId: 123456789 }, android: { serviceAccountKeyPath: ./google-services.json } } } }配置语义逐项说明cli.version: 5.0.0声明需要 EAS CLI 最低版本保证eas.json字段兼容性development 画像developmentClient: true生成开发构建Development Build配合distribution: internal内部分发ios.simulator: true支持 iOS 模拟器安装——这是日常开发调试的标配preview 画像内部分发的预发布版本android.buildType: apk产出可直接安装的 APK而非 AAB适合测试人员旁载安装production 画像autoIncrement: true每次构建自动递增构建号省去手工维护版本号submit.productioniOS 提交需要 Apple ID 与 App Store Connect App IDascAppIdAndroid 提交需要 Google Play 服务账号密钥文件路径serviceAccountKeyPath。注意示例中的appleId/ascAppId/serviceAccountKeyPath为占位值实际使用时应替换为真实凭据并避免将密钥提交到版本库。常用命令速查# Build commands eas build --platform ios --profile development eas build --platform android --profile preview eas build --platform all --profile production # Submit to stores eas submit --platform ios eas submit --platform android # OTA updates eas update --branch production --message Bug fixeseas build通过--profile选择上面定义的画像--platform指定目标平台all表示 iOS Android 全量构建eas submit将已构建产物提交到对应商店配置取自eas.json的submit段eas update --branch production走 EAS Update 发布OTA 热更新可绕过应用商店审核直接修复线上 Bug——这正是SKILL.md对比表中 Expo OTA updates: Built-in 的能力落地。值得注意的是 OTA 更新只能下发 JavaScript 层面的改动涉及原生代码的变更仍需走完整的构建-提交流程。最佳实践清单SKILL.md总结的 Dos / Donts 是上述六个模式的浓缩经验适合作为架构评审时的检查清单应当遵循Dos使用 Expo更快的开发迭代、内置 OTA 更新、托管原生代码用 FlashList 而非 FlatList长列表性能更优记忆化组件memo/useCallback抑制不必要的重渲染使用 Reanimated动画运行在原生线程维持 60fps在真机上测试模拟器无法暴露真实世界的性能与交互问题。应当避免Donts不要内联样式统一用StyleSheet.create样式对象只创建一次避免每次渲染重建不要在 render 中发请求改用useEffect或 React Query见 Pattern 3不要忽略平台差异iOS 与 Android 都要实测见 Pattern 5不要把密钥写进代码使用环境变量与安全存储见 Pattern 2 的 SecureStore不要跳过错误边界移动端崩溃代价高昂错误边界是第一道防线。在 agents 生态中的落地Skill 与 Agent 的协作方式该技能并非孤立存在它嵌入了 agents 仓库frontend-mobile-development插件的能力矩阵。插件内的 mobile-developer.md Agent 将本技能的六个模式扩展为完整的移动开发能力图谱——从 React Native New ArchitectureFabric、TurboModules、JSI、Hermes 引擎配置到离线优先数据同步、生物认证、推送通知与 EAS 发布流程同时 component-scaffold.md 命令提供组件脚手架的自动化生成与 Pattern 5 的跨平台按钮、Pattern 6 的列表项组件形成脚手架生成 架构模式的组合拳。典型的工作流协作方式Agent 依据用户需求如构建一个带离线能力的电商 App激活react-native-architecture技能SKILL.md先给出项目结构、Expo 选型与快速启动基础当导航层级不足以覆盖复杂场景时按渐进式披露机制加载references/details.md即本文展开的六个模式与 EAS 配置落地过程中配合component-scaffold命令批量生成类型安全、可访问的组件文件最终交付符合本技能最佳实践的完整工程。结语本文从 references/details.md 出发完整继承了六个可运行的生产级模式与 EAS 发布配置并结合 SKILL.md 的项目结构、技术选型与最佳实践做了纵深补充Expo Router 的声明式导航与路由守卫、React Query 的离线持久化与乐观更新闭环、三类原生模块的防御式封装、平台差异化策略、FlashList 渲染节流以及从 Development Build 到商店提交与 OTA 更新的发布链路。这套模式彼此独立又可自由组合是架构新项目、评审既有代码或向团队传递 React Native 工程规范时的可靠参考。【免费下载链接】agentsMulti-harness agentic plugin marketplace for Claude Code, Codex, Cursor, OpenCode, GitHub Copilot, and Google Antigravity项目地址: https://gitcode.com/GitHub_Trending/agents24/agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联 返回资讯列表 →