diff --git a/.changeset/thin-rings-eat.md b/.changeset/thin-rings-eat.md new file mode 100644 index 00000000000..20ff354a683 --- /dev/null +++ b/.changeset/thin-rings-eat.md @@ -0,0 +1,5 @@ +--- +"@remix-run/dev": patch +--- + +Vite: reduce network calls for route modules during HMR diff --git a/packages/remix-dev/vite/plugin.ts b/packages/remix-dev/vite/plugin.ts index c3cae627821..8558b1c78f3 100644 --- a/packages/remix-dev/vite/plugin.ts +++ b/packages/remix-dev/vite/plugin.ts @@ -1471,29 +1471,28 @@ function isEqualJson(v1: unknown, v2: unknown) { } function addRefreshWrapper( - pluginConfig: ResolvedVitePluginConfig, + remixConfig: ResolvedVitePluginConfig, code: string, id: string ): string { - let isRoute = - id.endsWith(CLIENT_ROUTE_QUERY_STRING) || getRoute(pluginConfig, id); - let acceptExports = isRoute - ? [ - "clientAction", - "clientLoader", - "handle", - "meta", - "links", - "shouldRevalidate", - ] - : []; + let route = getRoute(remixConfig, id); + let acceptExports = + route || id.endsWith(CLIENT_ROUTE_QUERY_STRING) + ? [ + "clientAction", + "clientLoader", + "handle", + "meta", + "links", + "shouldRevalidate", + ] + : []; return ( - REACT_REFRESH_HEADER.replace("__SOURCE__", JSON.stringify(id)) + + REACT_REFRESH_HEADER.replaceAll("__SOURCE__", JSON.stringify(id)) + code + - REACT_REFRESH_FOOTER.replace("__SOURCE__", JSON.stringify(id)).replace( - "__ACCEPT_EXPORTS__", - JSON.stringify(acceptExports) - ) + REACT_REFRESH_FOOTER.replaceAll("__SOURCE__", JSON.stringify(id)) + .replaceAll("__ACCEPT_EXPORTS__", JSON.stringify(acceptExports)) + .replaceAll("__ROUTE_ID__", JSON.stringify(route?.id)) ); } @@ -1527,6 +1526,7 @@ if (import.meta.hot && !inWebWorker && window.__remixLiveReloadEnabled) { RefreshRuntime.registerExportsForReactRefresh(__SOURCE__, currentExports); import.meta.hot.accept((nextExports) => { if (!nextExports) return; + __ROUTE_ID__ && window.__remixRouteModuleUpdates.set(__ROUTE_ID__, nextExports); const invalidateMessage = RefreshRuntime.validateRefreshBoundaryAndEnqueueUpdate(currentExports, nextExports, __ACCEPT_EXPORTS__); if (invalidateMessage) import.meta.hot.invalidate(invalidateMessage); }); diff --git a/packages/remix-dev/vite/static/refresh-utils.cjs b/packages/remix-dev/vite/static/refresh-utils.cjs index e7745e04b12..a2891438a0c 100644 --- a/packages/remix-dev/vite/static/refresh-utils.cjs +++ b/packages/remix-dev/vite/static/refresh-utils.cjs @@ -17,8 +17,10 @@ const enqueueUpdate = debounce(async () => { for (let route of routeUpdates.values()) { manifest.routes[route.id] = route; - - let imported = await __hmr_import(route.url + "?t=" + Date.now()); + let imported = window.__remixRouteModuleUpdates.get(route.id); + if (!imported) { + throw Error(`[remix:hmr] No module update found for route ${route.id}`); + } let routeModule = { ...imported, // react-refresh takes care of updating these in-place, @@ -53,6 +55,7 @@ const enqueueUpdate = debounce(async () => { ); __remixRouter._internalSetRoutes(routes); routeUpdates.clear(); + window.__remixRouteModuleUpdates.clear(); } await revalidate(); @@ -138,6 +141,7 @@ function __hmr_import(module) { } const routeUpdates = new Map(); +window.__remixRouteModuleUpdates = new Map(); async function revalidate() { let { promise, resolve } = channel();