为什么是 Metro?

了解为什么 Metro 是 React Native 中通用打包的未来以及它如何使开发者受益。


Metro 是 Expo 和 React Native 的官方打包工具。它是 Expo 框架中的核心构建工具。打包工具涉及成千上万的选择和权衡。本文档概述了 Expo 围绕 Metro 开发的主要原因以及它如何为开发者带来益处。

官方 Meta 打包器

🌐 Official Meta bundler

Metro 由 Meta 维护,Meta 也是 React、React Native、Yoga 和 Hermes 的维护者。它用于开发一些世界上最大的应用,涵盖应用商店中的各类应用。

🌐 Metro is maintained by Meta, the maintainers of React, React Native, Yoga, and Hermes. It's used for developing some of the world's largest apps, ranging across all categories in the app stores.

Meta 工程师积极开发 Metro,明确要求将所有应用(超过 40 万个源文件)打包在一起,同时保持快速可靠。

🌐 Meta engineers actively develop Metro with the express requirement of bundling all their apps, across 400k+ source files, while remaining fast and reliable.

通过提供一流的 Metro 支持,我们确保 Expo 开发者在 Meta 的工具之间能够保持连续性,并能够立即访问新兴功能。这包括:

🌐 By having first-class Metro support, we ensure Expo developers have continuity across Meta's tools and get instant access to emerging features. This includes:

  • React Fast Refresh 最早在 2019 年作为 Metro 功能被引入。随后一年,React 网页社区通过 Webpack 采用了它。
  • 将 JavaScript 转换为 Hermes 字节码以实现即时原生启动。
  • React Native 开发工具,包括对 网络和 JS 调试 的一流支持,仅适用于 Metro 和 Hermes。
  • React Compiler 最初是作为 Metro 兼容的 Babel 插件推出的。

计划加入 Metro 的新功能和即将推出的功能包括:

🌐 New and upcoming features that are planned to come to Metro include:

  • 使用静态 Hermes 将 Flow 代码编译为本地机器代码。在 Tzvetan Mikov 的 静态 Hermes 演讲中了解更多信息。
  • 数据获取、流式传输、React Suspense、服务器渲染,以及面向所有平台的通用 React 服务器组件的构建时静态渲染。想了解更多内容,请参见 React Conf 2024 上的 通用 React 服务器组件 讲座。

Expo 团队与 Meta 合作开发了用于 Expo Router 的 Metro,添加了诸如 基于文件的路由Web 支持包拆分树摇CSSDOM 组件、服务器组件以及 API 路由 等功能。

🌐 The Expo team collaborates with Meta to develop Metro for Expo Router, adding features like file-based routing, web support, bundle splitting, tree shaking, CSS, DOM components, server components, and API routes.

大规模实战测试

🌐 Battle-tested at scale

几乎世界上每一个 React Native 应用都使用 Metro,这使它成为一个经过实战检验、针对大型项目优化的解决方案。这使其适合各种规模的开发者,从爱好者到大型公司。Metro 专为处理大规模 Meta 应用而设计,这也是它具备像使用 Watchman 的本地文件监控和共享远程缓存等功能的原因。

🌐 Nearly every React Native app in the world uses Metro, making it a battle-tested solution optimized for large-scale projects. This makes it suitable for developers of all sizes, from hobbyists to large companies. Metro is designed specifically to handle large-scale Meta apps, which is why it has features such as native file watching with Watchman and shared remote caches.

按需处理

🌐 On-demand processing

在开发过程中,Metro 不会执行任何特定平台的工作,除非有请求。这允许开发者在处理大型项目时,不会因为支持的平台数量而产生性能开销。结合积极的缓存和异步路由,开发者可以逐步打包应用中他们正在主动开发的部分。

🌐 In development, Metro doesn't perform any platform-specific work until requested. This allows developers to work on large projects without paying a performance cost for the number of platforms they support. In conjunction with aggressive caching and async routes, developers can incrementally bundle only the parts of the app that they're actively working on.

多维

🌐 Multi-dimensional

与传统打包工具不同,传统打包工具会创建多个实例来打包服务器端和客户端代码,而 Metro 最大化了跨平台和环境(服务器、客户端、DOM 组件)的资源重用。这种架构非常适合多平台和服务器开发。

🌐 Unlike traditional bundlers, which create multiple instances to bundle server and client code, Metro maximizes resource reuse across platforms and environments (server, client, DOM components). This architecture is ideal for multiplatform and server development.

回滚到上一个更新版本

🌐 Reusable transform memoization

