|
9 | 9 | createControlledPromise,
|
10 | 10 | deepEqual,
|
11 | 11 | functionalUpdate,
|
| 12 | + isPromise, |
12 | 13 | last,
|
13 | 14 | pick,
|
14 | 15 | replaceEqualDeep,
|
@@ -2508,11 +2509,9 @@ export class RouterCore<
|
2508 | 2509 | })
|
2509 | 2510 | }
|
2510 | 2511 |
|
2511 |
| - const potentialPendingMinPromise = async () => { |
| 2512 | + const potentialPendingMinPromise = () => { |
2512 | 2513 | const latestMatch = this.getMatch(matchId)!
|
2513 |
| - if (latestMatch._nonReactive.minPendingPromise) { |
2514 |
| - await latestMatch._nonReactive.minPendingPromise |
2515 |
| - } |
| 2514 | + return latestMatch._nonReactive.minPendingPromise |
2516 | 2515 | }
|
2517 | 2516 |
|
2518 | 2517 | const prevMatch = this.getMatch(matchId)!
|
@@ -2621,41 +2620,63 @@ export class RouterCore<
|
2621 | 2620 | try {
|
2622 | 2621 | if (
|
2623 | 2622 | !this.isServer ||
|
2624 |
| - (this.isServer && |
2625 |
| - this.getMatch(matchId)!.ssr === true) |
| 2623 | + this.getMatch(matchId)!.ssr === true |
2626 | 2624 | ) {
|
2627 | 2625 | this.loadRouteChunk(route)
|
2628 | 2626 | }
|
2629 | 2627 |
|
2630 |
| - updateMatch(matchId, (prev) => ({ |
2631 |
| - ...prev, |
2632 |
| - isFetching: 'loader', |
2633 |
| - })) |
2634 |
| - |
2635 | 2628 | // Kick off the loader!
|
2636 |
| - const loaderData = |
2637 |
| - await route.options.loader?.(getLoaderContext()) |
2638 |
| - |
2639 |
| - handleRedirectAndNotFound( |
2640 |
| - this.getMatch(matchId), |
2641 |
| - loaderData, |
| 2629 | + const loaderResult = |
| 2630 | + route.options.loader?.(getLoaderContext()) |
| 2631 | + const loaderResultIsPromise = |
| 2632 | + route.options.loader && isPromise(loaderResult) |
| 2633 | + |
| 2634 | + const willLoadSomething = !!( |
| 2635 | + loaderResultIsPromise || |
| 2636 | + route._lazyPromise || |
| 2637 | + route._componentsPromise || |
| 2638 | + route.options.head || |
| 2639 | + route.options.scripts || |
| 2640 | + route.options.headers || |
| 2641 | + this.getMatch(matchId)!._nonReactive |
| 2642 | + .minPendingPromise |
2642 | 2643 | )
|
2643 |
| - updateMatch(matchId, (prev) => ({ |
2644 |
| - ...prev, |
2645 |
| - loaderData, |
2646 |
| - })) |
| 2644 | + |
| 2645 | + if (willLoadSomething) { |
| 2646 | + updateMatch(matchId, (prev) => ({ |
| 2647 | + ...prev, |
| 2648 | + isFetching: 'loader', |
| 2649 | + })) |
| 2650 | + } |
| 2651 | + |
| 2652 | + if (route.options.loader) { |
| 2653 | + const loaderData = loaderResultIsPromise |
| 2654 | + ? await loaderResult |
| 2655 | + : loaderResult |
| 2656 | + |
| 2657 | + handleRedirectAndNotFound( |
| 2658 | + this.getMatch(matchId), |
| 2659 | + loaderData, |
| 2660 | + ) |
| 2661 | + updateMatch(matchId, (prev) => ({ |
| 2662 | + ...prev, |
| 2663 | + loaderData, |
| 2664 | + })) |
| 2665 | + } |
2647 | 2666 |
|
2648 | 2667 | // Lazy option can modify the route options,
|
2649 | 2668 | // so we need to wait for it to resolve before
|
2650 | 2669 | // we can use the options
|
2651 |
| - await route._lazyPromise |
| 2670 | + if (route._lazyPromise) await route._lazyPromise |
2652 | 2671 | const headResult = executeHead()
|
2653 | 2672 | const head = headResult ? await headResult : undefined
|
2654 |
| - await potentialPendingMinPromise() |
| 2673 | + const pendingPromise = potentialPendingMinPromise() |
| 2674 | + if (pendingPromise) await pendingPromise |
2655 | 2675 |
|
2656 | 2676 | // Last but not least, wait for the the components
|
2657 | 2677 | // to be preloaded before we resolve the match
|
2658 |
| - await route._componentsPromise |
| 2678 | + if (route._componentsPromise) |
| 2679 | + await route._componentsPromise |
2659 | 2680 | updateMatch(matchId, (prev) => ({
|
2660 | 2681 | ...prev,
|
2661 | 2682 | error: undefined,
|
@@ -2890,33 +2911,44 @@ export class RouterCore<
|
2890 | 2911 | }
|
2891 | 2912 |
|
2892 | 2913 | loadRouteChunk = (route: AnyRoute) => {
|
2893 |
| - if (route._lazyPromise === undefined) { |
| 2914 | + if (!route._lazyLoaded && route._lazyPromise === undefined) { |
2894 | 2915 | if (route.lazyFn) {
|
2895 | 2916 | route._lazyPromise = route.lazyFn().then((lazyRoute) => {
|
2896 | 2917 | // explicitly don't copy over the lazy route's id
|
2897 | 2918 | const { id: _id, ...options } = lazyRoute.options
|
2898 | 2919 | Object.assign(route.options, options)
|
| 2920 | + route._lazyLoaded = true |
| 2921 | + route._lazyPromise = undefined // gc promise, we won't need it anymore |
2899 | 2922 | })
|
2900 | 2923 | } else {
|
2901 |
| - route._lazyPromise = Promise.resolve() |
| 2924 | + route._lazyLoaded = true |
2902 | 2925 | }
|
2903 | 2926 | }
|
2904 | 2927 |
|
2905 | 2928 | // If for some reason lazy resolves more lazy components...
|
2906 |
| - // We'll wait for that before pre attempt to preload any |
| 2929 | + // We'll wait for that before we attempt to preload the |
2907 | 2930 | // components themselves.
|
2908 |
| - if (route._componentsPromise === undefined) { |
2909 |
| - route._componentsPromise = route._lazyPromise.then(() => |
2910 |
| - Promise.all( |
2911 |
| - componentTypes.map(async (type) => { |
2912 |
| - const component = route.options[type] |
2913 |
| - if ((component as any)?.preload) { |
2914 |
| - await (component as any).preload() |
2915 |
| - } |
2916 |
| - }), |
2917 |
| - ), |
2918 |
| - ) |
| 2931 | + if (!route._componentsLoaded && route._componentsPromise === undefined) { |
| 2932 | + const loadComponents = () => { |
| 2933 | + const preloads = [] |
| 2934 | + for (const type of componentTypes) { |
| 2935 | + const preload = (route.options[type] as any)?.preload |
| 2936 | + if (preload) preloads.push(preload()) |
| 2937 | + } |
| 2938 | + if (preloads.length) |
| 2939 | + return Promise.all(preloads).then(() => { |
| 2940 | + route._componentsLoaded = true |
| 2941 | + route._componentsPromise = undefined // gc promise, we won't need it anymore |
| 2942 | + }) |
| 2943 | + route._componentsLoaded = true |
| 2944 | + route._componentsPromise = undefined // gc promise, we won't need it anymore |
| 2945 | + return |
| 2946 | + } |
| 2947 | + route._componentsPromise = route._lazyPromise |
| 2948 | + ? route._lazyPromise.then(loadComponents) |
| 2949 | + : loadComponents() |
2919 | 2950 | }
|
| 2951 | + |
2920 | 2952 | return route._componentsPromise
|
2921 | 2953 | }
|
2922 | 2954 |
|
|
0 commit comments