为什么选择 Metro?
编辑
了解为什么 Metro 是 React Native 通用打包的未来,以及它如何惠及开发者。
Metro 是 Expo 和 React Native 的官方打包工具。它是 Expo 框架中的一个核心构建工具。打包工具包含成千上万的意见和权衡。本文档概述了 Expo 为什么围绕 Metro 开发的主要原因以及它如何惠及开发者。
官方 Meta 打包工具
Metro 由 Meta 维护,Meta 是 React、React Native、Yoga 和 Hermes 的维护者。它被用于开发一些全球最大的应用程序,涵盖了应用商店中的所有类别。
Meta 工程师积极开发 Metro,明确要求将他们所有的应用程序打包,涵盖超过 40 万个源文件,同时保持快速和可靠。
通过提供一流的 Metro 支持,我们确保 Expo 开发者在 Meta 的工具之间保持连续性,并立即访问新兴功能。这包括:
- React Fast Refresh 于 2019 年作为 Metro 的一项功能首次推出。React 网页社区在第二年通过 Webpack 采用了它。
- 将 JavaScript 转换为 Hermes 字节码,以实现即时原生启动。
- React Native DevTools,包括对 网络和 JS 调试 的一流支持,专门与 Metro 和 Hermes 一起使用。
- React Compiler 最初作为与 Metro 兼容的 Babel 插件发布。
计划在 Metro 中推出的新功能包括:
- 使用 Static Hermes 将 Flow 代码编译为原生机器代码。有关更多信息,请查看 Tzvetan Mikov 的 Static Hermes 讲座。
- 数据获取、流处理、React Suspense、服务器渲染,以及使用通用 React 服务器组件的构建时静态渲染,适用于所有平台。有关更多信息,请查看 React Conf 2024 的 Universal React Server Components 讲座。
Expo 团队与 Meta 合作开发旨在为 Expo Router 提供 Metro,增加了 基于文件的路由、Web 支持、捆绑拆分、树摇、CSS、DOM 组件、服务器组件和 API 路由 等功能。
大规模实战检验
几乎世界上每个 React Native 应用程序都在使用 Metro,这使其成为一个经过实战检验的解决方案,优化了大规模项目的使用。这使其适用于从业余爱好者到大型公司的所有规模开发者。Metro 专门设计用来处理大规模 Meta 应用程序,这就是为什么它具有如 Watchman 的原生文件监视和 共享远程缓存 这样的功能。
按需处理
在开发过程中,Metro 直到请求时才执行任何特定于平台的工作。这使开发者能够在不为所支持平台数量支付性能成本的情况下,进行大型项目的开发。结合激进的缓存和 异步路由,开发者可以增量打包他们正在积极处理的应用程序部分。
多维度
与传统的打包工具不同,这些工具创建多个实例以捆绑服务器和客户端代码,而 Metro 最大化了跨平台和环境(服务器、客户端、DOM 组件)之间的资源重用。这种架构非常适合多平台和服务器开发。
可重用的转换记忆化
Metro 是增量式的,可以创建可在多台机器上使用的缓存转换工件。这使大型团队能够重用来自远程构建器的工作,这是 Meta 在所有大型项目中使用的一种技术。
针对自定义运行时优化
尽管其他打包工具围绕Web浏览器的静态规范而设计,Metro则针对React Native的灵活性进行了优化。这使得生成所需的特定语言特性集成为可能,以进行 Hermes 字节码编译,从而在生产中实现更快的应用程序启动。这也将扩展到 Static Hermes,它将静态类型信息编译为原生应用程序的机器代码。
跨技术支持
Expo 利用 Metro 的技术来创建新颖的功能,如 DOM 组件。这使得在原生应用程序中的 React 组件能够动态捆绑为整个网站,并与父应用程序共用所有相同的默认设置,按需进行。
原生资产导出
与传统打包工具的最终结果是完全托管的应用程序不同,Metro 的配置选项支持将捆绑导出为嵌入到独立应用程序二进制文件中的原生工件。这利用了 Apple 平台上诸如 xcassets 的操作系统特定优化。
并发处理
Metro 中的所有 AST 转换都是在所有可用线程上并发执行,最大化硬件的使用。
与其他方法的比较
虽然 Metro 是为通用应用程序开发而设计的,但它常常与其他仅限于 Web 的打包工具进行比较。以下是一些关键区别:
浏览器 ESM 与打包
虽然像 Vite 这样的打包工具利用浏览器内置的 ESM 支持,但这种方法在中到大规模时可能会导致较慢的实际开发时间,因为存在数千个级联的网络请求。Metro 在本地开发中执行打包,这使得开发结果与生产结果更接近,并且更适合 React Native 的更大模块数量。
JavaScript 与原生语言
一些打包工具选择用 Rust 编写其核心以提高性能,但这也带来了一些权衡,例如更具挑战性的贡献、补丁和开发。Metro 根据操作使用一系列技术:
- 核心打包工具和实用程序用 JS/Flow 编写。
- 文件监视通过 Watchman 用 C++ 编写,并具有 JS 备份。Watchman 随后在计算机上的各个项目中使用。
- AST 使用 Hermes 解析器(WebAssembly)解析为 Babel 兼容格式。
- AST 转换使用 Babel 执行。这最大化了开发者的自定义。
- 在原生平台上使用 Hermes 进行压缩,而在 Web 上使用 Terser(可选的 ESBuild 支持)。
- CSS 解析和压缩使用 LightningCSS(Rust)执行。
这种方法与 Meta 和社区工具保持一致,同时使开发者更容易进行调试、分析和修补。