RN打包

什么是JSBundle

JSBundle 是 JS代碼打包后的產(chǎn)物枪蘑,在React-native里面主要是通過(guò)react-native-cli提供的命令進(jìn)行打包磺樱。跟網(wǎng)頁(yè)類似秫逝,一個(gè)RN項(xiàng)目除了代碼還會(huì)有資源文件古程,比如本地圖片煎殷、JSON等屯伞,這些都會(huì)放到跟JSbundle同級(jí)的assets目錄下。這些文件可以內(nèi)置在原生的工程里豪直,在原生工程啟動(dòng)時(shí)通過(guò)RN官方提供的方法加載JSbundle劣摇,并放到JS引擎中執(zhí)行。也可以打成壓縮包之后通過(guò)網(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)通過(guò)npm依賴的方式集成到react-native源碼中,也可以單獨(dú)下載(https://github.com/react-native-community/cli#documentation)语卤,具體命令可通過(guò)官方文檔或npx react-native --help 查閱

JSBundle格式

原始格式

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


jsbundle-minify.png

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


jsbundle.png

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

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


jsbundle-3.png

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

官方為了縮減JSbundle的大小堰塌,對(duì)很多函數(shù)做了簡(jiǎn)化處理赵刑,例如declare變成了__d, require變成了__r。

Hermes二進(jìn)制格式

二進(jìn)制格式的本質(zhì)是字節(jié)碼场刑,字節(jié)碼是JS轉(zhuǎn)成可執(zhí)行代碼的中間形式般此。由于JS代碼在 JS引擎里面需要編譯為字節(jié)碼或者機(jī)器碼才能執(zhí)行,這一階段比較耗時(shí)牵现,而且每次啟動(dòng)都是執(zhí)行铐懊,明顯是屬于重復(fù)工作。為了減少這個(gè)時(shí)間瞎疼,官方推出了hermes二進(jìn)制格式科乎,也就是我們說(shuō)的字節(jié)碼,支持預(yù)編譯并且可以緩存在本地贼急,減少二次編譯茅茂,甚至可以在生成JSbundle的時(shí)候就編譯為二進(jìn)制格式。關(guān)于字節(jié)碼的詳細(xì)解釋竿裂,可以參考我這篇博客(http://www.reibang.com/p/af772cc66428),這里就不詳細(xì)解釋了玉吁。

RAM格式

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

打包腳本

我們使用react-native bundle命令來(lái)打包,假設(shè)打出來(lái)的包都放在 build 這個(gè)目錄下矫户,我們需要執(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)制文件中對(duì)應(yīng)函數(shù)的偏移量的映射關(guān)系)。注意這里-output-source-map的值是上一步生成的JSBundle皆辽,并非我們通常所說(shuō)的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驱闷。這一步不是必須的耻台,但是如果你想通過(guò)sentry之類的錯(cuò)誤收集平臺(tái)來(lái)找到出錯(cuò)的代碼,并且JSbundle是使用了hermes二進(jìn)制格式的空另,就一定要上傳這個(gè)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開(kāi)發(fā)里面的webpack扼菠。前面說(shuō)的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三個(gè)階段循榆,分別是解析源碼生成module的依賴圖析恢、轉(zhuǎn)換module的格式已被目標(biāo)平臺(tái)所理解以及序列化生成最終產(chǎn)物,三個(gè)階段官方有提供默認(rèn)的實(shí)現(xiàn)(比如transformer是使用了babel)冯痢,也提供了配置來(lái)替換一些關(guān)鍵函數(shù)氮昧。metro內(nèi)部會(huì)根據(jù)依賴圖的變化計(jì)算新增、修改和刪除的模塊浦楣,并且通過(guò)緩存transformer的結(jié)果來(lái)提升debug時(shí)的熱更新效率。關(guān)于metro有很多博客介紹咪辱,可以參考http://www.reibang.com/p/5730da61132f振劳。

metro.png

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

hermesc

這是hermes的一個(gè)命令行工具专筷,封裝了hemres用到的常用函數(shù)弱贼,其中-emit-binary 功能是根據(jù)傳入的路徑找到j(luò)sbundle,加載內(nèi)容磷蛹,然后一行一行的解析吮旅,將JS編譯為字節(jié)碼,同時(shí)生成映射文件味咳。這個(gè)工具也支持dump字節(jié)碼庇勃、AST檬嘀、IR以及解析JSX、ts等功能责嚷,可以說(shuō)是非常全面了鸳兽。可以輸入./node_modules/react-native/sdks/hermesc/osx-bin/hermesc --help 查看所有的命令

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末罕拂,一起剝皮案震驚了整個(gè)濱河市揍异,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌爆班,老刑警劉巖衷掷,帶你破解...
    沈念sama閱讀 222,104評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蛋济,居然都是意外死亡棍鳖,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,816評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)镀裤,“玉大人容劳,你說(shuō)我怎么就攤上這事∫教保” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 168,697評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵旧困,是天一觀的道長(zhǎng)醇份。 經(jīng)常有香客問(wèn)我,道長(zhǎng)吼具,這世上最難降的妖魔是什么僚纷? 我笑而不...
    開(kāi)封第一講書人閱讀 59,836評(píng)論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮拗盒,結(jié)果婚禮上怖竭,老公的妹妹穿的比我還像新娘。我一直安慰自己陡蝇,他們只是感情好痊臭,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,851評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著登夫,像睡著了一般广匙。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上恼策,一...
    開(kāi)封第一講書人閱讀 52,441評(píng)論 1 310
  • 那天鸦致,我揣著相機(jī)與錄音,去河邊找鬼。 笑死蹋凝,一個(gè)胖子當(dāng)著我的面吹牛鲁纠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鳍寂,決...
    沈念sama閱讀 40,992評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼改含,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了迄汛?” 一聲冷哼從身側(cè)響起捍壤,我...
    開(kāi)封第一講書人閱讀 39,899評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎鞍爱,沒(méi)想到半個(gè)月后鹃觉,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,457評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡睹逃,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,529評(píng)論 3 341
  • 正文 我和宋清朗相戀三年盗扇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沉填。...
    茶點(diǎn)故事閱讀 40,664評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡疗隶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出翼闹,到底是詐尸還是另有隱情斑鼻,我是刑警寧澤,帶...
    沈念sama閱讀 36,346評(píng)論 5 350
  • 正文 年R本政府宣布猎荠,位于F島的核電站坚弱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏关摇。R本人自食惡果不足惜荒叶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,025評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望输虱。 院中可真熱鬧停撞,春花似錦、人聲如沸悼瓮。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,511評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)横堡。三九已至,卻和暖如春冠桃,著一層夾襖步出監(jiān)牢的瞬間命贴,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,611評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留胸蛛,地道東北人污茵。 一個(gè)月前我還...
    沈念sama閱讀 49,081評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像葬项,于是被迫代替她去往敵國(guó)和親泞当。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,675評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

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