RN打包

什么是JSBundle

JSBundle 是 JS代碼打包后的產(chǎn)物,在React-native里面主要是通過react-native-cli提供的命令進(jìn)行打包。跟網(wǎng)頁類似,一個RN項(xiàng)目除了代碼還會有資源文件,比如本地圖片、JSON等,這些都會放到跟JSbundle同級的assets目錄下。這些文件可以內(nèi)置在原生的工程里,在原生工程啟動時通過RN官方提供的方法加載JSbundle,并放到JS引擎中執(zhí)行。也可以打成壓縮包之后通過網(wǎng)絡(luò)下載(也就是熱更新)后再在本地執(zhí)行。

react-native-cli

React-native官方提供的命令行工具,里面包含了拉取react-native模版工程(init命令)、診斷運(yùn)行環(huán)境(doctor命令)、打包(bundle命令),以及遠(yuǎn)程調(diào)試(本地node服務(wù))所用到的代碼。默認(rèn)通過npm依賴的方式集成到react-native源碼中,也可以單獨(dú)下載(https://github.com/react-native-community/cli#documentation),具體命令可通過官方文檔或npx react-native --help 查閱

JSBundle格式

原始格式

原始格式是純文本的JS代碼,默認(rèn)情況下會進(jìn)行壓縮和混淆


jsbundle-minify.png

當(dāng)打包時關(guān)閉掉-minify選項(xiàng)后,可以看到原始的代碼


jsbundle.png

JSbundle里每一行都是一個module,也就是一個文件的內(nèi)容,在每一行的末尾會有該module的ID和所依賴的其他module的ID
jsbundle-2.png

moduleId是根據(jù)編譯時的順序生成的,默認(rèn)是從0開始生成,按文件依次遞增。前面的內(nèi)容都是框架自帶的module,我們自己寫的module通常在后面。


jsbundle-3.png

本文是根據(jù)官方提供的awesome project模版拉取的代碼并生成的jsbunble,可以跟源碼對比看看有什么差異。

官方為了縮減JSbundle的大小,對很多函數(shù)做了簡化處理,例如declare變成了__d, require變成了__r。

Hermes二進(jìn)制格式

二進(jìn)制格式的本質(zhì)是字節(jié)碼,字節(jié)碼是JS轉(zhuǎn)成可執(zhí)行代碼的中間形式。由于JS代碼在 JS引擎里面需要編譯為字節(jié)碼或者機(jī)器碼才能執(zhí)行,這一階段比較耗時,而且每次啟動都是執(zhí)行,明顯是屬于重復(fù)工作。為了減少這個時間,官方推出了hermes二進(jìn)制格式,也就是我們說的字節(jié)碼,支持預(yù)編譯并且可以緩存在本地,減少二次編譯,甚至可以在生成JSbundle的時候就編譯為二進(jìn)制格式。關(guān)于字節(jié)碼的詳細(xì)解釋,可以參考我這篇博客(http://www.itdecent.cn/p/af772cc66428),這里就不詳細(xì)解釋了。

RAM格式

RAM也是一種二進(jìn)制格式,推出的目的是為了壓縮包大小,主要是將jsbundle按模塊拆分為單個的文件以支持按需加載,但是由于只支持iOS,并沒有真正推廣起來。想了解可以看官方介紹(https://facebook.github.io/metro/docs/bundling),不推薦深入研究。

打包腳本

我們使用react-native bundle命令來打包,假設(shè)打出來的包都放在 build 這個目錄下,我們需要執(zhí)行以下指令:

  1. 這生成index.android.bundle和index.android.bundle.packager.map,分別是JSbundle和sourceMap文件
    npx react-native bundle --platform android --dev false --entry-file index.js --bundle-output ./build/index.android.bundle --sourcemap-output ./build/index.android.bundle.packager.map

  2. 生成hermes二進(jìn)制文件index.android.bundle.hbc及其與源碼的映射文件index.android.bundle.hbc.map(主要是記錄模塊的VLQ編碼與二進(jìn)制文件中對應(yīng)函數(shù)的偏移量的映射關(guān)系)。注意這里-output-source-map的值是上一步生成的JSBundle,并非我們通常所說的sourcemap文件。不同的版本hermesc的位置略有不同,可執(zhí)行
    ./node_modules/hermes-engine/osx-bin/hermesc -emit-binary -out ./build/index.android.bundle.hbc -output-source-map ./build/index.android.bundle

    ./node_modules/react-native/sdks/hermesc/osx-bin/hermesc -emit-binary -out ./build/index.android.bundle.hbc -output-source-map ./build/index.android.bundle

  3. 根據(jù)第1步生成的sourcemap以及第2步生成的映射文件生成二進(jìn)制文件的sourcemap。這一步不是必須的,但是如果你想通過sentry之類的錯誤收集平臺來找到出錯的代碼,并且JSbundle是使用了hermes二進(jìn)制格式的,就一定要上傳這個sourceMap。
    ./node_modules/react-native/scripts/compose-source-maps.js ./build/index.android.bundle.packager.map ./build/index.android.bundle.hbc.map -o ./build/index.android.bundle.map

metro

metro是react-native專用的打包工具,有點(diǎn)類似web開發(fā)里面的webpack。前面說的react-native bundle命令背后就是用的metro(可參考代碼 https://github.com/react-native-community/cli/tree/main/packages/cli-plugin-metro),關(guān)于metro的使用可以參考官方文檔(https://facebook.github.io/metro/docs/concepts)

metro 大致可以分為resolver、transformer和Serialization三個階段,分別是解析源碼生成module的依賴圖、轉(zhuǎn)換module的格式已被目標(biāo)平臺所理解以及序列化生成最終產(chǎn)物,三個階段官方有提供默認(rèn)的實(shí)現(xiàn)(比如transformer是使用了babel),也提供了配置來替換一些關(guān)鍵函數(shù)。metro內(nèi)部會根據(jù)依賴圖的變化計(jì)算新增、修改和刪除的模塊,并且通過緩存transformer的結(jié)果來提升debug時的熱更新效率。關(guān)于metro有很多博客介紹,可以參考http://www.itdecent.cn/p/5730da61132f

metro.png

我們做拆包,主要是針對Serialization這個階段做修改,修改的函數(shù)包括createModuleIdFactory(自定義模塊ID的生成規(guī)則,確保唯一即可)、processModuleFilter(根據(jù)module信息判斷是否已經(jīng)處理過,打業(yè)務(wù)包需要)

hermesc

這是hermes的一個命令行工具,封裝了hemres用到的常用函數(shù),其中-emit-binary 功能是根據(jù)傳入的路徑找到j(luò)sbundle,加載內(nèi)容,然后一行一行的解析,將JS編譯為字節(jié)碼,同時生成映射文件。這個工具也支持dump字節(jié)碼、AST、IR以及解析JSX、ts等功能,可以說是非常全面了??梢暂斎?code>./node_modules/react-native/sdks/hermesc/osx-bin/hermesc --help 查看所有的命令

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • react-native因?yàn)槭怯肑avaScript語言寫的,所以需要把js代碼和圖片資源都放進(jìn)apk中,所以打包...
    雪脩閱讀 4,237評論 0 1
  • ANDROID:react-native bundle --entry-file index.js --bundl...
    liy_lmn閱讀 275評論 0 0
  • 一、Native本地加載流程 1.1、React應(yīng)用打包 1、導(dǎo)出.jsbundle包和圖片資源 生成.jsbun...
    雙魚子曰1987閱讀 2,283評論 0 2
  • 假設(shè)我們已經(jīng)開發(fā)和調(diào)試好程序了。但是怎么發(fā)布呢? 我們知道現(xiàn)在我們運(yùn)行程序是要把npm啟起來的,所以我們是把js代...
    Viknando閱讀 2,776評論 0 0
  • ios:react-native bundle --entry-file index.ios.js --bundl...
    yhj0129閱讀 431評論 0 1

友情鏈接更多精彩內(nèi)容