You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Expo SDK 49项目在TestFlight中启动即崩溃求助

Expo项目TestFlight启动崩溃:"invalid host, js engine: hermes" 排查指南

开发环境运行正常的Expo SDK49项目,使用expo-router路由,部署到TestFlight后启动即崩溃,iOS控制台仅显示invalid host, js engine: hermes错误。此前多个测试版本正常,已尝试常见方案三周未解决。


iOS日志

*** Terminating app due to uncaught exception 
'RCTFatalException: Unhandled JS Exception: Error: invalid host, js engine: hermes', 
reason: 'Unhandled JS Exception: Error: invalid host, js engine: hermes, stack:
validate@154167:21
configure@153802:30
createClient@154133:27
anonymous@153583:58
loadModuleImplementation@206:13
guardedLoadModule@137:37
metroRequire@64:91
anonymous@153422:66
loadModuleImplementation@206:13
guardedLoadModule@137:37
metroRequire@64:91
anonymous@153411:65
loadModuleImplementation@206:13
guardedLoadModule@137:37
metroRequire@64:91
anonymous@142296:54
loadModuleImplementation@206:13
guardedLoadModule@137:37
metroRequire@64:91
anonymous@108132:26
loadModuleImplementation@206:13
guardedLoadModule@129:46
metroRequire@64:91
get@107915:26
metroContext@108106:14
loadRoute@74985:32
applyDefaultInitialRouteName@74887:31
fileNodeToRouteNode@74942:40
treeNodeToRouteNode@74973:32
anonymous@74843:32
getTreeNodesAsRouteNodes@74842:20
fileNodeToRouteNode@74931:40
treeNodeToRouteNode@74973:32<…>

package.json

{
  "name": "popil",
  "version": "3.1.0",
  "scripts": {
    "start": "expo start",
    "android": "expo start --android",
    "ios": "expo start --ios",
    "web": "expo start --web",
    "test": "jest --watchAll",
    "debugger": "react-native-debugger"
  },
  "jest": {
    "preset": "jest-expo"
  },
  "dependencies": {
    "@expo/vector-icons": "^13.0.0",
    "@gorhom/bottom-sheet": "^4.4.7",
    "@react-native-async-storage/async-storage": "1.18.2",
    "@react-navigation/drawer": "^6.6.2",
    "@react-navigation/native": "^6.0.2",
    "@react-navigation/stack": "^6.3.17",
    "@reduxjs/toolkit": "^1.9.5",
    "axios": "^1.4.0",
    "babel-plugin-module-resolver": "^5.0.0",
    "dayjs": "^1.11.9",
    "expo": "^49.0.0",
    "expo-checkbox": "~2.4.0",
    "expo-constants": "~14.4.2",
    "expo-dev-client": "~2.4.12",
    "expo-device": "~5.4.0",
    "expo-font": "~11.4.0",
    "expo-image-picker": "~14.3.2",
    "expo-linear-gradient": "~12.3.0",
    "expo-linking": "~5.0.2",
    "expo-notifications": "~0.20.1",
    "expo-router": "^2.0.4",
    "expo-splash-screen": "~0.20.5",
    "expo-status-bar": "~1.6.0",
    "expo-updates": "~0.18.18",
    "expo-web-browser": "~12.3.2",
    "formik": "^2.4.2",
    "html-entities": "^2.4.0",
    "htmlparser2": "^9.0.0",
    "react": "18.2.0",
    "react-content-loader": "^6.2.1",
    "react-dom": "18.2.0",
    "react-native": "0.72.6",
    "react-native-collapsible-tab-view": "^6.2.1",
    "react-native-gesture-handler": "~2.12.0",
    "react-native-pager-view": "6.2.0",
    "react-native-paper": "^5.10.4",
    "react-native-parsed-text": "^0.0.22",
    "react-native-reanimated": "~3.3.0",
    "react-native-render-html": "^6.3.4",
    "react-native-safe-area-context": "4.6.3",
    "react-native-screens": "~3.22.0",
    "react-native-svg": "13.9.0",
    "react-native-svg-transformer": "^1.0.0",
    "react-native-toast-message": "^2.1.6",
    "react-native-web": "~0.19.6",
    "react-native-webview": "13.2.2",
    "react-redux": "^8.1.1",
    "reactotron-react-native": "^5.0.3",
    "redux": "^4.2.1",
    "redux-persist": "^6.0.0",
    "styled-components": "^6.0.0-rc.3",
    "yup": "^1.2.0",
    "expo-system-ui": "~2.4.0",
    "expo-navigation-bar": "~2.3.0"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0",
    "@types/react": "~18.2.14",
    "@types/react-native-snap-carousel": "^3.8.5",
    "@types/react-redux": "^7.1.25",
    "@types/styled-components": "^5.1.26",
    "jest": "^29.2.1",
    "jest-expo": "^49.0.0",
    "prettier": "^2.8.8",
    "react-test-renderer": "18.2.0",
    "reactotron-redux": "^3.1.3",
    "typescript": "^5.1.3"
  },
  "private": true
}

