This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

异步路由

了解如何在 Expo Router 中使用异步打包来加速开发。


Expo Router 可以根据路由文件使用 React Suspense 自动拆分你的 JavaScript 包。这可以加快开发速度,因为只有你导航到的路由会被打包或加载到内存中。这对减少应用的初始包大小也非常有用。

🌐 Expo Router can automatically split your JavaScript bundle based on the route files using React Suspense. This enables faster development as only the routes you navigate to will be bundled or loaded into memory. This can also be useful for reducing the initial bundle size for your application.

使用 Hermes 引擎的应用在拆分包方面的收益不会太大,因为字节码已经提前进行内存映射。但是,这将改善你的空中更新、React 服务器组件和网络支持。

🌐 Apps using the Hermes Engine will not benefit as much from bundle splitting as the bytecode is already memory mapped ahead of time. However, it will improve your over-the-air updates, React Server Components, and web support.

工作原理

🌐 How it works

所有路由都被封装在 Suspense 边界内,并且是异步加载的。这意味着第一次导航到某个路由时,加载会稍微慢一些。不过,一旦加载完成,它将被缓存,后续访问将会是即时的。

🌐 All Routes are wrapped inside a suspense boundary and are loaded asynchronously. This means that the first time you navigate to a route, it will take a little longer to load. However, once it is loaded, it will be cached and subsequent visits will be instant.

加载错误由父路由处理,通过 ErrorBoundary 导出。

🌐 Loading errors are handled in the parent route, via the ErrorBoundary export.

在开发过程中,异步路由无法进行静态分析,因此所有文件都会被视为路由,即使它们没有导出默认组件。组件打包并加载后,任何无效的路由都会显示备用警告屏幕。

🌐 Async routes cannot be statically analyzed during development, so all files will be treated as routes even if they don't export a default component. After the component is bundled and loaded, any invalid route will use a fallback warning screen.

对于熟悉高级打包技术的人来说,异步路由功能由 React Suspense、基于路由的代码拆分 和 懒加载打包(在开发中)组成。

🌐 For those familiar with advanced bundling techniques, the async routes feature is composed of React Suspense, route-based bundle splitting and lazy bundling (in development).

设置

🌐 Setup

在 SDK 58 及更高版本中,异步路由在 Web 开发和生产环境中默认启用。原生平台默认是禁用的。在 SDK 57 及更早版本中,每个平台都需要显式选择才能使用异步路由。

🌐 In SDK 58 and later, async routes are enabled by default on web in development and production. Native platforms default to disabled. In SDK 57 and earlier, async routes require an explicit opt-in on every platform.

在你的 应用配置 的 Expo Router 配置插件中配置 asyncRoutes。要在网页上禁用异步路由,将 asyncRoutes 设置为 { "web": false }。将 asyncRoutes 设置为 false 会在所有平台上禁用该功能:

🌐 Configure asyncRoutes in the Expo Router config plugin of your app config. To disable async routes on web, set asyncRoutes to { "web": false }. Setting asyncRoutes to false disables the feature on all platforms:

app.json
{ "expo": { "plugins": [["expo-router", { "asyncRoutes": false }]] } }

你也可以使用 "development" 或 "production" 来只在该模式下启用异步路由,或者使用一个带有特定平台设置的对象(default、android、ios 或 web):

🌐 You can also use "development" or "production" to enable async routes only in that mode, or an object with platform-specific settings (default, android, ios, or web):

  • 明确的平台值优先于 default。
  • 设置 { "default": false } 会在网页上禁用异步路由,除非 web 明确启用它们。
  • 在 SDK 58 及更高版本中,仅设置本地平台会保留 Web 的默认设置。例如,{ "android": true } 的行为就像 { "android": true, "web": true }。本地生产构建仍然会同步加载路由。

例如,这个配置在两种模式下都在 web 上启用异步路由,并在 iOS 开发环境中启用,而在 Android 上则禁用它们。在 SDK 57 及更早版本中,它也可以作为显式的选择性启用方式使用:

🌐 For example, this configuration enables async routes on web in both modes and on iOS in development, while disabling them on Android. It also works as an explicit opt-in in SDK 57 and earlier:

app.json
{ "expo": { "plugins": [ [ "expo-router", { "origin": "https://acme.com", "asyncRoutes": { "web": true, "android": false, "default": "development" } } ] ] } }

更改设置后,在启动或导出项目时,用 --clear 清理 Metro 缓存:

🌐 After changing the setting, clear the Metro cache with --clear when starting or exporting your project:

Terminal
- npx expo start --clear

# Or when exporting
- npx expo export --clear
- yarn expo start --clear

# Or when exporting
- yarn expo export --clear
- pnpm expo start --clear

# Or when exporting
- pnpm expo export --clear
- bun expo start --clear

# Or when exporting
- bun expo export --clear

静态渲染

🌐 Static rendering

在生产环境的 Web 应用中,通过在 Node.js 中同步渲染所有 Suspense 边界,然后根据给定 HTML 文件的所有选定路由将所有异步代码块链接到 HTML 中,从而支持静态渲染。这确保你在服务器导航时不会遇到加载状态的瀑布效应。随后的导航将递归加载任何缺失的代码块。

🌐 Static rendering is supported in production web apps by rendering all Suspense boundaries synchronously in Node.js, then linking all of async chunks together in the HTML based on all the selected routes for a given HTML file. This ensures you don't encounter a waterfall of loading states on server navigations. Subsequent navigations will recursively load any missing chunks.

为了确保一致的首次渲染,通向 URL 的叶路由的所有布局路由都将包含在初始服务器响应中。

🌐 To ensure a consistent first render, all layout routes leading up to the leaf route for a URL will be included in the initial server response.

所有用 unstable_settings = { anchor: '...' } 定义的锚点路由都会包含在初始 HTML 文件中,因为它们是第一次渲染所必需的。比如,如果服务器请求的是一个模态框,那么模态框下渲染的屏幕也会被包含,以确保模态框能正确显示。

🌐 All anchor routes, defined with unstable_settings = { anchor: '...' } will be included in the initial HTML file as they are required for the first render. For example, if the server request is for a modal, the screen rendered under the modal will also be included to ensure the modal is rendered correctly.

注意事项

🌐 Caveats

异步路由有以下限制:

🌐 The following limitations apply to async routes:

  • 异步路由尚不支持原生生产应用。
  • 在开发过程中,运行时 JavaScript 是惰性打包的,因此你可能会遇到 HTML 与可用 JavaScript 不匹配的情况。
  • 自定义 SuspenseFallback 导出在异步路由中不起作用。在 SDK 58 及更高版本中,Web 应用会使用默认的加载回退,除非禁用了异步路由。要保留自定义回退,请在 expo-router 配置插件中设置 asyncRoutes: { web: false }。查看 迁移指南 了解应用配置示例。