@tanstack/router-core 0.0.1-alpha.7 → 0.0.1-alpha.9
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/build/cjs/packages/router-core/src/routeMatch.js +6 -5
- package/build/cjs/packages/router-core/src/routeMatch.js.map +1 -1
- package/build/cjs/packages/router-core/src/router.js +43 -27
- package/build/cjs/packages/router-core/src/router.js.map +1 -1
- package/build/esm/index.js +49 -32
- package/build/esm/index.js.map +1 -1
- package/build/stats-html.html +1 -1
- package/build/stats-react.json +134 -134
- package/build/types/index.d.ts +15 -6
- package/build/umd/index.development.js +49 -32
- package/build/umd/index.development.js.map +1 -1
- package/build/umd/index.production.js +1 -1
- package/build/umd/index.production.js.map +1 -1
- package/package.json +1 -1
- package/src/link.ts +3 -1
- package/src/routeMatch.ts +11 -7
- package/src/router.ts +53 -31
package/package.json
CHANGED
package/src/link.ts
CHANGED
|
@@ -220,8 +220,10 @@ export type LinkOptions<
|
|
|
220
220
|
activeOptions?: ActiveOptions
|
|
221
221
|
// If set, will preload the linked route on hover and cache it for this many milliseconds in hopes that the user will eventually navigate there.
|
|
222
222
|
preload?: false | 'intent'
|
|
223
|
-
// When preloaded
|
|
223
|
+
// When preloaded, the preloaded result will be considered "fresh" for this duration in milliseconds
|
|
224
224
|
preloadMaxAge?: number
|
|
225
|
+
// When preloaded and subsequently inactive, the preloaded result will remain in memory for this duration in milliseconds
|
|
226
|
+
preloadGcMaxAge?: number
|
|
225
227
|
// Delay intent preloading by this many milliseconds. If the intent exits before this delay, the preload will be cancelled.
|
|
226
228
|
preloadDelay?: number
|
|
227
229
|
// If true, will render the link without the href attribute
|
package/src/routeMatch.ts
CHANGED
|
@@ -30,6 +30,7 @@ export interface RouteMatch<
|
|
|
30
30
|
routeLoaderData: TRouteInfo['routeLoaderData']
|
|
31
31
|
isFetching: boolean
|
|
32
32
|
isPending: boolean
|
|
33
|
+
invalidAt: number
|
|
33
34
|
__: {
|
|
34
35
|
element?: GetFrameworkGeneric<'Element'> // , TRouteInfo['loaderData']>
|
|
35
36
|
errorElement?: GetFrameworkGeneric<'Element'> // , TRouteInfo['loaderData']>
|
|
@@ -60,7 +61,7 @@ export interface RouteMatch<
|
|
|
60
61
|
resolve: () => void
|
|
61
62
|
}
|
|
62
63
|
cancel: () => void
|
|
63
|
-
load: () => Promise<void>
|
|
64
|
+
load: (opts?: { maxAge?: number }) => Promise<void>
|
|
64
65
|
invalidate: () => void
|
|
65
66
|
hasLoaders: () => boolean
|
|
66
67
|
}
|
|
@@ -97,13 +98,10 @@ export function createRouteMatch<
|
|
|
97
98
|
isPending: false,
|
|
98
99
|
isFetching: false,
|
|
99
100
|
isInvalid: false,
|
|
101
|
+
invalidAt: Infinity,
|
|
100
102
|
getIsInvalid: () => {
|
|
101
103
|
const now = Date.now()
|
|
102
|
-
|
|
103
|
-
routeMatch.options.loaderMaxAge ??
|
|
104
|
-
router.options.defaultLoaderMaxAge ??
|
|
105
|
-
0
|
|
106
|
-
return routeMatch.isInvalid || routeMatch.updatedAt! + maxAge < now
|
|
104
|
+
return routeMatch.isInvalid || routeMatch.invalidAt < now
|
|
107
105
|
},
|
|
108
106
|
__: {
|
|
109
107
|
abortController: new AbortController(),
|
|
@@ -212,7 +210,7 @@ export function createRouteMatch<
|
|
|
212
210
|
elementTypes.some((d) => typeof route.options[d] === 'function')
|
|
213
211
|
)
|
|
214
212
|
},
|
|
215
|
-
load: async () => {
|
|
213
|
+
load: async (opts) => {
|
|
216
214
|
const id = '' + Date.now() + Math.random()
|
|
217
215
|
routeMatch.__.latestId = id
|
|
218
216
|
|
|
@@ -298,6 +296,12 @@ export function createRouteMatch<
|
|
|
298
296
|
routeMatch.error = undefined
|
|
299
297
|
routeMatch.status = 'success'
|
|
300
298
|
routeMatch.updatedAt = Date.now()
|
|
299
|
+
routeMatch.invalidAt =
|
|
300
|
+
routeMatch.updatedAt +
|
|
301
|
+
(opts?.maxAge ??
|
|
302
|
+
routeMatch.options.loaderMaxAge ??
|
|
303
|
+
router.options.defaultLoaderMaxAge ??
|
|
304
|
+
0)
|
|
301
305
|
} catch (err) {
|
|
302
306
|
if (id !== routeMatch.__.latestId) {
|
|
303
307
|
return routeMatch.__.loaderPromise
|
package/src/router.ts
CHANGED
|
@@ -81,9 +81,10 @@ export interface RouterOptions<TRouteConfig extends AnyRouteConfig> {
|
|
|
81
81
|
stringifySearch?: SearchSerializer
|
|
82
82
|
parseSearch?: SearchParser
|
|
83
83
|
filterRoutes?: FilterRoutesFn
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
defaultPreload?: false | 'intent'
|
|
85
|
+
defaultPreloadMaxAge?: number
|
|
86
|
+
defaultPreloadGcMaxAge?: number
|
|
87
|
+
defaultPreloadDelay?: number
|
|
87
88
|
useErrorBoundary?: boolean
|
|
88
89
|
defaultElement?: GetFrameworkGeneric<'Element'>
|
|
89
90
|
defaultErrorElement?: GetFrameworkGeneric<'Element'>
|
|
@@ -227,9 +228,10 @@ export interface Router<
|
|
|
227
228
|
getRoute: <TId extends keyof TAllRouteInfo['routeInfoById']>(
|
|
228
229
|
id: TId,
|
|
229
230
|
) => Route<TAllRouteInfo, TAllRouteInfo['routeInfoById'][TId]>
|
|
230
|
-
loadRoute: (
|
|
231
|
+
loadRoute: (navigateOpts: BuildNextOptions) => Promise<RouteMatch[]>
|
|
232
|
+
preloadRoute: (
|
|
231
233
|
navigateOpts: BuildNextOptions,
|
|
232
|
-
loaderOpts: { maxAge
|
|
234
|
+
loaderOpts: { maxAge?: number; gcMaxAge?: number },
|
|
233
235
|
) => Promise<RouteMatch[]>
|
|
234
236
|
matchRoutes: (
|
|
235
237
|
pathname: string,
|
|
@@ -238,8 +240,8 @@ export interface Router<
|
|
|
238
240
|
loadMatches: (
|
|
239
241
|
resolvedMatches: RouteMatch[],
|
|
240
242
|
loaderOpts?: { withPending?: boolean } & (
|
|
241
|
-
| { preload: true; maxAge: number }
|
|
242
|
-
| { preload?: false; maxAge?: never }
|
|
243
|
+
| { preload: true; maxAge: number; gcMaxAge: number }
|
|
244
|
+
| { preload?: false; maxAge?: never; gcMaxAge?: never }
|
|
243
245
|
),
|
|
244
246
|
) => Promise<void>
|
|
245
247
|
invalidateRoute: (opts: MatchLocation) => void
|
|
@@ -289,7 +291,8 @@ export function createRouter<
|
|
|
289
291
|
const originalOptions = {
|
|
290
292
|
defaultLoaderGcMaxAge: 5 * 60 * 1000,
|
|
291
293
|
defaultLoaderMaxAge: 0,
|
|
292
|
-
|
|
294
|
+
defaultPreloadMaxAge: 2000,
|
|
295
|
+
defaultPreloadDelay: 50,
|
|
293
296
|
...userOptions,
|
|
294
297
|
stringifySearch: userOptions?.stringifySearch ?? defaultStringifySearch,
|
|
295
298
|
parseSearch: userOptions?.parseSearch ?? defaultParseSearch,
|
|
@@ -782,17 +785,32 @@ export function createRouter<
|
|
|
782
785
|
})
|
|
783
786
|
},
|
|
784
787
|
|
|
785
|
-
loadRoute: async (
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
788
|
+
loadRoute: async (navigateOpts = router.location) => {
|
|
789
|
+
const next = router.buildNext(navigateOpts)
|
|
790
|
+
const matches = router.matchRoutes(next.pathname, {
|
|
791
|
+
strictParseParams: true,
|
|
792
|
+
})
|
|
793
|
+
await router.loadMatches(matches)
|
|
794
|
+
return matches
|
|
795
|
+
},
|
|
796
|
+
|
|
797
|
+
preloadRoute: async (navigateOpts = router.location, loaderOpts) => {
|
|
789
798
|
const next = router.buildNext(navigateOpts)
|
|
790
799
|
const matches = router.matchRoutes(next.pathname, {
|
|
791
800
|
strictParseParams: true,
|
|
792
801
|
})
|
|
793
802
|
await router.loadMatches(matches, {
|
|
794
803
|
preload: true,
|
|
795
|
-
maxAge:
|
|
804
|
+
maxAge:
|
|
805
|
+
loaderOpts.maxAge ??
|
|
806
|
+
router.options.defaultPreloadMaxAge ??
|
|
807
|
+
router.options.defaultLoaderMaxAge ??
|
|
808
|
+
0,
|
|
809
|
+
gcMaxAge:
|
|
810
|
+
loaderOpts.gcMaxAge ??
|
|
811
|
+
router.options.defaultPreloadGcMaxAge ??
|
|
812
|
+
router.options.defaultLoaderGcMaxAge ??
|
|
813
|
+
0,
|
|
796
814
|
})
|
|
797
815
|
return matches
|
|
798
816
|
},
|
|
@@ -905,23 +923,23 @@ export function createRouter<
|
|
|
905
923
|
|
|
906
924
|
loadMatches: async (resolvedMatches, loaderOpts) => {
|
|
907
925
|
const now = Date.now()
|
|
926
|
+
const minMaxAge = loaderOpts?.preload
|
|
927
|
+
? Math.max(loaderOpts?.maxAge, loaderOpts?.gcMaxAge)
|
|
928
|
+
: 0
|
|
908
929
|
|
|
909
930
|
const matchPromises = resolvedMatches.map(async (match) => {
|
|
910
931
|
// Validate the match (loads search params etc)
|
|
911
932
|
match.__.validate()
|
|
912
933
|
|
|
913
|
-
// If the match doesn't have a loader, don't attempt to load it
|
|
914
|
-
if (!match.hasLoaders()) {
|
|
915
|
-
return
|
|
916
|
-
}
|
|
917
934
|
// If this is a preload, add it to the preload cache
|
|
918
|
-
if (loaderOpts?.preload &&
|
|
935
|
+
if (loaderOpts?.preload && minMaxAge > 0) {
|
|
919
936
|
// If the match is currently active, don't preload it
|
|
920
937
|
if (router.state.matches.find((d) => d.matchId === match.matchId)) {
|
|
921
938
|
return
|
|
922
939
|
}
|
|
940
|
+
|
|
923
941
|
router.matchCache[match.matchId] = {
|
|
924
|
-
gc: now + loaderOpts.
|
|
942
|
+
gc: now + loaderOpts.gcMaxAge,
|
|
925
943
|
match,
|
|
926
944
|
}
|
|
927
945
|
}
|
|
@@ -932,7 +950,9 @@ export function createRouter<
|
|
|
932
950
|
match.status === 'error' ||
|
|
933
951
|
match.status === 'idle'
|
|
934
952
|
) {
|
|
935
|
-
|
|
953
|
+
const maxAge = loaderOpts?.preload ? loaderOpts?.maxAge : undefined
|
|
954
|
+
|
|
955
|
+
match.load({ maxAge })
|
|
936
956
|
}
|
|
937
957
|
|
|
938
958
|
if (match.status === 'loading') {
|
|
@@ -1051,6 +1071,7 @@ export function createRouter<
|
|
|
1051
1071
|
activeOptions,
|
|
1052
1072
|
preload,
|
|
1053
1073
|
preloadMaxAge: userPreloadMaxAge,
|
|
1074
|
+
preloadGcMaxAge: userPreloadGcMaxAge,
|
|
1054
1075
|
preloadDelay: userPreloadDelay,
|
|
1055
1076
|
disabled,
|
|
1056
1077
|
}) => {
|
|
@@ -1079,14 +1100,9 @@ export function createRouter<
|
|
|
1079
1100
|
|
|
1080
1101
|
const next = router.buildNext(nextOpts)
|
|
1081
1102
|
|
|
1082
|
-
preload = preload ?? router.options.
|
|
1083
|
-
const preloadMaxAge =
|
|
1084
|
-
userPreloadMaxAge ??
|
|
1085
|
-
router.options.defaultLinkPreloadMaxAge ??
|
|
1086
|
-
router.options.defaultLoaderGcMaxAge ??
|
|
1087
|
-
0
|
|
1103
|
+
preload = preload ?? router.options.defaultPreload
|
|
1088
1104
|
const preloadDelay =
|
|
1089
|
-
userPreloadDelay ?? router.options.
|
|
1105
|
+
userPreloadDelay ?? router.options.defaultPreloadDelay ?? 0
|
|
1090
1106
|
|
|
1091
1107
|
// Compare path/hash for matches
|
|
1092
1108
|
const pathIsEqual = router.state.location.pathname === next.pathname
|
|
@@ -1124,22 +1140,28 @@ export function createRouter<
|
|
|
1124
1140
|
|
|
1125
1141
|
// The click handler
|
|
1126
1142
|
const handleFocus = (e: MouseEvent) => {
|
|
1127
|
-
if (preload
|
|
1128
|
-
router.
|
|
1143
|
+
if (preload) {
|
|
1144
|
+
router.preloadRoute(nextOpts, {
|
|
1145
|
+
maxAge: userPreloadMaxAge,
|
|
1146
|
+
gcMaxAge: userPreloadGcMaxAge,
|
|
1147
|
+
})
|
|
1129
1148
|
}
|
|
1130
1149
|
}
|
|
1131
1150
|
|
|
1132
1151
|
const handleEnter = (e: MouseEvent) => {
|
|
1133
1152
|
const target = (e.target || {}) as LinkCurrentTargetElement
|
|
1134
1153
|
|
|
1135
|
-
if (preload
|
|
1154
|
+
if (preload) {
|
|
1136
1155
|
if (target.preloadTimeout) {
|
|
1137
1156
|
return
|
|
1138
1157
|
}
|
|
1139
1158
|
|
|
1140
1159
|
target.preloadTimeout = setTimeout(() => {
|
|
1141
1160
|
target.preloadTimeout = null
|
|
1142
|
-
router.
|
|
1161
|
+
router.preloadRoute(nextOpts, {
|
|
1162
|
+
maxAge: userPreloadMaxAge,
|
|
1163
|
+
gcMaxAge: userPreloadGcMaxAge,
|
|
1164
|
+
})
|
|
1143
1165
|
}, preloadDelay)
|
|
1144
1166
|
}
|
|
1145
1167
|
}
|