轉載請註明出處王亟亟的大牛之路
最近都在忙着搭架子,找框架,談需求和開會。甚至都沒有時間好好裝逼,昨天幫安卓的小夥把項目從安卓整體遷移到了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
具體的錯誤來源於項目的MainActivity不在根目錄。
方法1,遷移MainActivity.class
不解釋了,字面意思
方法2,改運行的腳本
其實也就是修改runAndroid.js
他在node_modules.react-native/local-cli/runAndroid/runAndroid.js
修改方式也很簡單,path肯定是拼接的,找到拼的代碼改了就行