¥Lazy Route Discovery (a.k.a. "Fog of War")
Remix 在 v2.10.0
的 future.unstable_lazyRouteDiscovery
和 未来标志 之后引入了对延迟路由发现(又名 "战争迷雾")(RFC)的支持(后来在 v2.13.0
中稳定为 future.v3_lazyRouteDiscovery
)。这允许你选择启用此行为,这将成为 Remix 下一个主要版本(又名 React Router v7(1、2))的默认行为。有关此功能的更多信息,请查看 博客文章。
¥Remix introduced support for Lazy Route Discovery (a.k.a. "Fog of War") (RFC) behind the future.unstable_lazyRouteDiscovery
Future Flag in v2.10.0
(later stabilized as future.v3_lazyRouteDiscovery
in v2.13.0
). This allows you to opt-into this behavior, which will become the default in the next major version of Remix — a.k.a. React Router v7 (1, 2). For more information on this feature, please check out the blog post.
¥Current Behavior
目前,Remix 在初始加载(即 /assets/manifest-[hash].js
)时会将完整的路由清单加载到 JS 文件中。清单文件不包含路由模块的实现,而是包含它们的 URL 路径和元信息(路由 JS/CSS 导入、服务器上是否有 loader
/action
等)。预先提供完整的清单文件,Remix 可以在链接点击时进行同步客户端路由匹配,并立即启动路由模块和数据的加载。对于中小型应用,预先加载完整清单通常不会造成限制,因为它具有高度可缓存性和良好的 gzip 压缩性能。然而,我们发现,在规模化的情况下,此清单可能会变得足够大,从而影响某些性能指标。
¥Currently, Remix loads the complete route manifest in a JS file on initial load (i.e., /assets/manifest-[hash].js
). The manifest does not contain the route module implementations but rather their URL paths and meta information (route JS/CSS imports, whether they have a loader
/action
on the server, etc.). Having this full manifest up-front allows Remix to do synchronous client-side route matching on Link clicks and kick off the loads for route modules and data immediately. For small-to-medium-sized apps, loading the full manifest up-front is usually not prohibitive as it is highly cacheable and gzips down quite well. However, at scale we found that this manifest could grow large enough to impact some performance metrics.
¥New Behavior
启用 "战争迷雾" 后,Remix 将不再在初始加载时发送完整的路由清单。相反,你的 SSR 渲染将仅包含初始清单中的 SSR 路由,并且当用户在应用中导航时,将加载其他路由。随着时间的推移,清单会逐渐增长,包含用户导航到的应用部分。
¥When you enable "Fog of War", Remix will no longer send a full route manifest on initial load. Instead, your SSR render will only include the SSR routes in the initial manifest, and additional routes will be loaded as the user navigates around the application. Over time, the manifest grows to include the portions of the app the user navigated to.
请注意,这并非从终端用户处获取任何应用 URL 的 "hide" 方式。它最初不会在清单文件中包含所有资源。然而,用于在用户导航时获取新路由的清单端点仍然可以公开所有已定义的应用路由 - 尽管它只是稍微模糊了一些。
¥Please note that this is not a way to "hide" any of your application URLs from end-users. It doesn't ship them all in the manifest initially. However, the manifest endpoint used to fetch new routes as the user navigates around will still be able to expose all of your defined application routes — albeit it's just a bit more obscured.
¥Eager Route Discovery
与往常一样,这种惰性路由发现需要权衡利弊。它缩短了应用的初始加载时间,但 Remix 无法再对链接点击执行同步路由匹配,这可能会导致瀑布流。
¥As always, there is a tradeoff with this type of lazy-route discovery. It improves initial application load times — but Remix can no longer perform synchronous route matching on link clicks, which can lead to waterfalls.
在当前架构下(不使用 <Link prefetch>
),点击链接将如下所示:
¥In the current architecture (without using <Link prefetch>
), clicking a link would look something like this:
click /a
|-- load route module -->
|-- load route data -->
| render /a
在“战争迷雾”架构中,点击链接可能会引发瀑布流:
¥In the Fog of War architecture, clicking a link can introduce a waterfall:
click /a
|-- discover route -->
|-- load route module -->
|-- load route data -->
| render /a
Remix 讨厌瀑布效果,因此“战争迷雾”功能实现了优化,在大多数情况下可以避免瀑布效果。默认情况下,页面上渲染的所有 <Link>
和 <NavLink>
组件都将批量处理,并通过向服务器发送请求立即渲染 "discovered"。此请求将匹配服务器上所有当前链接路径,并返回所有必需的路由清单条目。在大多数情况下,此请求应在用户点击任何链接之前完成(因为用户通常不会在最初的几百毫秒内点击链接),并且清单将在点击任何链接之前进行修补。然后,当点击链接时,Remix 能够进行同步客户端匹配,就像战争迷雾行为不存在一样。
¥Remix hates waterfalls, so the Fog of War feature implements an optimization to avoid them in the majority of cases. By default, all <Link>
and <NavLink>
components rendered on the page will be batched up and eagerly "discovered" via a request to the server. This request will match all current link paths on the server and send back all required route manifest entries. In the majority of cases, this request should complete before the user clicks any links (since users don't usually click links in the first few hundred milliseconds), and the manifest will be patched before any links are clicked. Then, when a link is clicked, Remix is able to do synchronous client-side matching as if the Fog of War behavior wasn't even present.
如果你希望退出此基于每个链接的即时路由发现,你可以通过 discover="none"
属性来实现(默认值为 discover="render"
)。
¥If you wish to opt out of this eager route discovery on a per-link basis, you can do that via the discover="none"
prop (the default value is discover="render"
).
¥Notable Changes
启用此功能后,window.__remixManifest.routes
中的路由清单将仅包含初始 SSR 所需的最少路由,并且路由将在用户导航时动态添加到其中。
¥When this feature is enabled, the route manifest in window.__remixManifest.routes
will only contain the minimal required routes on initial SSR, and routes will be added to it dynamically as the user navigates around
Remix 处理程序现在有一个新的内部 /__manifest
端点,它将通过该端点获取清单补丁。
¥The Remix handler now has a new internal /__manifest
endpoint through which it will fetch manifest patches
你需要确保你的部署架构将所有 /__manifest
请求路由到 Remix 处理程序。
¥You will need to ensure that your deployment architecture routes any /__manifest
requests through to the Remix handler
如果你已部署任何 CDN/边缘缓存层,/__manifest
路由会接受 2 个查询字符串参数,你可能需要将它们包含在缓存键中:version
和 p
¥If you have any CDN/Edge caching layers in place, the /__manifest
route accepts 2 query string params you may need to include in your cache key: version
and p
⚠️ 这被视为内部实现细节,不应由应用代码请求。
¥⚠️ This is considered an internal implementation detail and is not intended to be requested by application code