React Native 0.61.1运行Android端报Unexpected token '<'错误如何解决
React Native 0.61.1 安装运行报错
问题现象
安装现有React Native应用时程序抛出运行错误,核心报错为JS侧解析到非法字符<,JS bundle加载异常,无法调用热更新、应用注册相关核心方法,应用无法正常启动。
Logcat错误日志
E/unknown:ReactNative: Exception in native call from JS com.facebook.react.devsupport.JSException: Unexpected token '<' at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(Unknown Source:0) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(Unknown Source:37) at java.lang.Thread.run(Thread.java:920) Caused by: com.facebook.jni.CppException: Unexpected token '<' no stack ... 8 more D/SoLoader: Loaded: libyoga.so E/ReactNativeJNI: Attempting to call JS function on a bad application bundle: HMRClient.setup() E/unknown:ReactNative: Exception in native call java.lang.RuntimeException: Attempting to call JS function on a bad application bundle: HMRClient.setup() at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(Unknown Source:0) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(Unknown Source:37) at java.lang.Thread.run(Thread.java:920) E/ReactNativeJNI: Attempting to call JS function on a bad application bundle: AppRegistry.runApplication() E/unknown:ReactNative: Exception in native call java.lang.RuntimeException: Attempting to call JS function on a bad application bundle: AppRegistry.runApplication() at com.facebook.react.bridge.queue.NativeRunnable.run(Native Method) at android.os.Handler.handleCallback(Handler.java:938) at android.os.Handler.dispatchMessage(Handler.java:99) at com.facebook.react.bridge.queue.MessageQueueThreadHandler.dispatchMessage(Unknown Source:0) at android.os.Looper.loopOnce(Looper.java:201) at android.os.Looper.loop(Looper.java:288) at com.facebook.react.bridge.queue.MessageQueueThreadImpl$4.run(Unknown Source:37) at java.lang.Thread.run(Thread.java:920) D/SoLoader: init exiting
运行环境信息
执行npx react-native info输出如下:
info Fetching system and libraries information... System: OS: macOS 12.4 CPU: (8) x64 Apple M1 Memory: 40.87 MB / 8.00 GB Shell: 5.8.1 - /bin/zsh Binaries: Node: 14.19.0 - /usr/local/bin/node npm: 6.14.16 - /usr/local/bin/npm Watchman: 2022.06.13.00 - /opt/homebrew/bin/watchman SDKs: iOS SDK: Platforms: iOS 15.0, DriverKit 20.4, macOS 11.3, tvOS 15.0, watchOS 8.0 Android SDK: API Levels: 29, 30, 31, 32 Build Tools: 29.0.2, 30.0.2, 30.0.3, 32.0.0, 32.1.0 System Images: android-30 | Intel x86 Atom_64, android-32 | Google APIs ARM 64 v8a IDEs: Android Studio: 2021.1 AI-211.7628.21.2111.8193401 Xcode: 13.0/13A233 - /usr/bin/xcodebuild npmPackages: react: 16.9.0 => 16.9.0 react-native: 0.61.1 => 0.61.1
复现步骤
基于0.61.1版本创建React Native应用,按以下流程操作可稳定复现问题:
- 执行
npm i安装npm依赖,已尝试添加--legacy-peer-deps参数安装,问题仍存在 - 执行
npx react-native start --reset-cache启动Metro服务,已提前清空缓存 - 执行
npx react-native run-android构建运行Android端,同时尝试过通过Android Studio直接运行应用,均复现报错
已尝试排查方向
已参考社区公开的同类报错解决方案,从Babel版本兼容、Metro打包配置、Android端权限配置等方向排查,均未解决问题。
错误截图参考:
根因分析与修复方案
Unexpected token '<'报错的核心原因是Metro服务返回给客户端的不是合法JS bundle文件,而是HTML格式的错误响应(通常是404/500错误页,以<html>标签开头,JS引擎解析到第一个字符<就会抛出语法错误)。结合当前M1芯片macOS、RN0.61.1老版本、高版本Node/Watchman的环境特征,按以下步骤修复:
- 修复Node版本兼容问题
RN0.61.1最高适配Node 12.x LTS版本,当前使用的Node 14.19.0和该版本内置的Babel编译链存在兼容问题,会导致Metro编译时抛出HTML格式的错误页。通过nvm切换Node版本到12.22.12(12.x最终维护版本),删除项目下的node_modules文件夹、package-lock.json文件后重新执行npm i安装依赖。 - 修复Watchman版本兼容问题
当前安装的2022版Watchman和RN0.61的文件监听逻辑存在兼容问题,会导致bundle文件路径解析失败。先执行npx react-native start --reset-cache --no-watchman临时禁用Watchman启动服务验证问题是否复现,如果禁用后服务正常,卸载当前高版本Watchman,安装4.9.0版本适配老版本RN即可。 - 修复Android端调试连接配置
执行adb reverse tcp:8081 tcp:8081做本地端口转发,确保模拟器能访问到开发机的Metro服务;如果使用真机调试,确认真机和开发机在同一局域网,打开应用开发者菜单进入Dev Settings,将Debug server host配置为开发机局域网IP:8081,避免请求到其他服务返回HTML内容。 - 全量清理缓存
执行以下命令清理所有构建、依赖缓存,避免旧缓存干扰:
# 清理Android构建缓存 cd android && ./gradlew clean cd .. # 重装依赖 rm -rf node_modules && npm install # 清空Metro缓存启动服务 npx react-native start --reset-cache
全量清理完成后重新执行npx react-native run-android即可正常启动应用。
内容的提问来源于stack exchange,提问作者Prashant Yadav
相关产品推荐
相关产品推荐