app.json

{
  "expo": {
    "name": "Popil",
    "slug": "popil",
    "version": "3.1.0",
    "jsEngine": "hermes",
    "orientation": "portrait",
    "icon": "./src/assets/images/logo-ios.png",
    "scheme": "myapp",
    "userInterfaceStyle": "automatic",
    "splash": {
      "image": "./src/assets/images/splash.png",
      "resizeMode": "contain",
      "backgroundColor": "#18181f"
    },
    "assetBundlePatterns": [
      "**/*"
    ],
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "com.popil.popil",
      "bitcode": "Debug"
    },
    "android": {
      "versionCode": 12,
      "googleServicesFile": "./google-services.json",
      "adaptiveIcon": {
        "foregroundImage": "./src/assets/images/logo-android.png"
      },
      "package": "popil.popil"
    },
    "web": {
      "bundler": "metro",
      "favicon": "./src/assets/images/favicon.png"
    },
    "plugins": []
  }
}

eas.json

{
  "cli": {
    "version": ">= 5.1.0"
  },
  "build": {
    "development": {
      "developmentClient": true,
      "distribution": "internal",
      "channel": "development"
    },
    "preview": {
      "distribution": "internal",
      "android": {
        "buildType": "apk"
      },
      "channel": "preview"
    },
    "production": {
      "node": "18.17.1",
      "channel": "production",
      "prebuildCommand": "prebuild --npm"
    },
    "development-simulator": {
      "developmentClient": true,
      "distribution": "internal",
      "ios": {
        "simulator": true
      }
    }
  },
  "submit": {
    "production": {}
  }
}

index.tsx

import '@expo/metro-runtime';

import { ExpoRoot } from 'expo-router';
import Head from 'expo-router/head';
import { renderRootComponent } from 'expo-router/src/renderRootComponent';

// @ts-ignore
const ctx = require.context('./src/app', true, /.*/);

export function App() {
  return (
    // @ts-ignore
    <Head.Provider>
      <ExpoRoot context={ctx} />
    </Head.Provider>
  );
}

renderRootComponent(App);

排查方向与解决方案

1. 定位"invalid host"根源

从堆栈看,错误来自validate→configure→createClient流程,大概率是网络请求客户端(如axios)的baseURL配置问题:

  • 检查生产环境API域名是否正确,是否存在空值、未替换的localhost等开发环境占位符
  • 验证环境变量是否在TestFlight构建中正确注入:
    • 在eas.json的production构建中添加env字段传递环境变量
    • 确认expo-constants获取的manifest.extra包含正确的API地址

2. Expo Router适配生产构建

  • 检查index.tsx的require.context路径(当前为./src/app)是否匹配项目文件结构,expo-router默认要求app目录在根目录或src下
  • 升级expo-router到SDK49兼容的最新版本(当前2.0.4,建议升级到2.0.16+),修复已知生产构建路由问题

3. Hermes引擎构建配置

  • 在eas.json的production构建中显式指定Hermes引擎,确保生产构建生效:
    "production": {
      "node": "18.17.1",
      "channel": "production",
      "prebuildCommand": "prebuild --npm",
      "ios": {
        "jsEngine": "hermes"
      }
    }
    
  • 执行eas build --clean清理构建缓存,避免缓存导致的代码不一致

4. 环境变量与请求客户端检查

  • 确保所有依赖的环境变量(如API域名)未使用开发环境硬编码值,改用Constants.expoConfig?.extra?.API_URL这类方式获取
  • 检查axios实例创建代码,避免生产环境下baseURL为空或错误:
    // 正确示例
    const api = axios.create({ 
      baseURL: Constants.expoConfig?.extra?.API_URL || '默认生产域名' 
    });
    

5. 路由加载异常排查

堆栈显示错误发生在loadRoute阶段,需检查:

  • src/app下的路由文件是否存在本地文件路径错误,或依赖了仅开发环境存在的模块
  • 验证assetBundlePatterns配置是否覆盖所有需要打包的资源,避免生产环境缺失资源导致崩溃

内容的提问来源于stack exchange,提问作者Berat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 14:59:52