feat: cache dynamic path loaders

pull/2005/head
Evan You 2 years ago
parent b075ee5be6
commit ef6ae56c95

@ -26,6 +26,8 @@ interface RouteModule {
dependencies: string[] dependencies: string[]
} }
const routeModuleCache = new Map<string, RouteModule>()
export type ResolvedRouteConfig = UserRouteConfig & { export type ResolvedRouteConfig = UserRouteConfig & {
/** /**
* the raw route (relative to src root), e.g. foo/[bar].md * the raw route (relative to src root), e.g. foo/[bar].md
@ -92,6 +94,7 @@ export const dynamicRoutesPlugin = async (
}, },
async handleHotUpdate(ctx) { async handleHotUpdate(ctx) {
routeModuleCache.delete(ctx.file)
const mods = config.dynamicRoutes.fileToModulesMap[ctx.file] const mods = config.dynamicRoutes.fileToModulesMap[ctx.file]
if (mods) { if (mods) {
// path loader module or deps updated, reset loaded routes // path loader module or deps updated, reset loaded routes
@ -118,7 +121,7 @@ export async function resolveDynamicRoutes(
for (const route of routes) { for (const route of routes) {
// locate corresponding route paths file // locate corresponding route paths file
const fullPath = path.resolve(srcDir, route) const fullPath = normalizePath(path.resolve(srcDir, route))
const jsPathsFile = fullPath.replace(/\.md$/, '.paths.js') const jsPathsFile = fullPath.replace(/\.md$/, '.paths.js')
let pathsFile = jsPathsFile let pathsFile = jsPathsFile
if (!fs.existsSync(jsPathsFile)) { if (!fs.existsSync(jsPathsFile)) {
@ -135,46 +138,46 @@ export async function resolveDynamicRoutes(
} }
// load the paths loader module // load the paths loader module
let mod: RouteModule let mod = routeModuleCache.get(pathsFile)
try { if (!mod) {
mod = (await loadConfigFromFile({} as any, pathsFile)) as RouteModule try {
} catch (e) { mod = (await loadConfigFromFile({} as any, pathsFile)) as RouteModule
console.warn(`invalid paths file export in ${pathsFile}.`) routeModuleCache.set(pathsFile, mod)
continue } catch (e) {
console.warn(`invalid paths file export in ${pathsFile}.`)
continue
}
} }
if (mod) { // this array represents the virtual modules affected by this route
// this array represents the virtual modules affected by this route const matchedModuleIds = (routeFileToModulesMap[
const matchedModuleIds = (routeFileToModulesMap[ normalizePath(path.resolve(srcDir, route))
normalizePath(path.resolve(srcDir, route)) ] = new Set())
] = new Set())
// each dependency (including the loader module itself) also point to the
// same array
for (const dep of mod.dependencies) {
// deps are resolved relative to cwd
routeFileToModulesMap[normalizePath(path.resolve(dep))] =
matchedModuleIds
}
const resolveRoute = async (): Promise<ResolvedRouteConfig[]> => { // each dependency (including the loader module itself) also point to the
const loader = mod.config.paths // same array
const paths = await (typeof loader === 'function' ? loader() : loader) for (const dep of mod.dependencies) {
return paths.map((userConfig) => { // deps are resolved relative to cwd
const resolvedPath = route.replace( routeFileToModulesMap[normalizePath(path.resolve(dep))] = matchedModuleIds
dynamicRouteRE, }
(_, key) => userConfig.params[key]
) const resolveRoute = async (): Promise<ResolvedRouteConfig[]> => {
return { const loader = mod!.config.paths
path: resolvedPath, const paths = await (typeof loader === 'function' ? loader() : loader)
fullPath: normalizePath(path.resolve(srcDir, resolvedPath)), return paths.map((userConfig) => {
route, const resolvedPath = route.replace(
...userConfig dynamicRouteRE,
} (_, key) => userConfig.params[key]
}) )
} return {
pendingResolveRoutes.push(resolveRoute()) path: resolvedPath,
fullPath: normalizePath(path.resolve(srcDir, resolvedPath)),
route,
...userConfig
}
})
} }
pendingResolveRoutes.push(resolveRoute())
} }
return { return {

Loading…
Cancel
Save