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