Metro 是增量式的,可以创建可跨机器使用的缓存转换工件。这使得大型团队能够重用远程构建者的工作,这是 Meta 在所有大型项目中使用的一种技术。

🌐 Metro is incremental and can create cached transform artifacts that can be used across machines. This enables large teams to reuse work from remote builders, a technique used at Meta for all large projects.

针对自定义运行时进行了优化

🌐 Optimized for custom runtimes

虽然其他打包工具是围绕网页浏览器的静态规范设计的,但 Metro 是为 React Native 的灵活性而优化的。这使得一些功能成为可能,例如生成 Hermes 字节码编译所需的特定支持语言特性集,从而在生产环境中实现更快的应用启动速度。这也将扩展到 Static Hermes,它会将静态类型信息编译成用于原生应用的机器码。

🌐 While other bundlers are designed around the static specification of web browsers, Metro is optimized for the flexibility of React Native. This enables features like generating the specific set of supported language features required for Hermes bytecode compilation which enables faster app startup in production. This will also extend to Static Hermes, which will compile static type information into machine code for native apps.

跨技术支持

🌐 Cross-technology support

Expo 利用 Metro 的技术创建诸如 DOM 组件 之类的新功能。这使得原生应用中的 React 组件能够按需动态打包为完整的网站,并使用与父应用相同的默认设置。

🌐 Expo leverages Metro's technology to create novel functionality like DOM components. This allows a React component in a native app to be dynamically bundled as an entire website with all the same defaults as the parent app, on-demand.

原生资源导出

🌐 Native asset exports

与传统的打包工具不同,传统工具生成的最终结果是一个完整托管的应用,而 Metro 的配置选项支持将打包输出导出为可嵌入的本地组件,用于独立应用的二进制文件中。这利用了操作系统特定的优化,例如 Apple 平台上的 xcassets

🌐 Unlike traditional bundlers, where the end result is a fully hosted app, Metro's configuration options support exporting bundles to embed as native artifacts in standalone app binaries. This leverages OS-specific optimizations such as xcassets on Apple platforms.

并发处理

🌐 Concurrent processing

Metro 中的所有 AST 转换都是在所有可用线程上同时执行的,从而最大限度地利用硬件。

🌐 All AST transformation in Metro is performed concurrently across all available threads, maximizing the use of hardware.

与其他方法的比较

🌐 Comparison with other approaches

虽然 Metro 是为通用应用开发而设计的,但它经常被拿来与其他仅支持网页的打包工具进行比较。以下是一些主要区别:

🌐 While Metro is designed for universal app development, it's often compared to other web-only bundlers. Here are some key differences:

浏览器 ESM 与打包

🌐 Browser ESM versus bundling

虽然像 Vite 这样的打包工具利用了浏览器中内置的 ESM 支持,但在中大型项目中,这种方式可能会导致实际开发时间变慢,因为会产生成千上万的级联网络请求。Metro 在本地开发时进行打包,这使得开发结果与生产结果更为接近,更适合 React Native 的大量模块。

🌐 While bundlers like Vite leverage built-in ESM support in the browser, this approach can lead to slower practical development times at medium to large scales due to thousands of cascading network requests. Metro performs bundling in local development, which aligns the development results much closer to the production results and is better suited for React Native's larger module count.

JavaScript 与原生语言

🌐 JavaScript versus native languages

出于性能原因,一些打包工具选择用 Rust 编写其核心,但这也带来了一些权衡,例如贡献、修补和开发更具挑战性。Metro 根据操作使用混合技术:

🌐 Several bundlers are opting to write their core in Rust for performance reasons, but this comes with some trade-offs, such as more challenging contributions, patches, and development. Metro uses a mix of technologies based on the operation:

  • 核心打包器和实用程序是用 JS/Flow 编写的。
  • 文件监视是通过 Watchman 用 C++ 编写的,并提供了 JS 备用方案。然后,Watchman 会在你电脑上的各个项目中使用。
  • AST 使用 Hermes 解析器 (WebAssembly) 解析为 Babel 兼容格式。
  • AST 转换是使用 Babel 完成的。这最大化了开发者的自定义能力。
  • Minification 在原生平台上使用 Hermes,在 Web 上使用 Terser(带有可选的 ESBuild 支持)。
  • CSS 的解析和压缩是使用 LightningCSS(Rust) 执行的。

这种方法与 Meta 和社区工具保持一致,同时允许开发者更轻松地进行调试、分析和修补。

🌐 This approach aligns with Meta and community tools while allowing easier debugging, profiling, and patching for developers.