從Android到React Native開發(四、打包流程解析和釋出
作為失蹤人口,本篇是對前三篇React Native文章的番外補充,主要實現把React Native專案,打包為完整aar庫釋出到maven,提供庫支援的功能,算是小眾化的需求吧,不過透過本篇你可以瞭解:
React Native的資源的打包流程。
React Native原生依賴結構。
本地多aar檔案的合併實現。
進一步的Gradle指令碼理解。
如何釋出一個React Native的Maven庫。
OK,Let't do it (-_^)。
透過前幾篇,你已經對React Native的專案結構、通訊互動方式有了一定了解,不瞭解也沒關係((⊙_⊙)?), 我們知道,釋出一個maven庫,首先你要先有一個lib模組。
你需要在專案的android目錄下,即app
這個module的同級目錄下,建立一個Android Library的 module:rn-library
。(當然你也可以修改 app下的 apply plugin: "com.android.application"
為 apply plugin: 'com.android.library'
,再遮蔽applicationId
)。
一、引用
使用過React Native的應該知道,依賴的庫都是透過npm install安裝,安裝後的所有原始碼存在於node_modules
資料夾中,如果依賴的庫需要原生程式碼的支援,需要透過react-native link
實現原生程式碼模組的引用註冊。
而手動針對Android新增過link的應該熟悉,react-native link
實際上是透過指令碼,在 setting.gradle
檔案中引入模組在node_modules原生路徑,然後在 app 的module的build.gradle
中,透過compile project(':react-native-fs')
引用模組,最後在Application
的getPackages()
方法新增模組註冊。所以這裡我們明確了一點,專案引用的原生模組都是透過本地project module的引用。(這很重要( ̄へ ̄))
setting.gradle :
//在setting中指定模組的位置include ':react-native-fs'project(':react-native-fs').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-fs/android')
二、建立
看過的應該知道,React Native專案其實是透過ReactInstanceManager
,實現對js的bundle檔案載入的。所以要呈現一個React Native頁面,我們可以透過ReactInstanceManager
,在任意自定義Activity或者Fragment中,實現頁面的顯示渲染(當然你也可以直接繼承ReactActivity
)。這裡只列關鍵點點程式碼,即ReactInstanceManager
的建立和載入,如下發程式碼(更多可見篇章二):
mReactInstanceManager = ReactInstanceManager.builder() //設定載入檔案,這裡從assets中載入打包好的js bundle .setBundleAssetName("index.android.bundle") //異常輸出 .setNativeModuleCallExceptionHandler(new NativeModuleCallExceptionHandler() { @Override public void handleException(Exception e) { e.printStackTrace(); } }) //增加主模組註冊,必須 .addPackage(new MainReactPackage()) //增加使用你的第三方模組註冊 .addPackage(new RNFSPackage()) //通Application中指定的getJSMainModuleName .setJSMainModulePath("index") //是否支援開發者模式 .setUseDeveloperSupport(false) //初始化生命週期 .setInitialLifecycleState(LifecycleState.RESUMED) //設定Application .setApplication(getActivity().getApplication()) .build(); //js程式碼中註冊的的Component名字 AppRegistry.registerComponent('AppModule', () => App); String moduleName = "AppModule"; //透過頁面中已經宣告好ReactRootView,啟動 mReactRootView.startReactApplication(mReactInstanceManager, moduleName, null);
1、bundle檔案
從上方程式碼可以看出,我們直接載入 assets 目錄下的bundle檔案index.android.bundle
(當然你可以從本地或者網路載入jsbundle檔案也是可以),它的生成和複製是透過react-native目錄下的react.gradle
指令碼實現的。這個指令碼會讀取一些配置路徑,然後執行命令列打包和複製需要的資源,所以和app
的build.gradle檔案一樣,在rn-library
的build.gradle檔案頂部增加引入即可,打包後,預設生成的bundle文為即為index.android.bundle
檔案.。
//引入react指令碼apply from: "../../node_modules/react-native/react.gradle"
2、資原始檔
這裡有一個需要額外關注的點:根據node_nodules/react-native/local-cli/bundle/目錄下的assetPathUtils.js
檔案中,getAndroidResourceIdentifier
方法的原始碼可知,js檔案中引用本地的靜態資原始檔,如果存在多級目錄,是會被Encode處理的,其中/
會被替換為_
,數字會被遮蔽,assets_
會被遮蔽。
function getAndroidResourceIdentifier(asset: PackagerAsset) { var folderPath = getBasePath(asset); return (folderPath + '/' + asset.name) .toLowerCase() .replace(///g, '_') // Encode folder structure in file name .replace(/([^a-z0-9_])/g, '') // Remove illegal chars .replace(/^assets_/, ''); // Remove "assets_" prefix}
所以,比如放在React Native專案根目錄下的img/pic/logo.png
的資源,其實編譯時,會被重新命名後,複製merged到對應的是drawable目錄下,比如drawable-xxhdpi下的img_pic_logo.png
。這一切都是由react native中的指令碼執行的。不過預設情況下,生成複製的bundle檔案和resources資源路徑,是無法被打包到aar中的。所以如下程式碼所示,我們需要配置生成的資源自動新增到aar檔案中。
//預設路徑 //jsBundleDirRelease: "$buildDir/intermediates/assets/release //resourcesDirRelease: "$buildDir/intermediates/res/merged/release //修改為 project.ext.react = [ jsBundleDirRelease: "$buildDir/intermediates/bundles/release/assets", resourcesDirRelease: "$buildDir/intermediates/bundles/release/res", ]
三、打包
上面說過:React Native專案引用的原生模組,都是透過本地project module的引用。那麼預設的maven釋出方式,只會釋出指定module的aar檔案,對於引用的其他module模組,這些dependencies列在了與aar檔案同目錄的.pom檔案中,並不會打包僅aar,而明顯React Native的這些第三方支援包,並不是Maven庫。
這時候,就需要透過gradle指令碼,手動對依賴的module模組,實現aar檔案內容的合併。aar檔案本身和Apk一樣,其實是一個zip壓縮檔案,其中包含檔案如下所示:
/**主要檔案**/classes.jar R.txt AndroidManifest.xml res//**其他檔案**/proguard.txt libs/ jni/ ···
這裡所謂的合併,就是就是將所有需要的aar檔案內容,複製到一起,然後合併一個aar。當然,如何合併,合併的時機這些都是需要處理的點。而這時候, 指令碼,剛好滿足的我們的需求。透過引入apply from: 'fat-aar.gradle'
的指令碼,對需要合併模組引用修改為 embedded project(':react-native-fs')
依賴即可:
dependencies { embedded project(':react-native-fs') compile fileTree(dir: "libs", include: ["*.jar"]) compile "com.android.support:appcompat-v7:23.0.1" embedded "com.facebook.react:react-native:+" // From node_modules}
從指令碼程式碼中可以知道,這裡的embedded
實際上是一個configuration類,而這個configurations對應的是一個 ConfigurationContainer,ConfigurationContainer包含有dependencies,如下程式碼所示,最終還是使用compile
引用,但是這個過程中,我們透過embedded
統計到哪些包需要合併釋出。
configurations { embedded } dependencies { compile configurations.embedded }
因此我們可以根據build目錄下的一些檔案,動態的embedded
的module進行檔案複製和合並,如$build_dir/intermediates/exploded-aar
目錄下,對每個需要合併的module的res資料夾、libs資料夾、jars資料夾、assets資料夾等的複製。合併aar的流程如下圖所示,有興趣的可以深入瞭解: 。
圖片來自
最後我們可以先在rn-library
執行../gradlew assembleRelease
,讓react指令碼生成我們需要的資原始檔,然後再引用publish.gradle釋出aar到maven即可。
四、最後
如何,最終實現過程其實並不複雜,總結起來:
建立一個android.library
新增本地dependencies依賴
apply react.gradle 、 fat-aar.gradle、publish.gradle
在library透過../gradlew assembleRelease打包,然後透過
maven-publish
執行publish上傳。
Over(~ ̄ ̄)~
資源推薦:
作者:戀貓月亮
連結:
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4830/viewspace-2803044/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 從Android到React Native開發(四、打包流程解析和釋出為Maven庫)AndroidReact NativeMaven
- React Native釋出APP之打包iOS應用React NativeAPPiOS
- React Native專案自動化打包釋出React Native
- 從Android到React Native開發(二、通訊與模組實現)AndroidReact Native
- 從 Android 到 React Native 開發(三、自定義原生控制元件支援)AndroidReact Native控制元件
- 17-3 react native Android打包React NativeAndroid
- 說說Chrome外掛從開發除錯到打包釋出Chrome除錯
- React Native開發中自動打包指令碼React Native指令碼
- QT從入門到入土(八)——專案打包和釋出QT
- React Native Android混合開發實戰教程React NativeAndroid
- 開源React Native元件庫beeshell 2.0釋出React Native元件
- Android Native 開發之 NewString 與 NewStringUtf 解析Android
- react-native&android 之開發問題篇一ReactAndroid
- 開發 React Native APP —— 從改造官方Demo開始(1)React NativeAPP
- 開發 React Native APP —— 從改造官方Demo開始(2)React NativeAPP
- Airbnb: React Native 從選擇到放棄AIReact Native
- 《React Native高效開發》之create-react-native-appReact NativeAPP
- React Native釋出重構路線圖React Native
- Android開發學習之路--React-Native混合開發初體驗AndroidReact
- React Native 打包apk的那些坑React NativeAPK
- 詳解從 0 釋出 react 元件到 npm 上React元件NPM
- React Native填坑之旅 -- 從Native發事件給JSReact Native事件JS
- Android APK打包流程AndroidAPK
- [譯] React Native 與 iOS 和 Android 通訊React NativeiOSAndroid
- React Native 開發規範React Native
- 手把手教你React Native實戰從 React到Rn《二》React Native
- React Native在Android當中實踐(四)——程式碼整合React NativeAndroid
- 如何設計npm包的開發和釋出流程NPM
- React Native填坑之旅--開啟TurboModule(Android)React NativeAndroid
- React Native 0.55.4 Android 原始碼分析(Java層原始碼解析)React NativeAndroid原始碼Java
- React Native JSON解析和輔助函式(2)React NativeJSON函式
- react native 和原生平臺 android的互動React NativeAndroid
- 淺談Android打包流程Android
- 2023年最新iOS打包釋出流程彙總iOS
- (2018-05-04.Python從Zero到One)四、(前端)前端頁面開發流程__1.4.0前端頁面開發流程...Python前端
- React-native 開發小技巧React
- React Native 開發環境搭建React Native開發環境
- React-Native iOS Module開發ReactiOS