Native項目遷入React-Native過程中遇到的坑(0.4x版本)

轉載請註明出處王亟亟的大牛之路

最近都在忙着搭架子,找框架,談需求和開會。甚至都沒有時間好好裝逼,昨天幫安卓的小夥把項目從安卓整體遷移到了RN的項目下面,過程中遇到很多不可描述的坑,這裏給大家分享下經驗

先安利,安卓收納庫:https://github.com/ddwhan0123/Useful-Open-Source-Android

React-Native收納庫:https://github.com/ddwhan0123/Useful-Open-Source-React-Native


由來

項目剛開始的階段我還不在場(最初的app完全沒有RN/Weex的相關模塊),然後在我到崗後產品發現了,React-Native的“美好“,決定把原有的項目重構,7成的業務量遷移到React-Native模塊。

人手問題

重構開始前的人員配比
Android: 2人
iOS: 4人
前端:1名(會Vue,會一點React,完全沒摸過RN的)

過去一個月後
Android: 3人(有一個能寫點簡單RN頁面)
iOS: 3人(原有的一個被我拽去強行幹RN了)
前端:3(會React/Vue不會RN)+2(RN選手,會用Redux等第三方RN庫)+1(iOS被強拽的小夥)


模塊區分

在分頁面之初和產品砍了砍準則
(很多人覺得奇怪,既然如此爲什麼不用純RN?我的答案是,你不在位置上你不能理解,純原生的人難道就待機?)

  • 變動不大的用Native
  • 跟硬件相關的模塊用Native
  • 邏輯複雜但是頁面本身不復雜的用RN(這條被產品一個巴掌拍回了,他們不管實現難度)
  • 需要熱更的用RN
  • 其他省略

然後原生只剩下以下模塊

  • 登陸/註冊
  • 支付頁面
  • WebView相關頁面(這塊你懂的,強行拽來的)

遷移iOS

建完項目後先是拽iOS部分

這裏寫圖片描述

基本沒有遇到任何阻力,10分鐘(分支選擇耗費了幾分鐘)就整完了簡單的插了個RN頁面,跑起來無異常,iOS Over


遷移Android

android長這樣(自己項目各有差異,這個無所謂了,反正改安卓,改的不是目錄是Gradle配置)

這裏寫圖片描述

1.首先是查看授權,有就算了,沒有就加

   <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />

    <uses-permission android:name="android.permission.INTERNET" />

兩個必要的授權加一下,一個是彈窗,一個是網絡

2.項目文件的dependencies里加上RN的依賴

 compile 'com.facebook.react:react-native:+'  // From node_modules

3.android.gradle裏添加本地Maven的依賴

allprojects {
    repositories {
        mavenLocal()
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
}

你自己的項目應該還會有jcenter()和公網maven{}相關內容

4.添加搖一搖的Activity

     <activity android:name="com.facebook.react.devsupport.DevSettingsActivity" />

配置級別的內容已經貼完了

5.接下來是測試代碼(這部分內容在之前的互相跳轉裏出現過)

首先要建一個 ReactActivity

import com.facebook.react.ReactActivity;

import javax.annotation.Nullable;

public class RNActivity extends ReactActivity {
    @Nullable
    @Override
    protected String getMainComponentName() {
        return "統一的控件名";
    }
}

然後建一個測試用的Module

public class IntentModule extends ReactContextBaseJavaModule {
    public IntentModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        return "IntentModule";
    }

    @ReactMethod
    public void getDataFromIntent(Callback success, Callback error) {
        try {
            Activity currentActivity = getCurrentActivity();
            String result = currentActivity.getIntent().getStringExtra("result");//會有對應數據放入
            if (!TextUtils.isEmpty(result)) {
                success.invoke(result);
            }
        } catch (Exception ex) {
            error.invoke(ex.getMessage());
        }
    }
}

添加註冊到Application裏去的Package

public class MyReactPackage implements ReactPackage {
    @Override
    public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
        return Arrays.<NativeModule>asList(new IntentModule(reactContext));
    }

    @Override
    public List<Class<? extends JavaScriptModule>> createJSModules() {
        return Collections.emptyList();
    }

    @Override
    public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
        return Collections.emptyList();
    }
}

在Application裏註冊關聯


public class App extends Application implements ReactApplication {

    @Override
    public void onCreate() {
        super.onCreate();
        SoLoader.init(this, /* native exopackage */ false);
    }

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
        @Override
        public boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
            return Arrays.<ReactPackage>asList(
                    new MainReactPackage(),new MyReactPackage()
            );
        }
    };
}

改完之後上傳 git


嘗試性調試

git clone git@11.11.111.111:aaa-aaaa/RN_App.git (地址你懂的)
cd RN_App
npm install
react-native start
curl "http://localhost:8081/index.android.bundle?platform=android" -o "android/app/src/main/assets/index.android.bundle"
react-native run-android

在ok的情況下,跳轉完會長這樣

這裏寫圖片描述

看上去是不太複雜但是,實質上遇到很多操蛋的問題,我在這裏給大家羅列下


坑1: okhttp3.6那些事

這裏寫圖片描述

RN 0.43用的是ok http3.4.1
但是項目中用到了3.6.0
然後在websocket api的地方有兼容問題(當時心裏簡直操蛋)
解決方法

主項目添加兼容的dependencies設置

configurations.all { resolutionStrategy.force 'com.squareup.okhttp3:okhttp:3.4.1' }

相關文章:https://github.com/facebook/react-native/issues/11680


坑2 js bundle打不進項目,也就是 Js Server跑起來了,react-native run-android包是打了,但是他喵的js沒打進去(我也不知道怎麼日狗了)

方法1,打本地包(offline姿勢)

react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/

路徑根據你的具體項目而定

方法2,打js服務的包,也就是我上面提到的

curl "http://localhost:8081/index.android.bundle?platform=android" -o "android/app/src/main/assets/index.android.bundle"

結果會打一個bundle出來
這裏寫圖片描述


坑3 搖了沒反應

這個問題我還沒解決,或者說沒時間解決,交給給小夥們去幹了(一般是手機彈窗的授權問題相關)


坑4 執行 react-native run-android 安裝成功後 Activity class does not exist

這裏寫圖片描述
已知的錯誤場景:http://stackoverflow.com/questions/35131769/error-type-3-activity-class-com-awesome-project-com-awesome-project-mainactiv

具體的錯誤來源於項目的MainActivity不在根目錄。

方法1,遷移MainActivity.class
不解釋了,字面意思

方法2,改運行的腳本

其實也就是修改runAndroid.js

他在node_modules.react-native/local-cli/runAndroid/runAndroid.js

修改方式也很簡單,path肯定是拼接的,找到拼的代碼改了就行
這裏寫圖片描述

最佳解決指南:https://github.com/facebook/react-native/issues/5546

發佈了227 篇原創文章 · 獲贊 617 · 訪問量 105萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章