expo-config-setup

安装量: 54
排名: #13774

安装

npx skills add https://github.com/dengineproblem/agents-monorepo --skill expo-config-setup

Expo Config Setup Expert Expert at configuring Expo projects with app.json, app.config.js, and platform-specific settings for optimal development and production builds. Core Configuration Principles Static vs Dynamic Configuration Use app.json for static configuration that doesn't change between environments Use app.config.js for dynamic configuration requiring environment variables or conditional logic Never mix sensitive data directly in configuration files - use environment variables Platform-Specific Settings Always configure both iOS and Android platforms explicitly Use platform-specific overrides for different requirements Consider platform differences in permissions, capabilities, and UI guidelines Essential App Configuration Structure // app.config.js export default { expo : { name : process . env . APP_NAME || "My App" , slug : "my-app" , version : "1.0.0" , orientation : "portrait" , icon : "./assets/icon.png" , userInterfaceStyle : "automatic" , splash : { image : "./assets/splash.png" , resizeMode : "contain" , backgroundColor : "#ffffff" } , assetBundlePatterns : [ "*/" ] , ios : { supportsTablet : true , bundleIdentifier : process . env . IOS_BUNDLE_ID || "com.company.myapp" , buildNumber : process . env . IOS_BUILD_NUMBER || "1" , infoPlist : { NSCameraUsageDescription : "This app uses the camera to take photos." , NSLocationWhenInUseUsageDescription : "This app uses location to provide location-based features." } } , android : { adaptiveIcon : { foregroundImage : "./assets/adaptive-icon.png" , backgroundColor : "#FFFFFF" } , package : process . env . ANDROID_PACKAGE || "com.company.myapp" , versionCode : parseInt ( process . env . ANDROID_VERSION_CODE ) || 1 , permissions : [ "android.permission.CAMERA" , "android.permission.ACCESS_FINE_LOCATION" ] } , web : { favicon : "./assets/favicon.png" , bundler : "metro" } } } ; Environment-Specific Configuration // app.config.js with environment handling const IS_DEV = process . env . APP_VARIANT === 'development' ; const IS_PREVIEW = process . env . APP_VARIANT === 'preview' ; const getAppName = ( ) => { if ( IS_DEV ) return 'MyApp (Dev)' ; if ( IS_PREVIEW ) return 'MyApp (Preview)' ; return 'MyApp' ; } ; const getBundleId = ( ) => { if ( IS_DEV ) return 'com.company.myapp.dev' ; if ( IS_PREVIEW ) return 'com.company.myapp.preview' ; return 'com.company.myapp' ; } ; export default { expo : { name : getAppName ( ) , slug : IS_DEV ? 'myapp-dev' : IS_PREVIEW ? 'myapp-preview' : 'myapp' , scheme : IS_DEV ? 'myapp-dev' : IS_PREVIEW ? 'myapp-preview' : 'myapp' , version : process . env . APP_VERSION || '1.0.0' , ios : { bundleIdentifier : getBundleId ( ) , } , android : { package : getBundleId ( ) , } , extra : { apiUrl : process . env . API_URL , environment : process . env . APP_VARIANT || 'production' , eas : { projectId : process . env . EAS_PROJECT_ID } } , updates : { url : https://u.expo.dev/ ${ process . env . EAS_PROJECT_ID } } , runtimeVersion : { policy : 'sdkVersion' } } } ; EAS Build Configuration // eas.json { "cli" : { "version" : ">= 5.0.0" } , "build" : { "development" : { "developmentClient" : true , "distribution" : "internal" , "ios" : { "simulator" : true } , "env" : { "APP_VARIANT" : "development" } } , "preview" : { "distribution" : "internal" , "ios" : { "resourceClass" : "m-medium" } , "android" : { "buildType" : "apk" } , "env" : { "APP_VARIANT" : "preview" } } , "production" : { "ios" : { "resourceClass" : "m-medium" } , "env" : { "APP_VARIANT" : "production" } } } , "submit" : { "production" : { "ios" : { "appleId" : "your@email.com" , "ascAppId" : "1234567890" , "appleTeamId" : "ABCD1234" } , "android" : { "serviceAccountKeyPath" : "./google-services.json" , "track" : "internal" } } } } Plugin Configuration Best Practices // Advanced plugin configuration export default { expo : { plugins : [ "expo-font" , "expo-router" , [ "expo-camera" , { "cameraPermission" : "Allow $(PRODUCT_NAME) to access your camera" , "microphonePermission" : "Allow $(PRODUCT_NAME) to access your microphone" , "recordAudioAndroid" : true } ] , [ "expo-location" , { "locationAlwaysAndWhenInUsePermission" : "Allow $(PRODUCT_NAME) to use your location." , "locationAlwaysPermission" : "Allow $(PRODUCT_NAME) to use your location." , "locationWhenInUsePermission" : "Allow $(PRODUCT_NAME) to use your location." } ] , [ "expo-notifications" , { "icon" : "./assets/notification-icon.png" , "color" : "#ffffff" , "sounds" : [ "./assets/notification-sound.wav" ] , "mode" : "production" } ] , [ "expo-build-properties" , { "ios" : { "deploymentTarget" : "13.4" , "useFrameworks" : "static" } , "android" : { "compileSdkVersion" : 34 , "targetSdkVersion" : 34 , "buildToolsVersion" : "34.0.0" , "minSdkVersion" : 23 , "kotlinVersion" : "1.9.0" } } ] , [ "expo-image-picker" , { "photosPermission" : "Allow $(PRODUCT_NAME) to access your photos" , "cameraPermission" : "Allow $(PRODUCT_NAME) to take pictures" } ] ] } } ; Asset and Icon Configuration // Comprehensive asset configuration export default { expo : { icon : "./assets/images/icon.png" , // 1024x1024 splash : { image : "./assets/images/splash.png" , // 1284x2778 for iPhone 13 Pro Max resizeMode : "contain" , backgroundColor : "#ffffff" } , ios : { icon : "./assets/images/icon-ios.png" , // iOS-specific icon if needed splash : { image : "./assets/images/splash-ios.png" , resizeMode : "cover" , backgroundColor : "#ffffff" , tabletImage : "./assets/images/splash-tablet.png" } } , android : { icon : "./assets/images/icon-android.png" , adaptiveIcon : { foregroundImage : "./assets/images/adaptive-icon.png" , // 1024x1024 backgroundImage : "./assets/images/adaptive-icon-background.png" , backgroundColor : "#FFFFFF" } , splash : { image : "./assets/images/splash-android.png" , resizeMode : "cover" , backgroundColor : "#ffffff" , mdpi : "./assets/images/splash-mdpi.png" , // 320x480 hdpi : "./assets/images/splash-hdpi.png" , // 480x800 xhdpi : "./assets/images/splash-xhdpi.png" , // 720x1280 xxhdpi : "./assets/images/splash-xxhdpi.png" , // 960x1600 xxxhdpi : "./assets/images/splash-xxxhdpi.png" // 1280x1920 } } } } ; Deep Linking and Scheme Configuration // Complete deep linking setup export default { expo : { scheme : "myapp" , web : { bundler : "metro" } , ios : { bundleIdentifier : "com.company.myapp" , associatedDomains : [ "applinks:myapp.com" , "applinks:www.myapp.com" ] } , android : { package : "com.company.myapp" , intentFilters : [ { action : "VIEW" , autoVerify : true , data : [ { scheme : "https" , host : "myapp.com" , pathPrefix : "/app" } , { scheme : "https" , host : "www.myapp.com" , pathPrefix : "/app" } ] , category : [ "BROWSABLE" , "DEFAULT" ] } , { action : "VIEW" , data : [ { scheme : "myapp" } ] , category : [ "BROWSABLE" , "DEFAULT" ] } ] } } } ; OTA Updates Configuration // Over-the-air updates setup export default { expo : { updates : { enabled : true , checkAutomatically : "ON_LOAD" , fallbackToCacheTimeout : 30000 , url : https://u.expo.dev/ ${ process . env . EAS_PROJECT_ID } } , runtimeVersion : { policy : "appVersion" // or "sdkVersion", "nativeVersion", "fingerprint" } , // For custom update logic extra : { updateChannel : process . env . APP_VARIANT || 'production' } } } ; Update Logic in App // App.js or updates hook import * as Updates from 'expo-updates' ; async function checkForUpdates ( ) { if ( DEV ) return ; try { const update = await Updates . checkForUpdateAsync ( ) ; if ( update . isAvailable ) { await Updates . fetchUpdateAsync ( ) ; await Updates . reloadAsync ( ) ; } } catch ( error ) { console . error ( 'Error checking for updates:' , error ) ; } } Notifications Configuration // Push notifications setup export default { expo : { notification : { icon : "./assets/notification-icon.png" , // 96x96, white on transparent color : "#3498db" , androidMode : "default" , androidCollapsedTitle : "#{unread_notifications} new notifications" } , ios : { infoPlist : { UIBackgroundModes : [ "remote-notification" ] } } , android : { googleServicesFile : "./google-services.json" , useNextNotificationsApi : true } , plugins : [ [ "expo-notifications" , { icon : "./assets/notification-icon.png" , color : "#3498db" , sounds : [ "./assets/sounds/notification.wav" ] , mode : "production" } ] ] } } ; Security Best Practices // Secure configuration patterns export default ( { config } ) => { // Validate required env vars const requiredEnvVars = [ 'API_URL' , 'EAS_PROJECT_ID' ] ; for ( const envVar of requiredEnvVars ) { if ( ! process . env [ envVar ] ) { console . warn ( Warning: ${ envVar } is not set ) ; } } return { ... config , expo : { ... config . expo , // Never expose sensitive keys in extra extra : { apiUrl : process . env . API_URL , // Use EAS Secrets for sensitive values // NOT: apiKey: process.env.API_KEY } , // Certificate pinning for production ios : { ... config . expo ?. ios , infoPlist : { NSAppTransportSecurity : { NSAllowsArbitraryLoads : false , NSExceptionDomains : { "myapp.com" : { NSExceptionRequiresForwardSecrecy : true , NSIncludesSubdomains : true } } } } } } } ; } ; Common Configuration Pitfalls Missing Bundle Identifiers : problem : Build fails with "missing bundleIdentifier" solution : Always set ios.bundleIdentifier and android.package Incorrect Asset Dimensions : problem : Icons/splash screens look blurry or cropped solution : Follow exact size requirements (icon : 1024x1024) Version Code Issues : problem : Store rejects upload due to version code solution : Increment android.versionCode for each upload Missing Permissions : problem : Feature crashes on first use solution : Declare all required permissions with descriptions OTA Update Failures : problem : Updates not applying solution : Check runtimeVersion policy matches native builds Validation and Testing

Validate configuration

npx expo doctor

Check for common issues

npx expo-cli diagnostics

Test deep links

iOS

xcrun simctl openurl booted "myapp://path"

Android

adb shell am start -a android.intent.action.VIEW -d "myapp://path"

Preview configuration

npx expo config --type public npx expo config --type introspect Лучшие практики Environment separation — разные конфиги для dev/preview/prod Dynamic config — app.config.js для переменных окружения EAS Secrets — храните sensitive данные в EAS Secrets Version management — автоматизируйте версии через CI/CD Plugin audit — регулярно обновляйте и проверяйте плагины Test deep links — тестируйте на обеих платформах

返回排行榜