ReactNative进阶(二十八)Metro

文章目录

一、前言

众所周知,Metro 是 React Native 默认的 JavaScript 打包模块。对于前端项目,打包工具已有webpack(大而全,图片代码打包),rollup(专攻代码打包,框架场景常见)等,既然有这些打包工具为什么还要在移动端搞一个metro,其中一个原因为ram bundle,iOS采用indexed ram bundle读取一个文件效率更高,Android采用file ram bundle。

二、Metro生命周期

metro的bundling有三个阶段:

  • 解析 (Resolution): 解析所有模块并且构建成图,有点类似于Gradle在配置阶段会将所有相互依赖的任务构建成图。
  • 转换 (Transformation):转换阶段会将模块转换成目标平台能识别的格式,这一阶段执行了js编译,主流常用的js编译器为babel。
  • 序列化 (Serialization):最后一个阶段序列化,会将所有转换之后的模块打包成一个或者多个bundle。

2.1 解析(Resolution)

在Gradle 配置阶段我们常看到assets、aidl、res、java的配置。

javascript 复制代码
android{
    ...
    sourceSets {
        main {
            java.excludes = [
                    '**/build/**',
            ]
            srcDirs.forEach {
                assets.srcDirs += "$projectDir/$it/main/assets"
                aidl.srcDirs += "$projectDir/$it/main/aidl"
                res.srcDirs += "$projectDir/$it/main/res-frame-animation"
                res.srcDirs += "$projectDir/$it/main/res"
                java.srcDirs += "$projectDir/$it/main/java"
            }
        }
    }
    ...
}

metro与之对应项为assetExts、sourceExts。

2.2 转换(Transformation)

在ram bundle的启动优化中,通过getTransformOptions可以实现模块预加载,而其他的模块按需加载从而提高启动速度。

javascript 复制代码
function getTransformOptions(
  entryPoints: $ReadOnlyArray<string>,
  options: {
    dev: boolean,
    hot: boolean,
    platform: ?string,
  },
  getDependenciesOf: (path: string) => Promise<Array<string>>,
): Promise<ExtraTransformOptions> {
  // ...
}

type ExtraTransformOptions = {
  preloadedModules?: {[path: string]: true} | false,
  ramGroups?: Array<string>,
  transform?: {
    inlineRequires?: {blockList: {[string]: true}} | boolean,
    nonInlinedRequires?: $ReadOnlyArray<string>,
  },
};

在preloadedModules中配置的模块为预加载模块,而其他的模块在ram bundle按需加载,这一块有点类似于Android multidex,Android5.0之前可以将部分类指明到主dex,其他被分配到辅dex。在Android App的构建流程中,编译完之后还会对字节码进行混淆,这块metro也有minifierPath(默认使用metro-minify-terser)、minifierConfig。在混淆这块除了terser,metro还提供了metro-minify-uglify。

2.3 序列化(Serialization)

在序列化的阶段模块需要有id以便于require导入,创建模块id的函数为createModuleIdFactory,而processModuleFilter决定了过滤掉哪些模块不进入bundle,所以通过createModuleIdFactory与processModuleFilter两个函数可以实现分包。

随着react-refresh、react-reconciler相继出现,react hot loader逐渐被替代,react refresh的实现与平台无关,React 、React Native等实现react-reconciler的自定义渲染器都能使用,而且react refresh能hot的颗粒度更小。在Web平台使用react refresh 。移动平台则是React Native团队自己实现且内置到了metro打包器取名fast-refresh。

三、拓展阅读

相关推荐
paopaokaka_luck2 小时前
基于springboot+vue的智慧家政管理系统(AI问答、 WebSocket实时沟通、ECharts运营分析、订单规则与服务追踪)
java·javascript·spring boot·数据分析·echarts·mybatis
weixin_448119943 小时前
Datawhale Easy Data × AI:构建知识与记忆驱动的 Agent笔记8
人工智能·笔记·react.js
溪语流沙3 小时前
【每天一个CSS | Day19】流光文字与一笔写成的手写签名
前端·javascript·css
CDwenhuohuo3 小时前
electron pc项目打包成桌面端
前端·javascript·electron
EatFan6 小时前
React 项目踩坑实录:useEffect 闭包陷阱、Context 性能陷阱与 React 18 升级避坑排查手册
前端·javascript·react.js·react·react hooks·useeffect·闭包陷阱
w2sfot9 小时前
【JS加密在线】jsjiami.online(让JavaScript 更安全!)
开发语言·javascript·安全
梦想的颜色10 小时前
【编程实战】AI 时代 APP 开发全栈硬核指南:技术选型 + AI 架构 + 模型落地全维度决策
python·flutter·react native·react.js·ai·桌面应用·milvus
知野小兔11 小时前
对比react钩子函数
react.js
杨杰39813 小时前
我给嵌入式设备写了个 6MB 的 JavaScript 运行时(xuan)
javascript
只睡四小时14 小时前
AI 生成 PPTX:11 页课件编译出 429 个形状
javascript·python·pptx·ai生成ppt·ooxml