• 重启React Native老项目的奇幻之旅:填坑实录与解决方案分享


    这两天为了重启五年前基于 React Native(版本 0.59.9)开发的老项目,经过各种填坑查询等操作,最终把它成功地运行起来了。

    在这篇文章中,我将详述那些遭遇的挑战以及对应的解决方案,以期为同样面临此类困境的开发者提供宝贵的经验参考。

    这个项目涉及到的环境基本版本信息如下:

    react: 16.8.3

    react-native: 0.59.9

    下载Gradle包

    本来想着很简单,因为这个项目在之前是能正常运行的,我的机器环境就没有改变过,代码也没有修改过,所以直接执行如下命令:

    react-native run-android
    

    然而现实却是Gradle包下载缓慢且频繁中断,后来就通过上外网的方式把它解决了。

    不过这种上网的方式下载也是挺慢的,想以后如果不是通过其它上网方式该如何解决呢?

    这里提供一个链接,估计按照下面的方式应该是能更快地下载Gradle包的。

    国内最方便的AndroidStudio Gradle包下载方法

    NPM证书过期与镜像源迁移

    想着Gradle下载好了,我又没有修改过什么代码,总可以把项目给运行起来了吧。

    然而是我小看整个过程中碰到的难题了。

    再次运行 react-native run-android 命令,直接报了如下的错误:

    [npm] ERR: request to https://registry.npm.taobao.org failed, reason: certificate has expired
    

    碰到问题就直接在网上搜索相关问题,了解下来应该是 npm.taobao.org 和 registry.npm.taobao.org 域名于 2022 年 05 月 31 日零时起停止服务,而 npm.taobao.org 这个网站的证书也于 2024年01月22日过期了,这也就是为啥会出现request to https://registry.npm.taobao.org failed, reason: certificate has expired错误的原因。

    既然知道了原因,那就把镜像源给换掉,新的镜像源要切换成 https://registry.npmmirror.com

    网上一搜就知道如何切换了,由于我这边有时用npm有时用yarn,所以就一起把npm和yarn的镜像源都设置掉了。

    使用的命令如下:

    #设置npm的镜像源
    npm config set registry https://registry.npmmirror.com
    #设置yarn的镜像源
    yarn config set registry https://registry.npmmirror.com
    

    为了查看镜像源是否被设置过来了,就用如下的命令进行验证:

    #查看npm当前的镜像源
    npm config get registry
    #查看yarn当前的镜像源
    yarn config get registry
    

    经过验证,当前的镜像源确实被修改成了https://registry.npmmirror.com

    想着这下问题总归被解决了吧,继续执行 react-native run-android命令,但出乎我的意料,依然报 request to https://registry.npm.taobao.org failed, reason: certificate has expired 错误,而且看起来镜像源也没有被切换过来。

    难道是npm中代理设置的问题?

    那就查看一下目前的代理:

    #查看代理
    npm config list
    yarn config list
    

    发现确实设置过代理,那就先把代理给删除掉:

    # npm删除代理
    npm config delete proxy
    npm config delete https-proxy
    
    # yarn删除代理
    yarn config delete proxy
    yarn config delete https-proxy
    

    如果以后还要设置代理的话,就把设置代理的命令记录在这里,免得以后可以用到:

    # npm设置代理
    npm config set proxy http://127.0.0.1:8080
    npm config set https-proxy http://127.0.0.1:8080
    
    # yarn设置代理
    yarn config set proxy http://127.0.0.1:8080
    yarn config set https-proxy http://127.0.0.1:8080
    

    删除了代理后,继续执行 react-native run-android命令进行验证,依然报上面的certificate has expired错误。看起来有点到了山群水尽的地步,

    最后,索性一不做二不休,直接跳过SSL证书验证,执行下面的命令。

    # 跳过npm SSL证书验证
    npm set strict-ssl false
    # 跳过yarn SSL证书验证
    yarn config set "strict-ssl" false -g
    

    再次执行react-native run-android命令,这次certificate has expired错误消失了。

    至少把问题往前推进了一步。

    不过也别高兴得太早,又碰到了新的问题。且继续看下面的填坑记录。

    Invalid regular expression引发的困扰

    这次报告的错误消息为:

    error Invalid regular expression: 
    /(.*\\__fixtures__\\.*|node_modules[\\\]react[\\\]dist[\\\].*|website\\node_modules\\.
    *|heapCapture\\bundle\.js|.*\\__tests__\\.*)$/:
     Unterminated character class. Run CLI with --verbose flag for more details.
    

    好家伙,直接报告这一堆乱七八糟的错误消息给我,把我给整懵了。

    还好遇事不懂网络搜索,最后可以通过下面的方式进行解决:

    修改文件\node_modules\metro-config\src\defaults\blacklist.js,把其中的某段内容替换为:

    var sharedBlacklist = [
      /node_modules[\/\\]react[\/\\]dist[\/\\].*/,
      /website\/node_modules\/.*/,
      /heapCapture\/bundle\.js/,
      /.*\/__tests__\/.*/
    ];
    

    根据这个修改的内容推测应该是某个工具对于windows下的打包路径正则表达式没有写好导致的。

    再次执行react-native run-android命令,又出现新的幺蛾子了...

    程序包com.facebook.react.bridge不存在

    这次出现的错误消息为:

    > Task :react-native-camera:compileGeneralDebugJavaWithJavac
    E:\project\exphone\exphoneapp2\node_modules\react-native-camera\android\src\main\java\com\google\android\cameraview\Camera1.java:31: 错误: 程序包com.facebook.react.bridge不存在
    import com.facebook.react.bridge.ReadableMap;
                                    ^
    E:\project\exphone\exphoneapp2\node_modules\react-native-camera\android\src\main\java\com\google\android\cameraview\CameraViewImpl.java:23: 错误: 程序包com.facebook.react.bridge不存在
    import com.facebook.react.bridge.ReadableMap;
    

    依然是上网搜索,找到了一个解决方案:

    如果react-native版本低于0.63,在 android\build.gradle 添加如下内容:

    def REACT_NATIVE_VERSION = new File(['node', '--print',"JSON.parse(require('fs').readFileSync(require.resolve('react-native/package.json'), 'utf-8')).version"].execute(null, rootDir).text.trim())
    
    allprojects {
        configurations.all {
            resolutionStrategy {
                // Remove this override in 0.65+, as a proper fix is included in react-native itself.
                force "com.facebook.react:react-native:" + REACT_NATIVE_VERSION
            }
        }
    

    我的react-native版本是0.59.9,低于0.63,那就直接用上面的方法。

    再次运行react-native run-android进行验证,这次总算打包成功了!!!

    不过也不要高兴得太早,预知后事如何,请继续...

    DeviceException: No connected devices

    执行后出现如下的异常:

    PS E:\project\exphone\exphoneapp2> react-native run-android
    (node:18976) Warning: Accessing non-existent property 'padLevels' of module exports inside circular dependency
    (Use `node --trace-warnings ...` to show where the warning was created)
    info Starting JS server...
    info Building and installing the app on the device (cd android && gradlew.bat app:installDebug)...
    > Task :app:installDebug FAILED
    
    FAILURE: Build failed with an exception.
    
    * What went wrong:
    Execution failed for task ':app:installDebug'.
    > com.android.builder.testing.api.DeviceException: No connected devices!
    
    * Try:
    Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.
    

    这个异常的核心是com.android.builder.testing.api.DeviceException: No connected devices!

    也就是没有连接到模拟器。

    我用的模拟器是BlueStacks蓝叠,这个模拟器要比Google的模拟器快。

    需要设置的地方是勾选其中允许ADB连接:

    明明我的模拟器启动起来了,为何不能连接上呢?

    输入命令查看当前模拟器设备:

    # adb devices列出模拟器设备
    PS E:\project\exphone\exphoneapp2> adb devices
    List of devices attached
    

    发现确实没有显示出连接上的模拟器。

    那我们就手动连接一个:

    # 使用adb connect进行连接
    PS E:\project\exphone\exphoneapp2> adb connect 127.0.0.1:5555
    connected to 127.0.0.1:5555
    PS E:\project\exphone\exphoneapp2> adb devices               
    List of devices attached
    127.0.0.1:5555  device    
    

    连接上android模拟器之后,就继续用react-native run-android命令进行验证。

    打包成功,android模拟器也连接上了,不过期望的界面没有呈现,只显示了一个红色的醒目的错误界面。革命尚未成功,同志还需努力... 😭😭😭

    运行时TypeError: cb.apply is not a function

    在模拟器加载应用后,却不幸收到了类似如下的异常:

    /node_modules/npm/node_modules/graceful-fs/polyfills.js:287
          if (cb) cb.apply(this, arguments)
    
    TypeError: cb.apply is not a function
        at /node_modules/npm/node_modules/graceful-fs/polyfills.js:287:18
        at FSReqCallback.oncomplete (node:fs:199:5)
    

    经过一通网上搜索,找到其中一个相对简单的解决方案,就是在package.json中添加:

      "resolutions": {
        "**/graceful-fs": "^4.2.4"
      }
    

    执行react-native run-android终于在模拟器中看到了应用程序成功启动起来的界面:

    总结

    至此有种经过九九八十一难总算到了西天取到真经的感觉。

    为了便于后续查阅与实践,这里整理了一些前面用到的命令,以备后事之需。

    镜像源管理

    #设置npm的镜像源
    npm config set registry https://registry.npmmirror.com
    #设置yarn的镜像源
    yarn config set registry https://registry.npmmirror.com
    
    
    #查看npm当前的镜像源
    npm config get registry
    #查看yarn当前的镜像源
    yarn config get registry
    

    缓存管理

    # 查看已缓存包的列表
    yarn cache list
    
    # 查询cache缓存文件目录路径
    yarn cache dir
    
    # 清理缓存包
    npm cache clean --force
    yarn cache clean
    

    代理管理

    #查看代理
    npm config list
    yarn config list
    
    # npm删除代理
    npm config delete proxy
    npm config delete https-proxy
    
    # yarn删除代理
    yarn config delete proxy
    yarn config delete https-proxy
    
    
    # npm设置代理
    npm config set proxy http://127.0.0.1:8080
    npm config set https-proxy http://127.0.0.1:8080
    
    # yarn设置代理
    yarn config set proxy http://127.0.0.1:8080
    yarn config set https-proxy http://127.0.0.1:8080
    

    证书验证

    # 跳过npm SSL证书验证
    npm set strict-ssl false
    # 跳过yarn SSL证书验证
    yarn config set "strict-ssl" false -g
    

    模拟器管理

    # adb devices列出模拟器设备
    adb devices
    # 使用adb connect进行连接
    adb connect 127.0.0.1:5555
    
  • 相关阅读:
    Java stream流 常用记录
    学习记录683@类别不平衡问题解决的基本策略之再缩放的数学解释
    如何5分钟跑起来一个完整项目?
    Binder进程通信基础使用
    Redis安装教程(保姆级教程)
    【torchvision.datasets.ImageFolder类的使用】
    设计模式学习(六):代理模式
    每日一题——寻找右区间(排序 + 二分查找)
    gradio的基础教程
    不知道10年老电脑如何重装系统?其实很简单
  • 原文地址:https://www.cnblogs.com/dreampursuer/p/18137611