Expo SDK 49升级后EAS构建Android包fetch请求失败
Expo SDK 49 EAS构建Android包网络请求失败问题解决指南
问题概述
- Expo Go环境下所有功能正常,但通过
eas build -p android构建的Android安装包无法完成登录,报错TypeError: Network request failed - 该问题仅在将Expo SDK从46升级到49后出现,此前版本运行正常
- 已尝试更新所有依赖、移除未满足依赖库、清除yarn/npm缓存、切换包管理器、更换电脑、切换Node.js v16/v18,均未解决
- 开发与生产环境使用同一HTTP服务端,构建过程无报错,仅登录功能异常
优先排查方向
1. 解决HTTP明文请求限制(最常见原因)
从Expo SDK 48开始,生产构建默认启用Android网络安全配置,阻止所有HTTP明文请求(仅允许HTTPS)。如果你的服务端使用HTTP协议,必须手动配置允许明文流量:
在app.json或app.config.js中添加以下配置:
{ "expo": { "android": { "networkSecurityConfig": { // 允许指定域名的明文请求 "domainConfigs": [ { "domain": "你的服务端域名或IP", "cleartextTrafficPermitted": true } ] // 如果是测试环境,也可以全局允许明文请求(不建议生产用) // "cleartextTrafficPermitted": true } } } }
2. 修复Metro配置导致的polyfill缺失
你的metro.config.js使用异步函数导出配置,可能导致打包时全局对象(如fetch)的polyfill未被正确加载。修改为同步配置:
const { getDefaultConfig } = require('expo/metro-config'); const config = getDefaultConfig(__dirname); // 直接添加mjs扩展名,无需异步函数 config.resolver.sourceExts = [...config.resolver.sourceExts, 'mjs']; module.exports = config;
3. 手动注入Fetch Polyfill
生产构建中可能丢失fetch的全局polyfill,手动添加whatwg-fetch:
- 安装依赖:
yarn add whatwg-fetch
- 在项目入口文件
AppEntry.js顶部导入:
import 'whatwg-fetch';
4. 同步Babel配置与SDK版本
当前@babel/core版本(7.20.0)与Expo SDK 49不匹配,可能导致polyfill注入失败:
- 更新依赖:
yarn add -D @babel/core@^7.22.0
- 修改babel.config.js,确保生产环境注入全局polyfill:
module.exports = function(api) { api.cache(true); return { presets: ['babel-preset-expo'], env: { production: { plugins: ['react-native-polyfill-globals'] } } }; };
- 安装所需插件:
yarn add -D react-native-polyfill-globals
5. 验证EAS构建环境变量
确认EAS构建时使用了正确的服务端地址,避免生产环境配置错误:
在eas.json中配置生产环境变量:
{ "build": { "production": { "env": { "API_URL": "你的生产服务端地址" } } } }
附用户提供的配置文件
package.json
{ "name": "my_app_name", "version": "1.0.0", "main": "node_modules/expo/AppEntry.js", "scripts": { "start": "expo start", "android": "expo start --android", "ios": "expo start --ios", "web": "expo start --web" }, "dependencies": { "@react-native-async-storage/async-storage": "1.18.2", "@react-navigation/bottom-tabs": "^6.5.8", "@react-navigation/native": "^6.1.7", "@react-navigation/native-stack": "^6.9.13", "expo": "^49.0.8", "expo-barcode-scanner": "~12.5.3", "expo-camera": "~13.4.2", "expo-linear-gradient": "~12.3.0", "expo-localization": "~14.3.0", "expo-secure-store": "~12.3.1", "expo-status-bar": "~1.6.0", "i18n-js": "^4.3.0", "react": "18.2.0", "react-native": "0.72.4", "react-native-gesture-handler": "~2.12.0", "react-native-keyboard-aware-scroll-view": "^0.9.5", "react-native-loading-spinner-overlay": "^3.0.1", "react-native-safe-area-context": "4.6.3", "react-native-screens": "~3.22.0", "react-native-svg": "13.9.0", "victory-native": "^36.6.11" }, "devDependencies": { "@babel/core": "^7.20.0" }, "private": true }
babel.config.js
module.exports = function(api) { api.cache(true); return { presets: ['babel-preset-expo'] }; };
metro.config.js
// Learn more https://docs.expo.io/guides/customizing-metro const { getDefaultConfig } = require('expo/metro-config'); // module.exports = getDefaultConfig(__dirname); /** @type {import('expo/metro-config').MetroConfig} */ const config = getDefaultConfig(__dirname); module.exports = (async () => { const { resolver: { sourceExts }, } = config; return { ...config, resolver: { ...config.resolver, sourceExts: [...sourceExts, 'mjs'], }, }; })();
gradle日志
> Task :react-native-async-storage_async-storage:compileReleaseJavaWithJavac Note: /home/expo/workingdir/build/node_modules/@react-native-async-storage/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStorageModule.java uses or overrides a deprecated API. Note: Recompile with -Xlint:deprecation for details. Note: /home/expo/workingdir/build/node_modules/@react-native-async-storage/async-storage/android/src/main/java/com/reactnativecommunity/asyncstorage/AsyncStoragePackage.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:2728:18: warning: the variable "DebuggerInternal" was not declared in function "__shouldPauseOnThrow" typeof DebuggerInternal !== 'undefined' && ^~~~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:11514:7: warning: the variable "setTimeout" was not declared in function "logCapturedError" setTimeout(function () { ^~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:9474:108: warning: the variable "nativeFabricUIManager" was not declared in function "onChange" ...lInstanceHandle ? (from && nativeFabricUIManager.setIsJSResponder(from.sta... ^~~~~~~~~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:10095:21: warning: the variable "clearTimeout" was not declared in anonymous function " 264#" cancelTimeout = clearTimeout; ^~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:13845: 30: warning: the variable "__REACT_DEVTOOLS_GLOBAL_HOOK__" was not declared in anonymous function " 264#" if ("undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__) { ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:15730:5: warning: the variable "setImmediate" was not declared in function "handleResolved" setImmediate(function () { ^~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:19906:12: warning: the variable "fetch" was not declared in anonymous function " 499#" fetch: fetch, ^~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:19907:14: warning: the variable "Headers" was not declared in anonymous function " 499#" Headers: Headers, ^~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:19908:14: warning: the variable "Request" was not declared in anonymous function " 499#" Request: Request, ^~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:19909:15: warning: the variable "Response" was not declared in anonymous function " 499#" Response: Response ^~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:20066:24: warning: the variable "FileReader" was not declared in function "readBlobAsArrayBuffer" var reader = new FileReader(); ^~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:20117:36: warning: the variable "Blob" was not declared in anonymous function " 510#" } else if (support.blob && Blob.prototype.isPrototypeOf(body)) { ^~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:20119:40: warning: the variable "FormData" was not declared in anonymous function " 510#" } else if (support.formData && FormData.prototype.isPrototypeOf(body)) { ^~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:20121:44: warning: the variable "URLSearchParams" was not declared in anonymous function " 510#" ...e if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body... ^~~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:20240:26: warning: the variable "AbortController" was not declared in anonymous function " 516#" var ctrl = new AbortController(); ^~~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:20373:23: warning: the variable "XMLHttpRequest" was not declared in anonymous function " 520#" var xhr = new XMLHttpRequest(); ^~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:19919:71: warning: the variable "self" was not declared in anonymous function " 502#" ...undefined' && globalThis || typeof self !== 'undefined' && self || ^~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:24796:27: warning: the variable "performance" was not declared in anonymous function " 711#" if ("object" === typeof performance && "function" === typeof performance.no... ^~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:24819:26: warning: the variable "navigator" was not declared in anonymous function " 711#" "undefined" !== typeof navigator && undefined !== navigator.scheduling && u... ^~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:24929:37: warning: the variable "MessageChannel" was not declared in anonymous function " 711#" };else if ("undefined" !== typeof MessageChannel) { ^~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:24944:34: warning: the variable "nativeRuntimeScheduler" was not declared in anonymous function " 711#" ... = "undefined" !== typeof nativeRuntimeScheduler ? nativeRuntimeScheduler.... ^~~~~~~~~~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:36964:34: warning: the variable "requestAnimationFrame" was not declared in function "start 9#" ... this._animationFrame = requestAnimationFrame(this.onUpdate.bind(this)); ^~~~~~~~~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:90654:9: warning: the property "alignItems" was set multiple times in the object definition. alignItems: 'center', ^~~~~~~~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:90652:9: note: The first definition was here. alignItems: 'center', ^~~~~~~~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:106933:13: warning: the property "alignItems" was set multiple times in the object definition. alignItems: 'center', ^~~~~~~~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:106931:13: note: The first definition was here. alignItems: 'center', ^~~~~~~~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:106961:13: warning: the property "alignItems" was set multiple times in the object definition. alignItems: 'center', ^~~~~~~~~~~~~~~~~~~~ /home/expo/workingdir/build/android/app/build/generated/assets/createBundleReleaseJsAndAssets/index.android.bundle:106959:13: note: The first definition was here. alignItems: 'center', ^~~~~~~~~~~~~~~~~~~~ > Task :react-native-svg:compileReleaseJavaWithJavac Note: /home/expo/workingdir/build/node_modules/react-native-svg/android/src/main/java/com/horcrux/svg/VirtualView.java uses or overrides a deprecated API. Note: Recompile with -Xlint:deprecation for details. Note: Some input files use unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. > Task :expo-modules-core:compileReleaseJavaWithJavac Note: Some input files use or override a deprecated API. Note: Recompile with -Xlint:deprecation for details. Note: Some input files use unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. > Task :expo-secure-store:bundleLibCompileToJarRelease Note: /home/expo/workingdir/build/node_modules/expo-secure-store/android/src/main/java/expo/modules/securestore/SecureStoreModule.java uses or overrides a deprecated API. Note: Recompile with -Xlint:deprecation for details.
内容的提问来源于stack exchange,提问作者rmarques
相关产品推荐
相关产品推荐

