react-router 7.1.5 → 7.2.0-pre.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -1
- package/dist/development/{chunk-IR6S3I6Y.mjs → chunk-HLU4BUUT.mjs} +244 -78
- package/dist/development/dom-export.d.mts +2 -2
- package/dist/development/dom-export.d.ts +2 -2
- package/dist/development/dom-export.js +222 -58
- package/dist/development/dom-export.mjs +12 -4
- package/dist/{production/fog-of-war-CCAcUMgB.d.ts → development/fog-of-war-Ax4Jg2xL.d.ts} +9 -5
- package/dist/development/{fog-of-war-D6dP9JIt.d.mts → fog-of-war-Cyo_TZuh.d.mts} +9 -5
- package/dist/development/index.d.mts +10 -5
- package/dist/development/index.d.ts +10 -5
- package/dist/development/index.js +244 -78
- package/dist/development/index.mjs +2 -2
- package/dist/development/lib/types/route-module.d.mts +3 -1
- package/dist/development/lib/types/route-module.d.ts +3 -1
- package/dist/development/lib/types/route-module.js +1 -1
- package/dist/development/lib/types/route-module.mjs +1 -1
- package/dist/development/{route-data-Cq_b5feC.d.ts → route-data-DQbTMaUY.d.mts} +1 -0
- package/dist/{production/route-data-Cq_b5feC.d.mts → development/route-data-DQbTMaUY.d.ts} +1 -0
- package/dist/production/{chunk-JRAGQQ3X.mjs → chunk-IA3JXIZE.mjs} +244 -78
- package/dist/production/dom-export.d.mts +2 -2
- package/dist/production/dom-export.d.ts +2 -2
- package/dist/production/dom-export.js +222 -58
- package/dist/production/dom-export.mjs +12 -4
- package/dist/{development/fog-of-war-CCAcUMgB.d.ts → production/fog-of-war-Ax4Jg2xL.d.ts} +9 -5
- package/dist/production/{fog-of-war-D6dP9JIt.d.mts → fog-of-war-Cyo_TZuh.d.mts} +9 -5
- package/dist/production/index.d.mts +10 -5
- package/dist/production/index.d.ts +10 -5
- package/dist/production/index.js +244 -78
- package/dist/production/index.mjs +2 -2
- package/dist/production/lib/types/route-module.d.mts +3 -1
- package/dist/production/lib/types/route-module.d.ts +3 -1
- package/dist/production/lib/types/route-module.js +1 -1
- package/dist/production/lib/types/route-module.mjs +1 -1
- package/dist/production/{route-data-Cq_b5feC.d.ts → route-data-DQbTMaUY.d.mts} +1 -0
- package/dist/{development/route-data-Cq_b5feC.d.mts → production/route-data-DQbTMaUY.d.ts} +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# `react-router`
|
|
2
2
|
|
|
3
|
+
## 7.2.0-pre.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Don't apply Single Fetch revalidation de-optimization when in SPA mode since there is no server HTTP request ([#12948](https://github.com/remix-run/react-router/pull/12948))
|
|
8
|
+
- Add unstable support for splitting route modules in framework mode via `future.unstable_splitRouteModules` ([#11871](https://github.com/remix-run/react-router/pull/11871))
|
|
9
|
+
- Align dev server behavior with static file server behavior when `ssr:false` is set ([#12948](https://github.com/remix-run/react-router/pull/12948))
|
|
10
|
+
|
|
11
|
+
- When no `prerender` config exists, only SSR down to the root `HydrateFallback` (SPA Mode)
|
|
12
|
+
- When a `prerender` config exists but the current path is not prerendered, only SSR down to the root `HydrateFallback` (SPA Fallback)
|
|
13
|
+
- Return a 404 on `.data` requests to non-pre-rendered paths
|
|
14
|
+
|
|
15
|
+
- Improve prefetch performance of CSS side effects in framework mode ([#12889](https://github.com/remix-run/react-router/pull/12889))
|
|
16
|
+
- Disable Lazy Route Discovery for all `ssr:false` apps and not just "SPA Mode" because there is no runtime server to serve the search-param-configured `__manifest` requests ([#12894](https://github.com/remix-run/react-router/pull/12894))
|
|
17
|
+
|
|
18
|
+
- We previously only disabled this for "SPA Mode" which is `ssr:false` and no `prerender` config but we realized it should apply to all `ssr:false` apps, including those prerendering multiple pages
|
|
19
|
+
- In those `prerender` scenarios we would prerender the `/__manifest` file assuming the static file server would serve it but that makes some unneccesary assumptions about the static file server behaviors
|
|
20
|
+
|
|
21
|
+
- Properly handle interrupted manifest requests in lazy route discovery ([#12915](https://github.com/remix-run/react-router/pull/12915))
|
|
22
|
+
|
|
3
23
|
## 7.1.5
|
|
4
24
|
|
|
5
25
|
### Patch Changes
|
|
@@ -83,7 +103,7 @@ _No changes_
|
|
|
83
103
|
- Collapse `@remix-run/server-runtime` into `react-router`
|
|
84
104
|
- Collapse `@remix-run/testing` into `react-router`
|
|
85
105
|
|
|
86
|
-
- Remove
|
|
106
|
+
- Remove single_fetch future flag. ([#11522](https://github.com/remix-run/react-router/pull/11522))
|
|
87
107
|
|
|
88
108
|
- Drop support for Node 16, React Router SSR now requires Node 18 or higher ([#11391](https://github.com/remix-run/react-router/pull/11391))
|
|
89
109
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* react-router v7.
|
|
2
|
+
* react-router v7.2.0-pre.0
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -2459,6 +2459,7 @@ function createRouter(init) {
|
|
|
2459
2459
|
let localManifest = manifest;
|
|
2460
2460
|
try {
|
|
2461
2461
|
await patchRoutesOnNavigationImpl({
|
|
2462
|
+
signal,
|
|
2462
2463
|
path: pathname,
|
|
2463
2464
|
matches: partialMatches,
|
|
2464
2465
|
patch: (routeId, children) => {
|
|
@@ -5359,14 +5360,23 @@ function getKeyedLinksForMatches(matches, routeModules, manifest) {
|
|
|
5359
5360
|
module?.links?.() || []
|
|
5360
5361
|
];
|
|
5361
5362
|
}).flat(2);
|
|
5362
|
-
let preloads =
|
|
5363
|
+
let preloads = getModuleLinkHrefs(matches, manifest);
|
|
5363
5364
|
return dedupeLinkDescriptors(descriptors, preloads);
|
|
5364
5365
|
}
|
|
5366
|
+
function getRouteCssDescriptors(route) {
|
|
5367
|
+
if (!route.css) return [];
|
|
5368
|
+
return route.css.map((href) => ({ rel: "stylesheet", href }));
|
|
5369
|
+
}
|
|
5370
|
+
async function prefetchRouteCss(route) {
|
|
5371
|
+
if (!route.css) return;
|
|
5372
|
+
let descriptors = getRouteCssDescriptors(route);
|
|
5373
|
+
await Promise.all(descriptors.map(prefetchStyleLink));
|
|
5374
|
+
}
|
|
5365
5375
|
async function prefetchStyleLinks(route, routeModule) {
|
|
5366
5376
|
if (!route.css && !routeModule.links || !isPreloadSupported()) return;
|
|
5367
5377
|
let descriptors = [];
|
|
5368
5378
|
if (route.css) {
|
|
5369
|
-
descriptors.push(...route
|
|
5379
|
+
descriptors.push(...getRouteCssDescriptors(route));
|
|
5370
5380
|
}
|
|
5371
5381
|
if (routeModule.links) {
|
|
5372
5382
|
descriptors.push(...routeModule.links());
|
|
@@ -5382,13 +5392,15 @@ async function prefetchStyleLinks(route, routeModule) {
|
|
|
5382
5392
|
});
|
|
5383
5393
|
}
|
|
5384
5394
|
}
|
|
5385
|
-
|
|
5386
|
-
(link) => (!link.media || window.matchMedia(link.media).matches) && !document.querySelector(`link[rel="stylesheet"][href="${link.href}"]`)
|
|
5387
|
-
);
|
|
5388
|
-
await Promise.all(matchingLinks.map(prefetchStyleLink));
|
|
5395
|
+
await Promise.all(styleLinks.map(prefetchStyleLink));
|
|
5389
5396
|
}
|
|
5390
5397
|
async function prefetchStyleLink(descriptor) {
|
|
5391
5398
|
return new Promise((resolve) => {
|
|
5399
|
+
if (descriptor.media && !window.matchMedia(descriptor.media).matches || document.querySelector(
|
|
5400
|
+
`link[rel="stylesheet"][href="${descriptor.href}"]`
|
|
5401
|
+
)) {
|
|
5402
|
+
return resolve();
|
|
5403
|
+
}
|
|
5392
5404
|
let link = document.createElement("link");
|
|
5393
5405
|
Object.assign(link, descriptor);
|
|
5394
5406
|
function removeLink() {
|
|
@@ -5483,25 +5495,21 @@ function getNewMatchesForLinks(page, nextMatches, currentMatches, manifest, loca
|
|
|
5483
5495
|
}
|
|
5484
5496
|
return [];
|
|
5485
5497
|
}
|
|
5486
|
-
function getModuleLinkHrefs(matches,
|
|
5487
|
-
return dedupeHrefs(
|
|
5488
|
-
matches.map((match) => {
|
|
5489
|
-
let route = manifestPatch.routes[match.route.id];
|
|
5490
|
-
if (!route) return [];
|
|
5491
|
-
let hrefs = [route.module];
|
|
5492
|
-
if (route.imports) {
|
|
5493
|
-
hrefs = hrefs.concat(route.imports);
|
|
5494
|
-
}
|
|
5495
|
-
return hrefs;
|
|
5496
|
-
}).flat(1)
|
|
5497
|
-
);
|
|
5498
|
-
}
|
|
5499
|
-
function getCurrentPageModulePreloadHrefs(matches, manifest) {
|
|
5498
|
+
function getModuleLinkHrefs(matches, manifest, { includeHydrateFallback } = {}) {
|
|
5500
5499
|
return dedupeHrefs(
|
|
5501
5500
|
matches.map((match) => {
|
|
5502
5501
|
let route = manifest.routes[match.route.id];
|
|
5503
5502
|
if (!route) return [];
|
|
5504
5503
|
let hrefs = [route.module];
|
|
5504
|
+
if (route.clientActionModule) {
|
|
5505
|
+
hrefs = hrefs.concat(route.clientActionModule);
|
|
5506
|
+
}
|
|
5507
|
+
if (route.clientLoaderModule) {
|
|
5508
|
+
hrefs = hrefs.concat(route.clientLoaderModule);
|
|
5509
|
+
}
|
|
5510
|
+
if (includeHydrateFallback && route.hydrateFallbackModule) {
|
|
5511
|
+
hrefs = hrefs.concat(route.hydrateFallbackModule);
|
|
5512
|
+
}
|
|
5505
5513
|
if (route.imports) {
|
|
5506
5514
|
hrefs = hrefs.concat(route.imports);
|
|
5507
5515
|
}
|
|
@@ -5656,17 +5664,31 @@ function StreamTransfer({
|
|
|
5656
5664
|
)));
|
|
5657
5665
|
}
|
|
5658
5666
|
}
|
|
5659
|
-
function getSingleFetchDataStrategy(manifest, routeModules, getRouter) {
|
|
5667
|
+
function getSingleFetchDataStrategy(manifest, routeModules, ssr, getRouter) {
|
|
5660
5668
|
return async ({ request, matches, fetcherKey }) => {
|
|
5661
5669
|
if (request.method !== "GET") {
|
|
5662
5670
|
return singleFetchActionStrategy(request, matches);
|
|
5663
5671
|
}
|
|
5672
|
+
if (!ssr) {
|
|
5673
|
+
let foundLoaderBelowRoot = matches.some(
|
|
5674
|
+
(m) => m.route.id !== "root" && manifest.routes[m.route.id]?.hasLoader
|
|
5675
|
+
);
|
|
5676
|
+
if (!foundLoaderBelowRoot) {
|
|
5677
|
+
let matchesToLoad = matches.filter((m) => m.shouldLoad);
|
|
5678
|
+
let results = await Promise.all(matchesToLoad.map((m) => m.resolve()));
|
|
5679
|
+
return results.reduce(
|
|
5680
|
+
(acc, result, i) => Object.assign(acc, { [matchesToLoad[i].route.id]: result }),
|
|
5681
|
+
{}
|
|
5682
|
+
);
|
|
5683
|
+
}
|
|
5684
|
+
}
|
|
5664
5685
|
if (fetcherKey) {
|
|
5665
5686
|
return singleFetchLoaderFetcherStrategy(request, matches);
|
|
5666
5687
|
}
|
|
5667
5688
|
return singleFetchLoaderNavigationStrategy(
|
|
5668
5689
|
manifest,
|
|
5669
5690
|
routeModules,
|
|
5691
|
+
ssr,
|
|
5670
5692
|
getRouter(),
|
|
5671
5693
|
request,
|
|
5672
5694
|
matches
|
|
@@ -5700,7 +5722,7 @@ async function singleFetchActionStrategy(request, matches) {
|
|
|
5700
5722
|
}
|
|
5701
5723
|
};
|
|
5702
5724
|
}
|
|
5703
|
-
async function singleFetchLoaderNavigationStrategy(manifest, routeModules, router, request, matches) {
|
|
5725
|
+
async function singleFetchLoaderNavigationStrategy(manifest, routeModules, ssr, router, request, matches) {
|
|
5704
5726
|
let routesParams = /* @__PURE__ */ new Set();
|
|
5705
5727
|
let foundOptOutRoute = false;
|
|
5706
5728
|
let routeDfds = matches.map(() => createDeferred2());
|
|
@@ -5766,7 +5788,7 @@ async function singleFetchLoaderNavigationStrategy(manifest, routeModules, route
|
|
|
5766
5788
|
singleFetchDfd.resolve({});
|
|
5767
5789
|
} else {
|
|
5768
5790
|
try {
|
|
5769
|
-
if (foundOptOutRoute && routesParams.size > 0) {
|
|
5791
|
+
if (ssr && foundOptOutRoute && routesParams.size > 0) {
|
|
5770
5792
|
url.searchParams.set(
|
|
5771
5793
|
"_routes",
|
|
5772
5794
|
matches.filter((m) => routesParams.has(m.route.id)).map((m) => m.route.id).join(",")
|
|
@@ -6134,11 +6156,12 @@ function createServerRoutes(manifest, routeModules, future, isSpaMode, parentId
|
|
|
6134
6156
|
return dataRoute;
|
|
6135
6157
|
});
|
|
6136
6158
|
}
|
|
6137
|
-
function createClientRoutesWithHMRRevalidationOptOut(needsRevalidation, manifest, routeModulesCache, initialState,
|
|
6159
|
+
function createClientRoutesWithHMRRevalidationOptOut(needsRevalidation, manifest, routeModulesCache, initialState, ssr, isSpaMode) {
|
|
6138
6160
|
return createClientRoutes(
|
|
6139
6161
|
manifest,
|
|
6140
6162
|
routeModulesCache,
|
|
6141
6163
|
initialState,
|
|
6164
|
+
ssr,
|
|
6142
6165
|
isSpaMode,
|
|
6143
6166
|
"",
|
|
6144
6167
|
groupRoutesByParentId(manifest),
|
|
@@ -6147,14 +6170,14 @@ function createClientRoutesWithHMRRevalidationOptOut(needsRevalidation, manifest
|
|
|
6147
6170
|
}
|
|
6148
6171
|
function preventInvalidServerHandlerCall(type, route, isSpaMode) {
|
|
6149
6172
|
if (isSpaMode) {
|
|
6150
|
-
let
|
|
6151
|
-
let
|
|
6152
|
-
console.error(
|
|
6153
|
-
throw new ErrorResponseImpl(400, "Bad Request", new Error(
|
|
6173
|
+
let fn = type === "action" ? "serverAction()" : "serverLoader()";
|
|
6174
|
+
let msg = `You cannot call ${fn} in SPA Mode (routeId: "${route.id}")`;
|
|
6175
|
+
console.error(msg);
|
|
6176
|
+
throw new ErrorResponseImpl(400, "Bad Request", new Error(msg), true);
|
|
6154
6177
|
}
|
|
6155
|
-
let fn = type === "action" ? "serverAction()" : "serverLoader()";
|
|
6156
|
-
let msg = `You are trying to call ${fn} on a route that does not have a server ${type} (routeId: "${route.id}")`;
|
|
6157
6178
|
if (type === "loader" && !route.hasLoader || type === "action" && !route.hasAction) {
|
|
6179
|
+
let fn = type === "action" ? "serverAction()" : "serverLoader()";
|
|
6180
|
+
let msg = `You are trying to call ${fn} on a route that does not have a server ${type} (routeId: "${route.id}")`;
|
|
6158
6181
|
console.error(msg);
|
|
6159
6182
|
throw new ErrorResponseImpl(400, "Bad Request", new Error(msg), true);
|
|
6160
6183
|
}
|
|
@@ -6165,7 +6188,7 @@ function noActionDefinedError(type, routeId) {
|
|
|
6165
6188
|
console.error(msg);
|
|
6166
6189
|
throw new ErrorResponseImpl(405, "Method Not Allowed", new Error(msg), true);
|
|
6167
6190
|
}
|
|
6168
|
-
function createClientRoutes(manifest, routeModulesCache, initialState, isSpaMode, parentId = "", routesByParentId = groupRoutesByParentId(manifest), needsRevalidation) {
|
|
6191
|
+
function createClientRoutes(manifest, routeModulesCache, initialState, ssr, isSpaMode, parentId = "", routesByParentId = groupRoutesByParentId(manifest), needsRevalidation) {
|
|
6169
6192
|
return (routesByParentId[parentId] || []).map((route) => {
|
|
6170
6193
|
let routeModule = routeModulesCache[route.id];
|
|
6171
6194
|
function fetchServerHandler(singleFetch) {
|
|
@@ -6185,6 +6208,21 @@ function createClientRoutes(manifest, routeModulesCache, initialState, isSpaMode
|
|
|
6185
6208
|
}
|
|
6186
6209
|
return fetchServerHandler(singleFetch);
|
|
6187
6210
|
}
|
|
6211
|
+
function prefetchModule(modulePath) {
|
|
6212
|
+
import(
|
|
6213
|
+
/* @vite-ignore */
|
|
6214
|
+
/* webpackIgnore: true */
|
|
6215
|
+
modulePath
|
|
6216
|
+
);
|
|
6217
|
+
}
|
|
6218
|
+
function prefetchRouteModuleChunks(route2) {
|
|
6219
|
+
if (route2.clientActionModule) {
|
|
6220
|
+
prefetchModule(route2.clientActionModule);
|
|
6221
|
+
}
|
|
6222
|
+
if (route2.clientLoaderModule) {
|
|
6223
|
+
prefetchModule(route2.clientLoaderModule);
|
|
6224
|
+
}
|
|
6225
|
+
}
|
|
6188
6226
|
async function prefetchStylesAndCallHandler(handler) {
|
|
6189
6227
|
let cachedModule = routeModulesCache[route.id];
|
|
6190
6228
|
let linkPrefetchPromise = cachedModule ? prefetchStyleLinks(route, cachedModule) : Promise.resolve();
|
|
@@ -6206,7 +6244,8 @@ function createClientRoutes(manifest, routeModulesCache, initialState, isSpaMode
|
|
|
6206
6244
|
handle: routeModule.handle,
|
|
6207
6245
|
shouldRevalidate: getShouldRevalidateFunction(
|
|
6208
6246
|
routeModule,
|
|
6209
|
-
route
|
|
6247
|
+
route,
|
|
6248
|
+
ssr,
|
|
6210
6249
|
needsRevalidation
|
|
6211
6250
|
)
|
|
6212
6251
|
});
|
|
@@ -6223,7 +6262,6 @@ function createClientRoutes(manifest, routeModulesCache, initialState, isSpaMode
|
|
|
6223
6262
|
"No `routeModule` available for critical-route loader"
|
|
6224
6263
|
);
|
|
6225
6264
|
if (!routeModule.clientLoader) {
|
|
6226
|
-
if (isSpaMode) return null;
|
|
6227
6265
|
return fetchServerLoader(singleFetch);
|
|
6228
6266
|
}
|
|
6229
6267
|
return routeModule.clientLoader({
|
|
@@ -6278,9 +6316,24 @@ function createClientRoutes(manifest, routeModulesCache, initialState, isSpaMode
|
|
|
6278
6316
|
} else {
|
|
6279
6317
|
if (!route.hasClientLoader) {
|
|
6280
6318
|
dataRoute.loader = ({ request }, singleFetch) => prefetchStylesAndCallHandler(() => {
|
|
6281
|
-
if (isSpaMode) return Promise.resolve(null);
|
|
6282
6319
|
return fetchServerLoader(singleFetch);
|
|
6283
6320
|
});
|
|
6321
|
+
} else if (route.clientLoaderModule) {
|
|
6322
|
+
dataRoute.loader = async (args, singleFetch) => {
|
|
6323
|
+
invariant2(route.clientLoaderModule);
|
|
6324
|
+
let { clientLoader } = await import(
|
|
6325
|
+
/* @vite-ignore */
|
|
6326
|
+
/* webpackIgnore: true */
|
|
6327
|
+
route.clientLoaderModule
|
|
6328
|
+
);
|
|
6329
|
+
return clientLoader({
|
|
6330
|
+
...args,
|
|
6331
|
+
async serverLoader() {
|
|
6332
|
+
preventInvalidServerHandlerCall("loader", route, isSpaMode);
|
|
6333
|
+
return fetchServerLoader(singleFetch);
|
|
6334
|
+
}
|
|
6335
|
+
});
|
|
6336
|
+
};
|
|
6284
6337
|
}
|
|
6285
6338
|
if (!route.hasClientAction) {
|
|
6286
6339
|
dataRoute.action = ({ request }, singleFetch) => prefetchStylesAndCallHandler(() => {
|
|
@@ -6289,12 +6342,34 @@ function createClientRoutes(manifest, routeModulesCache, initialState, isSpaMode
|
|
|
6289
6342
|
}
|
|
6290
6343
|
return fetchServerAction(singleFetch);
|
|
6291
6344
|
});
|
|
6345
|
+
} else if (route.clientActionModule) {
|
|
6346
|
+
dataRoute.action = async (args, singleFetch) => {
|
|
6347
|
+
invariant2(route.clientActionModule);
|
|
6348
|
+
prefetchRouteModuleChunks(route);
|
|
6349
|
+
let { clientAction } = await import(
|
|
6350
|
+
/* @vite-ignore */
|
|
6351
|
+
/* webpackIgnore: true */
|
|
6352
|
+
route.clientActionModule
|
|
6353
|
+
);
|
|
6354
|
+
return clientAction({
|
|
6355
|
+
...args,
|
|
6356
|
+
async serverAction() {
|
|
6357
|
+
preventInvalidServerHandlerCall("action", route, isSpaMode);
|
|
6358
|
+
return fetchServerAction(singleFetch);
|
|
6359
|
+
}
|
|
6360
|
+
});
|
|
6361
|
+
};
|
|
6292
6362
|
}
|
|
6293
6363
|
dataRoute.lazy = async () => {
|
|
6294
|
-
|
|
6364
|
+
if (route.clientLoaderModule || route.clientActionModule) {
|
|
6365
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
6366
|
+
}
|
|
6367
|
+
let modPromise = loadRouteModuleWithBlockingLinks(
|
|
6295
6368
|
route,
|
|
6296
6369
|
routeModulesCache
|
|
6297
6370
|
);
|
|
6371
|
+
prefetchRouteModuleChunks(route);
|
|
6372
|
+
let mod = await modPromise;
|
|
6298
6373
|
let lazyRoute = { ...mod };
|
|
6299
6374
|
if (mod.clientLoader) {
|
|
6300
6375
|
let clientLoader = mod.clientLoader;
|
|
@@ -6322,7 +6397,8 @@ function createClientRoutes(manifest, routeModulesCache, initialState, isSpaMode
|
|
|
6322
6397
|
hasErrorBoundary: lazyRoute.hasErrorBoundary,
|
|
6323
6398
|
shouldRevalidate: getShouldRevalidateFunction(
|
|
6324
6399
|
lazyRoute,
|
|
6325
|
-
route
|
|
6400
|
+
route,
|
|
6401
|
+
ssr,
|
|
6326
6402
|
needsRevalidation
|
|
6327
6403
|
),
|
|
6328
6404
|
handle: lazyRoute.handle,
|
|
@@ -6337,6 +6413,7 @@ function createClientRoutes(manifest, routeModulesCache, initialState, isSpaMode
|
|
|
6337
6413
|
manifest,
|
|
6338
6414
|
routeModulesCache,
|
|
6339
6415
|
initialState,
|
|
6416
|
+
ssr,
|
|
6340
6417
|
isSpaMode,
|
|
6341
6418
|
route.id,
|
|
6342
6419
|
routesByParentId,
|
|
@@ -6346,15 +6423,18 @@ function createClientRoutes(manifest, routeModulesCache, initialState, isSpaMode
|
|
|
6346
6423
|
return dataRoute;
|
|
6347
6424
|
});
|
|
6348
6425
|
}
|
|
6349
|
-
function getShouldRevalidateFunction(route,
|
|
6426
|
+
function getShouldRevalidateFunction(route, manifestRoute, ssr, needsRevalidation) {
|
|
6350
6427
|
if (needsRevalidation) {
|
|
6351
6428
|
return wrapShouldRevalidateForHdr(
|
|
6352
|
-
|
|
6429
|
+
manifestRoute.id,
|
|
6353
6430
|
route.shouldRevalidate,
|
|
6354
6431
|
needsRevalidation
|
|
6355
6432
|
);
|
|
6356
6433
|
}
|
|
6357
|
-
if (
|
|
6434
|
+
if (!ssr && manifestRoute.id === "root" && manifestRoute.hasLoader && !manifestRoute.hasClientLoader) {
|
|
6435
|
+
return () => false;
|
|
6436
|
+
}
|
|
6437
|
+
if (ssr && route.shouldRevalidate) {
|
|
6358
6438
|
let fn = route.shouldRevalidate;
|
|
6359
6439
|
return (opts) => fn({ ...opts, defaultShouldRevalidate: true });
|
|
6360
6440
|
}
|
|
@@ -6371,8 +6451,13 @@ function wrapShouldRevalidateForHdr(routeId, routeShouldRevalidate, needsRevalid
|
|
|
6371
6451
|
};
|
|
6372
6452
|
}
|
|
6373
6453
|
async function loadRouteModuleWithBlockingLinks(route, routeModules) {
|
|
6374
|
-
let
|
|
6375
|
-
|
|
6454
|
+
let routeModulePromise = loadRouteModule(route, routeModules);
|
|
6455
|
+
let prefetchRouteCssPromise = prefetchRouteCss(route);
|
|
6456
|
+
let routeModule = await routeModulePromise;
|
|
6457
|
+
await Promise.all([
|
|
6458
|
+
prefetchRouteCssPromise,
|
|
6459
|
+
prefetchStyleLinks(route, routeModule)
|
|
6460
|
+
]);
|
|
6376
6461
|
return {
|
|
6377
6462
|
Component: getRouteModuleComponent(routeModule),
|
|
6378
6463
|
ErrorBoundary: routeModule.ErrorBoundary,
|
|
@@ -6400,8 +6485,8 @@ var nextPaths = /* @__PURE__ */ new Set();
|
|
|
6400
6485
|
var discoveredPathsMaxSize = 1e3;
|
|
6401
6486
|
var discoveredPaths = /* @__PURE__ */ new Set();
|
|
6402
6487
|
var URL_LIMIT = 7680;
|
|
6403
|
-
function isFogOfWarEnabled(
|
|
6404
|
-
return
|
|
6488
|
+
function isFogOfWarEnabled(ssr) {
|
|
6489
|
+
return ssr === true;
|
|
6405
6490
|
}
|
|
6406
6491
|
function getPartialManifest(manifest, router) {
|
|
6407
6492
|
let routeIds = new Set(router.state.matches.map((m) => m.route.id));
|
|
@@ -6427,11 +6512,11 @@ function getPartialManifest(manifest, router) {
|
|
|
6427
6512
|
routes: initialRoutes
|
|
6428
6513
|
};
|
|
6429
6514
|
}
|
|
6430
|
-
function getPatchRoutesOnNavigationFunction(manifest, routeModules, isSpaMode, basename) {
|
|
6431
|
-
if (!isFogOfWarEnabled(
|
|
6515
|
+
function getPatchRoutesOnNavigationFunction(manifest, routeModules, ssr, isSpaMode, basename) {
|
|
6516
|
+
if (!isFogOfWarEnabled(ssr)) {
|
|
6432
6517
|
return void 0;
|
|
6433
6518
|
}
|
|
6434
|
-
return async ({ path, patch }) => {
|
|
6519
|
+
return async ({ path, patch, signal }) => {
|
|
6435
6520
|
if (discoveredPaths.has(path)) {
|
|
6436
6521
|
return;
|
|
6437
6522
|
}
|
|
@@ -6439,15 +6524,17 @@ function getPatchRoutesOnNavigationFunction(manifest, routeModules, isSpaMode, b
|
|
|
6439
6524
|
[path],
|
|
6440
6525
|
manifest,
|
|
6441
6526
|
routeModules,
|
|
6527
|
+
ssr,
|
|
6442
6528
|
isSpaMode,
|
|
6443
6529
|
basename,
|
|
6444
|
-
patch
|
|
6530
|
+
patch,
|
|
6531
|
+
signal
|
|
6445
6532
|
);
|
|
6446
6533
|
};
|
|
6447
6534
|
}
|
|
6448
|
-
function useFogOFWarDiscovery(router, manifest, routeModules, isSpaMode) {
|
|
6535
|
+
function useFogOFWarDiscovery(router, manifest, routeModules, ssr, isSpaMode) {
|
|
6449
6536
|
React8.useEffect(() => {
|
|
6450
|
-
if (!isFogOfWarEnabled(
|
|
6537
|
+
if (!isFogOfWarEnabled(ssr) || navigator.connection?.saveData === true) {
|
|
6451
6538
|
return;
|
|
6452
6539
|
}
|
|
6453
6540
|
function registerElement(el) {
|
|
@@ -6477,6 +6564,7 @@ function useFogOFWarDiscovery(router, manifest, routeModules, isSpaMode) {
|
|
|
6477
6564
|
lazyPaths,
|
|
6478
6565
|
manifest,
|
|
6479
6566
|
routeModules,
|
|
6567
|
+
ssr,
|
|
6480
6568
|
isSpaMode,
|
|
6481
6569
|
router.basename,
|
|
6482
6570
|
router.patchRoutes
|
|
@@ -6495,9 +6583,9 @@ function useFogOFWarDiscovery(router, manifest, routeModules, isSpaMode) {
|
|
|
6495
6583
|
attributeFilter: ["data-discover", "href", "action"]
|
|
6496
6584
|
});
|
|
6497
6585
|
return () => observer.disconnect();
|
|
6498
|
-
}, [isSpaMode, manifest, routeModules, router]);
|
|
6586
|
+
}, [ssr, isSpaMode, manifest, routeModules, router]);
|
|
6499
6587
|
}
|
|
6500
|
-
async function fetchAndApplyManifestPatches(paths, manifest, routeModules, isSpaMode, basename, patchRoutes) {
|
|
6588
|
+
async function fetchAndApplyManifestPatches(paths, manifest, routeModules, ssr, isSpaMode, basename, patchRoutes, signal) {
|
|
6501
6589
|
let manifestPath = `${basename != null ? basename : "/"}/__manifest`.replace(
|
|
6502
6590
|
/\/+/g,
|
|
6503
6591
|
"/"
|
|
@@ -6509,13 +6597,19 @@ async function fetchAndApplyManifestPatches(paths, manifest, routeModules, isSpa
|
|
|
6509
6597
|
nextPaths.clear();
|
|
6510
6598
|
return;
|
|
6511
6599
|
}
|
|
6512
|
-
let
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6600
|
+
let serverPatches;
|
|
6601
|
+
try {
|
|
6602
|
+
let res = await fetch(url, { signal });
|
|
6603
|
+
if (!res.ok) {
|
|
6604
|
+
throw new Error(`${res.status} ${res.statusText}`);
|
|
6605
|
+
} else if (res.status >= 400) {
|
|
6606
|
+
throw new Error(await res.text());
|
|
6607
|
+
}
|
|
6608
|
+
serverPatches = await res.json();
|
|
6609
|
+
} catch (e) {
|
|
6610
|
+
if (signal?.aborted) return;
|
|
6611
|
+
throw e;
|
|
6517
6612
|
}
|
|
6518
|
-
let serverPatches = await res.json();
|
|
6519
6613
|
let knownRoutes = new Set(Object.keys(manifest.routes));
|
|
6520
6614
|
let patches = Object.values(serverPatches).reduce((acc, route) => {
|
|
6521
6615
|
if (route && !knownRoutes.has(route.id)) {
|
|
@@ -6534,7 +6628,7 @@ async function fetchAndApplyManifestPatches(paths, manifest, routeModules, isSpa
|
|
|
6534
6628
|
parentIds.forEach(
|
|
6535
6629
|
(parentId) => patchRoutes(
|
|
6536
6630
|
parentId || null,
|
|
6537
|
-
createClientRoutes(patches, routeModules, null, isSpaMode, parentId)
|
|
6631
|
+
createClientRoutes(patches, routeModules, null, ssr, isSpaMode, parentId)
|
|
6538
6632
|
)
|
|
6539
6633
|
);
|
|
6540
6634
|
}
|
|
@@ -6883,10 +6977,10 @@ function isValidMetaTag(tagName) {
|
|
|
6883
6977
|
}
|
|
6884
6978
|
var isHydrated = false;
|
|
6885
6979
|
function Scripts(props) {
|
|
6886
|
-
let { manifest, serverHandoffString, isSpaMode, renderMeta } = useFrameworkContext();
|
|
6980
|
+
let { manifest, serverHandoffString, isSpaMode, ssr, renderMeta } = useFrameworkContext();
|
|
6887
6981
|
let { router, static: isStatic, staticContext } = useDataRouterContext2();
|
|
6888
6982
|
let { matches: routerMatches } = useDataRouterStateContext();
|
|
6889
|
-
let enableFogOfWar = isFogOfWarEnabled(
|
|
6983
|
+
let enableFogOfWar = isFogOfWarEnabled(ssr);
|
|
6890
6984
|
if (renderMeta) {
|
|
6891
6985
|
renderMeta.didRenderScripts = true;
|
|
6892
6986
|
}
|
|
@@ -6898,11 +6992,44 @@ function Scripts(props) {
|
|
|
6898
6992
|
let streamScript = "window.__reactRouterContext.stream = new ReadableStream({start(controller){window.__reactRouterContext.streamController = controller;}}).pipeThrough(new TextEncoderStream());";
|
|
6899
6993
|
let contextScript = staticContext ? `window.__reactRouterContext = ${serverHandoffString};${streamScript}` : " ";
|
|
6900
6994
|
let routeModulesScript = !isStatic ? " " : `${manifest.hmr?.runtime ? `import ${JSON.stringify(manifest.hmr.runtime)};` : ""}${!enableFogOfWar ? `import ${JSON.stringify(manifest.url)}` : ""};
|
|
6901
|
-
${matches.map(
|
|
6902
|
-
|
|
6903
|
-
|
|
6904
|
-
)
|
|
6905
|
-
|
|
6995
|
+
${matches.map((match, routeIndex) => {
|
|
6996
|
+
let routeVarName = `route${routeIndex}`;
|
|
6997
|
+
let manifestEntry = manifest.routes[match.route.id];
|
|
6998
|
+
invariant2(manifestEntry, `Route ${match.route.id} not found in manifest`);
|
|
6999
|
+
let {
|
|
7000
|
+
clientActionModule,
|
|
7001
|
+
clientLoaderModule,
|
|
7002
|
+
hydrateFallbackModule,
|
|
7003
|
+
module
|
|
7004
|
+
} = manifestEntry;
|
|
7005
|
+
let chunks = [
|
|
7006
|
+
...clientActionModule ? [
|
|
7007
|
+
{
|
|
7008
|
+
module: clientActionModule,
|
|
7009
|
+
varName: `${routeVarName}_clientAction`
|
|
7010
|
+
}
|
|
7011
|
+
] : [],
|
|
7012
|
+
...clientLoaderModule ? [
|
|
7013
|
+
{
|
|
7014
|
+
module: clientLoaderModule,
|
|
7015
|
+
varName: `${routeVarName}_clientLoader`
|
|
7016
|
+
}
|
|
7017
|
+
] : [],
|
|
7018
|
+
...hydrateFallbackModule ? [
|
|
7019
|
+
{
|
|
7020
|
+
module: hydrateFallbackModule,
|
|
7021
|
+
varName: `${routeVarName}_HydrateFallback`
|
|
7022
|
+
}
|
|
7023
|
+
] : [],
|
|
7024
|
+
{ module, varName: `${routeVarName}_main` }
|
|
7025
|
+
];
|
|
7026
|
+
if (chunks.length === 1) {
|
|
7027
|
+
return `import * as ${routeVarName} from ${JSON.stringify(module)};`;
|
|
7028
|
+
}
|
|
7029
|
+
let chunkImportsSnippet = chunks.map((chunk) => `import * as ${chunk.varName} from "${chunk.module}";`).join("\n");
|
|
7030
|
+
let mergedChunksSnippet = `const ${routeVarName} = {${chunks.map((chunk) => `...${chunk.varName}`).join(",")}};`;
|
|
7031
|
+
return [chunkImportsSnippet, mergedChunksSnippet].join("\n");
|
|
7032
|
+
}).join("\n")}
|
|
6906
7033
|
${enableFogOfWar ? (
|
|
6907
7034
|
// Inline a minimal manifest with the SSR matches
|
|
6908
7035
|
`window.__reactRouterManifest = ${JSON.stringify(
|
|
@@ -6933,11 +7060,11 @@ import(${JSON.stringify(manifest.entry.module)});`;
|
|
|
6933
7060
|
}
|
|
6934
7061
|
));
|
|
6935
7062
|
}, []);
|
|
6936
|
-
let
|
|
6937
|
-
|
|
6938
|
-
|
|
6939
|
-
|
|
6940
|
-
|
|
7063
|
+
let preloads = isHydrated ? [] : manifest.entry.imports.concat(
|
|
7064
|
+
getModuleLinkHrefs(matches, manifest, {
|
|
7065
|
+
includeHydrateFallback: true
|
|
7066
|
+
})
|
|
7067
|
+
);
|
|
6941
7068
|
return isHydrated ? null : /* @__PURE__ */ React9.createElement(React9.Fragment, null, !enableFogOfWar ? /* @__PURE__ */ React9.createElement(
|
|
6942
7069
|
"link",
|
|
6943
7070
|
{
|
|
@@ -6981,7 +7108,7 @@ function mergeRefs(...refs) {
|
|
|
6981
7108
|
var isBrowser = typeof window !== "undefined" && typeof window.document !== "undefined" && typeof window.document.createElement !== "undefined";
|
|
6982
7109
|
try {
|
|
6983
7110
|
if (isBrowser) {
|
|
6984
|
-
window.__reactRouterVersion = "7.
|
|
7111
|
+
window.__reactRouterVersion = "7.2.0-pre.0";
|
|
6985
7112
|
}
|
|
6986
7113
|
} catch (e) {
|
|
6987
7114
|
}
|
|
@@ -8093,6 +8220,7 @@ function ServerRouter({
|
|
|
8093
8220
|
criticalCss,
|
|
8094
8221
|
serverHandoffString,
|
|
8095
8222
|
future: context.future,
|
|
8223
|
+
ssr: context.ssr,
|
|
8096
8224
|
isSpaMode: context.isSpaMode,
|
|
8097
8225
|
serializeError: context.serializeError,
|
|
8098
8226
|
renderMeta: context.renderMeta
|
|
@@ -8139,6 +8267,7 @@ function createRoutesStub(routes, context = {}) {
|
|
|
8139
8267
|
version: ""
|
|
8140
8268
|
},
|
|
8141
8269
|
routeModules: {},
|
|
8270
|
+
ssr: false,
|
|
8142
8271
|
isSpaMode: false
|
|
8143
8272
|
};
|
|
8144
8273
|
let patched = processRoutes(
|
|
@@ -8190,8 +8319,11 @@ function processRoutes(routes, context, manifest, routeModules, parentId) {
|
|
|
8190
8319
|
hasClientAction: false,
|
|
8191
8320
|
hasClientLoader: false,
|
|
8192
8321
|
hasErrorBoundary: route.ErrorBoundary != null,
|
|
8193
|
-
|
|
8194
|
-
|
|
8322
|
+
// any need for these?
|
|
8323
|
+
module: "build/stub-path-to-module.js",
|
|
8324
|
+
clientActionModule: void 0,
|
|
8325
|
+
clientLoaderModule: void 0,
|
|
8326
|
+
hydrateFallbackModule: void 0
|
|
8195
8327
|
};
|
|
8196
8328
|
manifest.routes[newRoute.id] = entryRoute;
|
|
8197
8329
|
routeModules[route.id] = {
|
|
@@ -8981,6 +9113,10 @@ var createRequestHandler = (build, mode) => {
|
|
|
8981
9113
|
errorHandler = derived.errorHandler;
|
|
8982
9114
|
}
|
|
8983
9115
|
let url = new URL(request.url);
|
|
9116
|
+
let normalizedPath = url.pathname.replace(/\.data$/, "").replace(/^\/_root$/, "/");
|
|
9117
|
+
if (normalizedPath !== "/" && normalizedPath.endsWith("/")) {
|
|
9118
|
+
normalizedPath = normalizedPath.slice(0, -1);
|
|
9119
|
+
}
|
|
8984
9120
|
let params = {};
|
|
8985
9121
|
let handleError = (error) => {
|
|
8986
9122
|
if (mode === "development" /* Development */) {
|
|
@@ -8992,6 +9128,32 @@ var createRequestHandler = (build, mode) => {
|
|
|
8992
9128
|
request
|
|
8993
9129
|
});
|
|
8994
9130
|
};
|
|
9131
|
+
if (!_build.ssr) {
|
|
9132
|
+
if (_build.prerender.length === 0) {
|
|
9133
|
+
request.headers.set("X-React-Router-SPA-Mode", "yes");
|
|
9134
|
+
} else if (!_build.prerender.includes(normalizedPath) && !_build.prerender.includes(normalizedPath + "/")) {
|
|
9135
|
+
if (url.pathname.endsWith(".data")) {
|
|
9136
|
+
errorHandler(
|
|
9137
|
+
new ErrorResponseImpl(
|
|
9138
|
+
404,
|
|
9139
|
+
"Not Found",
|
|
9140
|
+
`Refusing to SSR the path \`${normalizedPath}\` because \`ssr:false\` is set and the path is not included in the \`prerender\` config, so in production the path will be a 404.`
|
|
9141
|
+
),
|
|
9142
|
+
{
|
|
9143
|
+
context: loadContext,
|
|
9144
|
+
params,
|
|
9145
|
+
request
|
|
9146
|
+
}
|
|
9147
|
+
);
|
|
9148
|
+
return new Response("Not Found", {
|
|
9149
|
+
status: 404,
|
|
9150
|
+
statusText: "Not Found"
|
|
9151
|
+
});
|
|
9152
|
+
} else {
|
|
9153
|
+
request.headers.set("X-React-Router-SPA-Mode", "yes");
|
|
9154
|
+
}
|
|
9155
|
+
}
|
|
9156
|
+
}
|
|
8995
9157
|
let manifestUrl = `${_build.basename ?? "/"}/__manifest`.replace(
|
|
8996
9158
|
/\/+/g,
|
|
8997
9159
|
"/"
|
|
@@ -9012,7 +9174,7 @@ var createRequestHandler = (build, mode) => {
|
|
|
9012
9174
|
let response;
|
|
9013
9175
|
if (url.pathname.endsWith(".data")) {
|
|
9014
9176
|
let handlerUrl = new URL(request.url);
|
|
9015
|
-
handlerUrl.pathname =
|
|
9177
|
+
handlerUrl.pathname = normalizedPath;
|
|
9016
9178
|
let singleFetchMatches = matchServerRoutes(
|
|
9017
9179
|
routes,
|
|
9018
9180
|
handlerUrl.pathname,
|
|
@@ -9152,6 +9314,7 @@ async function handleSingleFetchRequest(serverMode, build, staticHandler, reques
|
|
|
9152
9314
|
);
|
|
9153
9315
|
}
|
|
9154
9316
|
async function handleDocumentRequest(serverMode, build, staticHandler, request, loadContext, handleError, criticalCss) {
|
|
9317
|
+
let isSpaMode = request.headers.has("X-React-Router-SPA-Mode");
|
|
9155
9318
|
let context;
|
|
9156
9319
|
try {
|
|
9157
9320
|
context = await staticHandler.query(request, {
|
|
@@ -9190,7 +9353,8 @@ async function handleDocumentRequest(serverMode, build, staticHandler, request,
|
|
|
9190
9353
|
basename: build.basename,
|
|
9191
9354
|
criticalCss,
|
|
9192
9355
|
future: build.future,
|
|
9193
|
-
|
|
9356
|
+
ssr: build.ssr,
|
|
9357
|
+
isSpaMode
|
|
9194
9358
|
}),
|
|
9195
9359
|
serverHandoffStream: encodeViaTurboStream(
|
|
9196
9360
|
state,
|
|
@@ -9200,7 +9364,8 @@ async function handleDocumentRequest(serverMode, build, staticHandler, request,
|
|
|
9200
9364
|
),
|
|
9201
9365
|
renderMeta: {},
|
|
9202
9366
|
future: build.future,
|
|
9203
|
-
|
|
9367
|
+
ssr: build.ssr,
|
|
9368
|
+
isSpaMode,
|
|
9204
9369
|
serializeError: (err) => serializeError(err, serverMode)
|
|
9205
9370
|
};
|
|
9206
9371
|
let handleDocumentRequestFunction = build.entry.module.default;
|
|
@@ -9245,7 +9410,8 @@ async function handleDocumentRequest(serverMode, build, staticHandler, request,
|
|
|
9245
9410
|
serverHandoffString: createServerHandoffString({
|
|
9246
9411
|
basename: build.basename,
|
|
9247
9412
|
future: build.future,
|
|
9248
|
-
|
|
9413
|
+
ssr: build.ssr,
|
|
9414
|
+
isSpaMode
|
|
9249
9415
|
}),
|
|
9250
9416
|
serverHandoffStream: encodeViaTurboStream(
|
|
9251
9417
|
state2,
|