1. 程式人生 > >Native專案遷入React-Native過程中遇到的坑(0.4x版本)

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

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

由來

專案剛開始的階段我還不在場(最初的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' }

坑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

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

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

方法2,改執行的指令碼

其實也就是修改runAndroid.js

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

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