RN打包

什么是JSBundle

JSBundle 是 JS代码打包后的产物,在React-native里面主要是通过react-native-cli提供的命令进行打包。跟网页类似,一个RN项目除了代码还会有资源文件,比如本地图片、JSON等,这些都会放到跟JSbundle同级的assets目录下。这些文件可以内置在原生的工程里,在原生工程启动时通过RN官方提供的方法加载JSbundle,并放到JS引擎中执行。也可以打成压缩包之后通过网络下载(也就是热更新)后再在本地执行。

react-native-cli

React-native官方提供的命令行工具,里面包含了拉取react-native模版工程(init命令)、诊断运行环境(doctor命令)、打包(bundle命令),以及远程调试(本地node服务)所用到的代码。默认通过npm依赖的方式集成到react-native源码中,也可以单独下载(https://github.com/react-native-community/cli#documentation),具体命令可通过官方文档或npx react-native --help 查阅

JSBundle格式

原始格式

原始格式是纯文本的JS代码,默认情况下会进行压缩和混淆


jsbundle-minify.png

当打包时关闭掉-minify选项后,可以看到原始的代码


jsbundle.png

JSbundle里每一行都是一个module,也就是一个文件的内容,在每一行的末尾会有该module的ID和所依赖的其他module的ID
jsbundle-2.png

moduleId是根据编译时的顺序生成的,默认是从0开始生成,按文件依次递增。前面的内容都是框架自带的module,我们自己写的module通常在后面。


jsbundle-3.png

本文是根据官方提供的awesome project模版拉取的代码并生成的jsbunble,可以跟源码对比看看有什么差异。

官方为了缩减JSbundle的大小,对很多函数做了简化处理,例如declare变成了__d, require变成了__r。

Hermes二进制格式

二进制格式的本质是字节码,字节码是JS转成可执行代码的中间形式。由于JS代码在 JS引擎里面需要编译为字节码或者机器码才能执行,这一阶段比较耗时,而且每次启动都是执行,明显是属于重复工作。为了减少这个时间,官方推出了hermes二进制格式,也就是我们说的字节码,支持预编译并且可以缓存在本地,减少二次编译,甚至可以在生成JSbundle的时候就编译为二进制格式。关于字节码的详细解释,可以参考我这篇博客(https://www.jianshu.com/p/af772cc66428),这里就不详细解释了。

RAM格式

RAM也是一种二进制格式,推出的目的是为了压缩包大小,主要是将jsbundle按模块拆分为单个的文件以支持按需加载,但是由于只支持iOS,并没有真正推广起来。想了解可以看官方介绍(https://facebook.github.io/metro/docs/bundling),不推荐深入研究。

打包脚本

我们使用react-native bundle命令来打包,假设打出来的包都放在 build 这个目录下,我们需要执行以下指令:

  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二进制文件index.android.bundle.hbc及其与源码的映射文件index.android.bundle.hbc.map(主要是记录模块的VLQ编码与二进制文件中对应函数的偏移量的映射关系)。注意这里-output-source-map的值是上一步生成的JSBundle,并非我们通常所说的sourcemap文件。不同的版本hermesc的位置略有不同,可执行
    ./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. 根据第1步生成的sourcemap以及第2步生成的映射文件生成二进制文件的sourcemap。这一步不是必须的,但是如果你想通过sentry之类的错误收集平台来找到出错的代码,并且JSbundle是使用了hermes二进制格式的,就一定要上传这个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专用的打包工具,有点类似web开发里面的webpack。前面说的react-native bundle命令背后就是用的metro(可参考代码 https://github.com/react-native-community/cli/tree/main/packages/cli-plugin-metro),关于metro的使用可以参考官方文档(https://facebook.github.io/metro/docs/concepts)

metro 大致可以分为resolver、transformer和Serialization三个阶段,分别是解析源码生成module的依赖图、转换module的格式已被目标平台所理解以及序列化生成最终产物,三个阶段官方有提供默认的实现(比如transformer是使用了babel),也提供了配置来替换一些关键函数。metro内部会根据依赖图的变化计算新增、修改和删除的模块,并且通过缓存transformer的结果来提升debug时的热更新效率。关于metro有很多博客介绍,可以参考https://www.jianshu.com/p/5730da61132f

metro.png

我们做拆包,主要是针对Serialization这个阶段做修改,修改的函数包括createModuleIdFactory(自定义模块ID的生成规则,确保唯一即可)、processModuleFilter(根据module信息判断是否已经处理过,打业务包需要)

hermesc

这是hermes的一个命令行工具,封装了hemres用到的常用函数,其中-emit-binary 功能是根据传入的路径找到jsbundle,加载内容,然后一行一行的解析,将JS编译为字节码,同时生成映射文件。这个工具也支持dump字节码、AST、IR以及解析JSX、ts等功能,可以说是非常全面了。可以输入./node_modules/react-native/sdks/hermesc/osx-bin/hermesc --help 查看所有的命令

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • react-native因为是用JavaScript语言写的,所以需要把js代码和图片资源都放进apk中,所以打包...
    雪脩阅读 4,099评论 0 1
  • ANDROID:react-native bundle --entry-file index.js --bundl...
    liy_lmn阅读 222评论 0 0
  • 一、Native本地加载流程 1.1、React应用打包 1、导出.jsbundle包和图片资源 生成.jsbun...
    双鱼子曰1987阅读 1,771评论 0 2
  • 假设我们已经开发和调试好程序了。但是怎么发布呢? 我们知道现在我们运行程序是要把npm启起来的,所以我们是把js代...
    Viknando阅读 2,675评论 0 0
  • ios:react-native bundle --entry-file index.ios.js --bundl...
    yhj0129阅读 372评论 0 1