0%

原生项目接入React Native

由于项目的业务需求,需要将原生的项目向React Native重构。原生的Android和iOS项目处于正常迭代的情况,React Native的重构版本已经初步完成一个基础版本,现在需要在这个基础版本上,进行原生端的接入工作。目标是在原生项目里的某几个页面,替换为React Native页面。

以下是记录本次接入遇到的问题

iOS端

下载原生项目

从代码仓库中下载原生项目并执行pod install成功运行在手机上。

集成到React Native项目中

  • 将React Native项目中的ios文件夹删除,并把原生的iOS项目拖入文件夹中修改文件夹名称为ios

  • 修改podfile文件

    React Native项目以及iOS原生项目都是用了cocospod作为库管理工具,所以需要做一个手动的合并操作,以下是合并之后的podfile

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    require_relative '../node_modules/react-native/scripts/react_native_pods'
    require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'

    # Uncomment the next line to define a global platform for your project
    platform :ios, '10.0'

    target 'Name' do
    # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
    # use_frameworks!

    config = use_native_modules!

    use_react_native!(
    :path => config[:reactNativePath],
    # to enable hermes on iOS, change `false` to `true` and then install pods
    :hermes_enabled => true
    )

    pod 'Bugly'

    pod 'YYText'


    use_flipper!('Flipper' => '0.75.1', 'Flipper-Folly' => '2.5.3', 'Flipper-RSocket' => '1.3.1')

    post_install do |installer|
    react_native_post_install(installer)
    installer.pods_project.targets.each do |target|
    target.build_configurations.each do |config|
    config.build_settings['ENABLE_BITCODE'] = 'NO'
    config.build_settings['ARCHS'] = 'arm64'
    end
    end
    end
    end

    保留了原生项目需要依赖的第三方库,以及React Native所需的库,之后执行

    1
    $ pod install

    运行

第一次运行可能会出现各种不同的问题,这里只记录了本人实际操作过程中遇到的问题以及解决方案

library not found for

在Xcode编译的时候,可能会遇到报这个错误”library not found for -lxxxxxx”。这是由于Xcode找不到React Native所依赖的库,但是这个需要依赖的库可以在Pods中找到,那么只需要在设置中给Xcode指向这个库的位置。

Build Setting —>Library Search Paths添加找不到的这个库的地址,如添加:

1
"${PODS_CONFIGURATION_BUILD_DIR}/Yoga"

“associated type descriptor for Swift.ExpressibleByFloatLiteral.FloatLiteralType”, referenced from:

这是一个有些摸不到头脑的问题,因为这个项目里根本就没有Swift写的代码,一时之间不知道问题所在,经过一番谷歌,找到了解决方案如下:

只需要在项目里新建一个Swift文件,里面什么都不用写,再次编译就没有这个问题了。

1
2
3
File -> New -> File

Select Swift File

解决方案详细描述

No bundle URL present

项目这个时候已经正常编译成功了,但是一运行App直接就得了红屏报错。这个是React Native常见的错误,即App访问不到bundle文件,但是又有一些不同:

  • App并没有试图向8081端口请求bundle,App上方没有一个进度条,直接就出现这个错误。
  • 电脑上8081端口没有自动启动
  • 手动启动8081端口之后,App没有响应,node服务也显示没有连接到App

根据8081端口没有自动启动,找到了Build Phases配置项,这里是Xcode在编译时候会执行的一些操作,和之前的React Naitve项目中的ios工程做了比较。缺少了一些shell脚本:Start PackagerBundle React Native code and images两个脚本,从原有项目拷贝过来即可。

error opening input file ‘x/x-Bridging-Header.h’

Xcode—>target—>Objective-C Bridging Header中修改为正确的的地址,或者不存在这个文件的话,直接清空即可

Android

下载原生项目

从代码仓库中下载原生项目并成功编译。

集成到React Native项目中

  • 将React Native项目中的android文件夹删除,并把原生的Android项目拖入文件夹中修改文件夹名称为android

  • 修改app/build.gradle

    dependencies中添加React Native所需要的依赖库

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    dependencies {
    implementation "com.android.support:appcompat-v7:27.1.1"
    ...
    原生项目依赖
    ...
    implementation "com.facebook.react:react-native:+" // From node_modules

    /* Filpper相关 */
    debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
    exclude group:'com.facebook.fbjni'
    }

    debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
    exclude group:'com.facebook.flipper'
    exclude group:'com.squareup.okhttp3', module:'okhttp'
    }

    debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
    exclude group:'com.facebook.flipper'
    }

    /* Js引擎 Hermes或者是Jsc */

    if (enableHermes) {
    def hermesPath = "../../node_modules/hermes-engine/android/";
    debugImplementation files(hermesPath + "hermes-debug.aar")
    releaseImplementation files(hermesPath + "hermes-release.aar")
    } else {
    implementation jscFlavor
    }


    ...
    React Native项目中其他依赖
    ...
    }

    由于React Native项目中需要开启Hermes引擎,还需要将相关的配置添加到build.gradle文件中

    1
    2
    3
    4
    5
    project.ext.react = [
    enableHermes: true,
    ]

    def enableHermes = project.ext.react.get("enableHermes", false);
  • 修改build.gradle

    在项目的 build.gradle 文件中为 React Native 和 JSC 引擎添加 maven 源的路径,必须写在 “allprojects” 代码块中

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    allprojects {
    repositories {
    maven {
    // All of React Native (JS, Android binaries) is installed from npm
    url "$rootDir/../node_modules/react-native/android"
    }
    maven {
    // Android JSC is installed from npm
    url("$rootDir/../node_modules/jsc-android/dist")
    }
    ...
    }
    ...
    }
  • 启用原生模块的自动链接

    setting.gradle中添加

    1
    apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)

    app/build.gradle的最底部添加

    1
    apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)

    运行

Error:Failed to open zip file. Gradle’s dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)

这是由于网络原因下载Gradle文件的时候,没有下载成功。由于没有下载完成的文件存在,再次点击下载依旧会报同样的错误。

找到这个没下载成功的文件,删除并重新下载即可,在

1
~/.gradle/wrapper/dists

找到相应版本的文件,删除即可

stackoverflow问题详情

Caused by: groovy.lang.MissingPropertyException: Could not get unknown property ‘mergeResourcesProvider’ for object of type com.android.build.gradle.internal.api.ApplicationVariantImpl.

修改了distributionUrl的版本以及android/build.gradle文件,改为了以下的版本

1
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip
1
com.android.tools.build:gradle:3.3.0