@remix-run/router 1.19.0 → 1.19.1
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 +10 -0
- package/dist/index.d.ts +1 -1
- package/dist/router.cjs.js +45 -54
- package/dist/router.cjs.js.map +1 -1
- package/dist/router.d.ts +2 -2
- package/dist/router.js +44 -53
- package/dist/router.js.map +1 -1
- package/dist/router.umd.js +45 -54
- package/dist/router.umd.js.map +1 -1
- package/dist/router.umd.min.js +2 -2
- package/dist/router.umd.min.js.map +1 -1
- package/dist/utils.d.ts +1 -1
- package/index.ts +1 -1
- package/package.json +1 -1
- package/router.ts +50 -57
- package/utils.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# `@remix-run/router`
|
|
2
2
|
|
|
3
|
+
## 1.19.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fog of War: Update `unstable_patchRoutesOnMiss` logic so that we call the method when we match routes with dynamic param or splat segments in case there exists a higher-scoring static route that we've not yet discovered. ([#11883](https://github.com/remix-run/react-router/pull/11883))
|
|
8
|
+
|
|
9
|
+
- We also now leverage an internal FIFO queue of previous paths we've already called `unstable_patchRouteOnMiss` against so that we don't re-call on subsequent navigations to the same path
|
|
10
|
+
|
|
11
|
+
- Rename `unstable_patchRoutesOnMiss` to `unstable_patchRoutesOnNavigation` to match new behavior ([#11888](https://github.com/remix-run/react-router/pull/11888))
|
|
12
|
+
|
|
3
13
|
## 1.19.0
|
|
4
14
|
|
|
5
15
|
### Minor Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticRouteMatch, AgnosticRouteObject, DataStrategyFunction as unstable_DataStrategyFunction, DataStrategyFunctionArgs as unstable_DataStrategyFunctionArgs, DataStrategyMatch as unstable_DataStrategyMatch, ErrorResponse, FormEncType, FormMethod, HandlerResult as unstable_HandlerResult, HTMLFormMethod, JsonFunction, LazyRouteFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params,
|
|
1
|
+
export type { ActionFunction, ActionFunctionArgs, AgnosticDataIndexRouteObject, AgnosticDataNonIndexRouteObject, AgnosticDataRouteMatch, AgnosticDataRouteObject, AgnosticIndexRouteObject, AgnosticNonIndexRouteObject, AgnosticRouteMatch, AgnosticRouteObject, DataStrategyFunction as unstable_DataStrategyFunction, DataStrategyFunctionArgs as unstable_DataStrategyFunctionArgs, DataStrategyMatch as unstable_DataStrategyMatch, ErrorResponse, FormEncType, FormMethod, HandlerResult as unstable_HandlerResult, HTMLFormMethod, JsonFunction, LazyRouteFunction, LoaderFunction, LoaderFunctionArgs, ParamParseKey, Params, AgnosticPatchRoutesOnNavigationFunction as unstable_AgnosticPatchRoutesOnNavigationFunction, PathMatch, PathParam, PathPattern, RedirectFunction, ShouldRevalidateFunction, ShouldRevalidateFunctionArgs, TrackedPromise, UIMatch, V7_FormMethod, DataWithResponseInit as UNSAFE_DataWithResponseInit, } from "./utils";
|
|
2
2
|
export { AbortedDeferredError, data as unstable_data, defer, generatePath, getToPathname, isRouteErrorResponse, joinPaths, json, matchPath, matchRoutes, normalizePathname, redirect, redirectDocument, replace, resolvePath, resolveTo, stripBasename, } from "./utils";
|
|
3
3
|
export type { BrowserHistory, BrowserHistoryOptions, HashHistory, HashHistoryOptions, History, InitialEntry, Location, MemoryHistory, MemoryHistoryOptions, Path, To, } from "./history";
|
|
4
4
|
export { Action, createBrowserHistory, createHashHistory, createMemoryHistory, createPath, parsePath, } from "./history";
|
package/dist/router.cjs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @remix-run/router v1.19.
|
|
2
|
+
* @remix-run/router v1.19.1
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Remix Software Inc.
|
|
5
5
|
*
|
|
@@ -1713,7 +1713,7 @@ function createRouter(init) {
|
|
|
1713
1713
|
let inFlightDataRoutes;
|
|
1714
1714
|
let basename = init.basename || "/";
|
|
1715
1715
|
let dataStrategyImpl = init.unstable_dataStrategy || defaultDataStrategy;
|
|
1716
|
-
let
|
|
1716
|
+
let patchRoutesOnNavigationImpl = init.unstable_patchRoutesOnNavigation;
|
|
1717
1717
|
|
|
1718
1718
|
// Config driven behavior flags
|
|
1719
1719
|
let future = _extends({
|
|
@@ -1728,6 +1728,10 @@ function createRouter(init) {
|
|
|
1728
1728
|
let unlistenHistory = null;
|
|
1729
1729
|
// Externally-provided functions to call on all state changes
|
|
1730
1730
|
let subscribers = new Set();
|
|
1731
|
+
// FIFO queue of previously discovered routes to prevent re-calling on
|
|
1732
|
+
// subsequent navigations to the same path
|
|
1733
|
+
let discoveredRoutesMaxSize = 1000;
|
|
1734
|
+
let discoveredRoutes = new Set();
|
|
1731
1735
|
// Externally-provided object to hold scroll restoration locations during routing
|
|
1732
1736
|
let savedScrollPositions = null;
|
|
1733
1737
|
// Externally-provided function to get scroll restoration keys
|
|
@@ -1743,7 +1747,7 @@ function createRouter(init) {
|
|
|
1743
1747
|
let initialScrollRestored = init.hydrationData != null;
|
|
1744
1748
|
let initialMatches = matchRoutes(dataRoutes, init.history.location, basename);
|
|
1745
1749
|
let initialErrors = null;
|
|
1746
|
-
if (initialMatches == null && !
|
|
1750
|
+
if (initialMatches == null && !patchRoutesOnNavigationImpl) {
|
|
1747
1751
|
// If we do not match a user-provided-route, fall back to the root
|
|
1748
1752
|
// to allow the error boundary to take over
|
|
1749
1753
|
let error = getInternalRouterError(404, {
|
|
@@ -1759,7 +1763,7 @@ function createRouter(init) {
|
|
|
1759
1763
|
};
|
|
1760
1764
|
}
|
|
1761
1765
|
|
|
1762
|
-
// In SPA apps, if the user provided a
|
|
1766
|
+
// In SPA apps, if the user provided a patchRoutesOnNavigation implementation and
|
|
1763
1767
|
// our initial match is a splat route, clear them out so we run through lazy
|
|
1764
1768
|
// discovery on hydration in case there's a more accurate lazy route match.
|
|
1765
1769
|
// In SSR apps (with `hydrationData`), we expect that the server will send
|
|
@@ -1777,7 +1781,7 @@ function createRouter(init) {
|
|
|
1777
1781
|
initialMatches = [];
|
|
1778
1782
|
|
|
1779
1783
|
// If partial hydration and fog of war is enabled, we will be running
|
|
1780
|
-
// `
|
|
1784
|
+
// `patchRoutesOnNavigation` during hydration so include any partial matches as
|
|
1781
1785
|
// the initial matches so we can properly render `HydrateFallback`'s
|
|
1782
1786
|
if (future.v7_partialHydration) {
|
|
1783
1787
|
let fogOfWar = checkFogOfWar(null, dataRoutes, init.history.location.pathname);
|
|
@@ -1916,7 +1920,7 @@ function createRouter(init) {
|
|
|
1916
1920
|
// we don't need to update UI state if they change
|
|
1917
1921
|
let blockerFunctions = new Map();
|
|
1918
1922
|
|
|
1919
|
-
// Map of pending
|
|
1923
|
+
// Map of pending patchRoutesOnNavigation() promises (keyed by path/matches) so
|
|
1920
1924
|
// that we only kick them off once for a given combo
|
|
1921
1925
|
let pendingPatchRoutes = new Map();
|
|
1922
1926
|
|
|
@@ -3540,7 +3544,16 @@ function createRouter(init) {
|
|
|
3540
3544
|
return null;
|
|
3541
3545
|
}
|
|
3542
3546
|
function checkFogOfWar(matches, routesToUse, pathname) {
|
|
3543
|
-
if (
|
|
3547
|
+
if (patchRoutesOnNavigationImpl) {
|
|
3548
|
+
// Don't bother re-calling patchRouteOnMiss for a path we've already
|
|
3549
|
+
// processed. the last execution would have patched the route tree
|
|
3550
|
+
// accordingly so `matches` here are already accurate.
|
|
3551
|
+
if (discoveredRoutes.has(pathname)) {
|
|
3552
|
+
return {
|
|
3553
|
+
active: false,
|
|
3554
|
+
matches
|
|
3555
|
+
};
|
|
3556
|
+
}
|
|
3544
3557
|
if (!matches) {
|
|
3545
3558
|
let fogMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
|
|
3546
3559
|
return {
|
|
@@ -3548,11 +3561,10 @@ function createRouter(init) {
|
|
|
3548
3561
|
matches: fogMatches || []
|
|
3549
3562
|
};
|
|
3550
3563
|
} else {
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
//
|
|
3554
|
-
//
|
|
3555
|
-
// around and find out
|
|
3564
|
+
if (Object.keys(matches[0].params).length > 0) {
|
|
3565
|
+
// If we matched a dynamic param or a splat, it might only be because
|
|
3566
|
+
// we haven't yet discovered other routes that would match with a
|
|
3567
|
+
// higher score. Call patchRoutesOnNavigation just to be sure
|
|
3556
3568
|
let partialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
|
|
3557
3569
|
return {
|
|
3558
3570
|
active: true,
|
|
@@ -3568,12 +3580,11 @@ function createRouter(init) {
|
|
|
3568
3580
|
}
|
|
3569
3581
|
async function discoverRoutes(matches, pathname, signal) {
|
|
3570
3582
|
let partialMatches = matches;
|
|
3571
|
-
let route = partialMatches.length > 0 ? partialMatches[partialMatches.length - 1].route : null;
|
|
3572
3583
|
while (true) {
|
|
3573
3584
|
let isNonHMR = inFlightDataRoutes == null;
|
|
3574
3585
|
let routesToUse = inFlightDataRoutes || dataRoutes;
|
|
3575
3586
|
try {
|
|
3576
|
-
await loadLazyRouteChildren(
|
|
3587
|
+
await loadLazyRouteChildren(patchRoutesOnNavigationImpl, pathname, partialMatches, routesToUse, manifest, mapRouteProperties, pendingPatchRoutes, signal);
|
|
3577
3588
|
} catch (e) {
|
|
3578
3589
|
return {
|
|
3579
3590
|
type: "error",
|
|
@@ -3597,52 +3608,32 @@ function createRouter(init) {
|
|
|
3597
3608
|
};
|
|
3598
3609
|
}
|
|
3599
3610
|
let newMatches = matchRoutes(routesToUse, pathname, basename);
|
|
3600
|
-
let matchedSplat = false;
|
|
3601
3611
|
if (newMatches) {
|
|
3602
|
-
|
|
3603
|
-
if (leafRoute.index) {
|
|
3604
|
-
// If we found an index route, we can stop
|
|
3605
|
-
return {
|
|
3606
|
-
type: "success",
|
|
3607
|
-
matches: newMatches
|
|
3608
|
-
};
|
|
3609
|
-
}
|
|
3610
|
-
if (leafRoute.path && leafRoute.path.length > 0) {
|
|
3611
|
-
if (leafRoute.path === "*") {
|
|
3612
|
-
// If we found a splat route, we can't be sure there's not a
|
|
3613
|
-
// higher-scoring route down some partial matches trail so we need
|
|
3614
|
-
// to check that out
|
|
3615
|
-
matchedSplat = true;
|
|
3616
|
-
} else {
|
|
3617
|
-
// If we found a non-splat route, we can stop
|
|
3618
|
-
return {
|
|
3619
|
-
type: "success",
|
|
3620
|
-
matches: newMatches
|
|
3621
|
-
};
|
|
3622
|
-
}
|
|
3623
|
-
}
|
|
3624
|
-
}
|
|
3625
|
-
let newPartialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
|
|
3626
|
-
|
|
3627
|
-
// If we are no longer partially matching anything, this was either a
|
|
3628
|
-
// legit splat match above, or it's a 404. Also avoid loops if the
|
|
3629
|
-
// second pass results in the same partial matches
|
|
3630
|
-
if (!newPartialMatches || partialMatches.map(m => m.route.id).join("-") === newPartialMatches.map(m => m.route.id).join("-")) {
|
|
3612
|
+
addToFifoQueue(pathname, discoveredRoutes);
|
|
3631
3613
|
return {
|
|
3632
3614
|
type: "success",
|
|
3633
|
-
matches:
|
|
3615
|
+
matches: newMatches
|
|
3634
3616
|
};
|
|
3635
3617
|
}
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
if
|
|
3639
|
-
|
|
3618
|
+
let newPartialMatches = matchRoutesImpl(routesToUse, pathname, basename, true);
|
|
3619
|
+
|
|
3620
|
+
// Avoid loops if the second pass results in the same partial matches
|
|
3621
|
+
if (!newPartialMatches || partialMatches.length === newPartialMatches.length && partialMatches.every((m, i) => m.route.id === newPartialMatches[i].route.id)) {
|
|
3622
|
+
addToFifoQueue(pathname, discoveredRoutes);
|
|
3640
3623
|
return {
|
|
3641
3624
|
type: "success",
|
|
3642
|
-
matches:
|
|
3625
|
+
matches: null
|
|
3643
3626
|
};
|
|
3644
3627
|
}
|
|
3628
|
+
partialMatches = newPartialMatches;
|
|
3629
|
+
}
|
|
3630
|
+
}
|
|
3631
|
+
function addToFifoQueue(path, queue) {
|
|
3632
|
+
if (queue.size >= discoveredRoutesMaxSize) {
|
|
3633
|
+
let first = queue.values().next().value;
|
|
3634
|
+
queue.delete(first);
|
|
3645
3635
|
}
|
|
3636
|
+
queue.add(path);
|
|
3646
3637
|
}
|
|
3647
3638
|
function _internalSetRoutes(newRoutes) {
|
|
3648
3639
|
manifest = {};
|
|
@@ -4513,15 +4504,15 @@ function shouldRevalidateLoader(loaderMatch, arg) {
|
|
|
4513
4504
|
}
|
|
4514
4505
|
|
|
4515
4506
|
/**
|
|
4516
|
-
* Idempotent utility to execute
|
|
4507
|
+
* Idempotent utility to execute patchRoutesOnNavigation() to lazily load route
|
|
4517
4508
|
* definitions and update the routes/routeManifest
|
|
4518
4509
|
*/
|
|
4519
|
-
async function loadLazyRouteChildren(
|
|
4510
|
+
async function loadLazyRouteChildren(patchRoutesOnNavigationImpl, path, matches, routes, manifest, mapRouteProperties, pendingRouteChildren, signal) {
|
|
4520
4511
|
let key = [path, ...matches.map(m => m.route.id)].join("-");
|
|
4521
4512
|
try {
|
|
4522
4513
|
let pending = pendingRouteChildren.get(key);
|
|
4523
4514
|
if (!pending) {
|
|
4524
|
-
pending =
|
|
4515
|
+
pending = patchRoutesOnNavigationImpl({
|
|
4525
4516
|
path,
|
|
4526
4517
|
matches,
|
|
4527
4518
|
patch: (routeId, children) => {
|
|
@@ -5128,7 +5119,7 @@ function getInternalRouterError(status, _temp5) {
|
|
|
5128
5119
|
if (status === 400) {
|
|
5129
5120
|
statusText = "Bad Request";
|
|
5130
5121
|
if (type === "route-discovery") {
|
|
5131
|
-
errorMessage = "Unable to match URL \"" + pathname + "\" - the `
|
|
5122
|
+
errorMessage = "Unable to match URL \"" + pathname + "\" - the `unstable_patchRoutesOnNavigation()` " + ("function threw the following error:\n" + message);
|
|
5132
5123
|
} else if (method && pathname && routeId) {
|
|
5133
5124
|
errorMessage = "You made a " + method + " request to \"" + pathname + "\" but " + ("did not provide a `loader` for route \"" + routeId + "\", ") + "so there is no way to handle the request.";
|
|
5134
5125
|
} else if (type === "defer-action") {
|