|
|
@ -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 {
|
|
|
|