rn打包分析

rn打包原来是packager,后来独立出一个专门的打包工具metro,构建工具的大致思路跟前端构建工具差很少,都会有一个启动文件,而后根据模块依赖关系把对应文件找到。前端

开发中打包

在开发中打包,咱们访问的是一个index.bundle,这个时候跟其余的前端构建工具一致,都是会启动一个node 服务,metro提供了一个createServer方法,这个方法结合http(s)模块构建出一个能够提供bundle文件的服务器,固然能够其余的node框架,好比express:node

const express = require('express');
const app = express();

app.use(
  metroBundlerServer.processRequest.bind(metroBundlerServer),
);

app.listen(8081);

咱们能够在浏览器中输入http://localhost:8081/index.bundle?platform=ios&dev=true
那么这个bundle文件就会被返回,而metroServer会提供几个方法来提供返回内容,能够是bundle也能够是其余静态资源,这里咱们访问的是bundle,那么就会使用processRequestBundle方法,这个方法会根据访问的url去找对应的js文件,而后打包成bundle文件
image.png
因此这里的虚拟目录根目录就是项目根目录,咱们能够独立的去访问某个目录下js文件,都会为咱们打包成bundle文件返回。react

bundle文件

这里简单分析下bundle文件,咱们简单的翻一下整个文件,就能够发现,前面除了第一行是设置环境变量,其余都是一些自执行函数,后面的全是_d函数,大体也能够猜出来,_d函数就是模块定义函数。咱们看前面的函数,第一个自执行函数里面有个很熟悉的东东,_d函数找到了,它被挂在到global下,在这个函数中把模块加载相关作了定义。
image.png
模块的id是一个createModuleIdFactory方法,而后咱们看到第一个定义的模块id是从11开始的,这是由于以前的polyfill文件生成也在调用这个函数。ios

function createModuleIdFactory() {
  const fileToIdMap = new Map();
  let nextId = 0;
  return path => {
    let id = fileToIdMap.get(path);
    if (typeof id !== 'number') {
      id = nextId++;
      fileToIdMap.set(path, id);
    }
    return id;
  };
}

然后面的几个函数咱们能够看到都是各类es6语法的polyfill,其中有个函数很特别,先是定义了一个inspect函数,里边大量的数据类型判断,以后从新定义了console方法,这里实际上是对console作了polyfill,可是因为rn的打印错误信息跟浏览器有不一致,因此前面会有不少数据类型判断,来保持跟浏览器控制台中打印的一致。
image.png
以后的紧接着就是咱们的项目启动模块,可是以后的就是rn、react以及其余依赖项目的模块,一致到全部的公共模块加载完才是咱们的业务模块。
image.pnges6

本地打包

本地打包也就是打包出实实在在的bundle文件,而不是虚拟目录下,命令使用这里就不说了,这里要注意的一点就是,若是你想在某个目录下存放你的bundle文件,这个目录必定要存在,metro不会帮你去建立目录。这个时候调用依然会是metro的server,只不过最终会输出bundle文件到指定目录。
打包后的bundle文件跟开发中的结构是一致的,可是咱们仔细看就会发现模块id变少了,前面的polyfill文件同样的,都是第一个模块ID都是11,也就是启动文件,那么就是中间的模块便少了,其实就是一些公共模块作了合并,因此看起来少了。express

总结

基原本说只要rn和react等基础包版本不变,那么打包出来的bundle文件公共部分就是相同的,这里也利于咱们进行基础包也业务包的分离。浏览器

相关文章
相关标签/搜索