This repository has been archived by the owner on Apr 6, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
/
preload.ts
63 lines (51 loc) · 2.1 KB
/
preload.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import type { Component } from 'vue'
import type { Router } from 'vue-router'
import { useNuxtApp } from '../nuxt'
import { useRouter } from './router'
/**
* Preload a component or components that have been globally registered.
*
* @param components Pascal-cased name or names of components to prefetch
*/
export const preloadComponents = async (components: string | string[]) => {
if (process.server) { return }
const nuxtApp = useNuxtApp()
components = Array.isArray(components) ? components : [components]
await Promise.all(components.map(name => _loadAsyncComponent(nuxtApp.vueApp._context.components[name])))
}
/**
* Prefetch a component or components that have been globally registered.
*
* @param components Pascal-cased name or names of components to prefetch
*/
export const prefetchComponents = (components: string | string[]) => {
// TODO
return preloadComponents(components)
}
// --- Internal ---
function _loadAsyncComponent (component: Component) {
if ((component as any)?.__asyncLoader && !(component as any).__asyncResolved) {
return (component as any).__asyncLoader()
}
}
export async function preloadRouteComponents (to: string, router: Router & { _routePreloaded?: Set<string>; _preloadPromises?: Array<Promise<any>> } = useRouter()): Promise<void> {
if (process.server) { return }
if (!router._routePreloaded) { router._routePreloaded = new Set() }
if (router._routePreloaded.has(to)) { return }
router._routePreloaded.add(to)
const promises = router._preloadPromises ||= []
if (promises.length > 4) {
// Defer adding new preload requests until the existing ones have resolved
return Promise.all(promises).then(() => preloadRouteComponents(to, router))
}
const components = router.resolve(to).matched
.map(component => component.components?.default)
.filter(component => typeof component === 'function')
for (const component of components) {
const promise = Promise.resolve((component as Function)())
.catch(() => {})
.finally(() => promises.splice(promises.indexOf(promise)))
promises.push(promise)
}
await Promise.all(promises)
}