命令行
运行 react-native bundle
打包命令会发生什么?
从命令的入口 react-native/package.json/bin
层层深入(five minutes later...),发现最终会用 @react-native-community/cli
中的 buildBundle 方法进行打包。
有意思的是这个方法内部并没有调用 metro
对外暴露的 打包 API,而是直接粗暴使用 metro
源码进行打包(我™直呼内行)。
接下来进入打包主流程。
主流程
打包后输出的包可以分为普通 bundle
、RAM bundle
,这里主要分析打包普通 bundle
的流程。
在打包时,metro
会启动一个服务器 Server
,它可以做一些打包、缓存和文件热替换工作。
其中,构建器 Bundler
会遍历文件并分成一个个模块,随后将这些模块导入 Serializer
流程进行合并,得到一个完整的打包文件 bundle.js
。
流程:Bundler
在 Bundler
类中,Resolver
负责管理依赖树和模块,Transformer
负责编译 js 和静态资源,它们是并行工作的。
DeltaCalculator
: 主要负责计算依赖变化。
WorkerFarm
: 使用单、多线程(根据配置)调用 babel
执行编译操作。
简单来说,DeltaCalculator
会将打包入口路径传给 Transformer
,后者通过 babel
遍历编译得出 graph
(ast
、code
和依赖树),然后返回到 DeltaCalculator
中保存。
这个过程会执行多次,因为除了业务代码,还有一些 polify
需要打包成模块,所以整个流程为:
1.根据业务入口,编译出一份依赖表和 n 个模块对象(一个文件就是一个模块)。
2.根据 polify
依赖入口,编译出另一份依赖表和多个模块,和步骤一结果进行合并。
3.进入 Serializer
流程合并所有模块,输出完整代码。
额外知识:
DeltaCalculator
内部维护 deletedFiles
、modifiedFiles
两个对象,通过 node-haste
去监听依赖文件的变化,进行增量刷新。
流程:Serializer
这块应该是最没有技术难度的部分。负责处理模块整合,核心代码是 baseJSBundle 和 bundleToString。
首先编译生成的模块代码用的是类 AMD
模块化。
// 每个模块 code 如下
// __d() 表示定义一个模块
__d(function(g,r,i,a,m,e,d){r(d[0]),r(d[1])},0,[1,356]);
polify
的代码比较特殊,是段立即执行的函数,在合包时放在最前。
其余模块将各自的 code
相加,如下:
// 我是 polify
!(function(r){})(); // ....
// 我是模块
__d(function(g,r,i,a,m,e,d){r(d[0]),r(d[1])},0,[1,356]);
__d(function(g,r,i,a,m,e,d){r(d[2]),r(d[3])},0,[1,111]);
// ...
看到这里我也有点无语,这字符串相加合包是真的简单粗暴。但是这段代码总觉得缺少一点什么。没错,现在各个模块都声明好了,却没有入口去调用,这就把入口代码补上。
// 我是 polify
!(function(r){})(); // ....
// 我是模块
__d(function(g,r,i,a,m,e,d){r(d[0]),r(d[1])},0,[1,356]);
__d(function(g,r,i,a,m,e,d){r(d[2]),r(d[3])},0,[1,111]);
// ...
// 我是入口
__r(0);
到这里,一个完整的 bundle
字符串已经生成好了,接下来将字符串写入文件就是整包 bundle.js
。
最后从之前打包出的模块列表中,找出谁是静态资源,拷贝到相应的静态资源路径下,结束整个打包流程。
结束语
react-native bundle
命令算是比较简单的打包流程,如果涉及到监听文件进行热替换、缓存,复杂度会上升,留待下次梳理吧~。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!