diff --git a/packages/astro/src/core/build/generate.ts b/packages/astro/src/core/build/generate.ts index 72339a680b..145fca9fd3 100644 --- a/packages/astro/src/core/build/generate.ts +++ b/packages/astro/src/core/build/generate.ts @@ -305,32 +305,27 @@ async function getPathsForRoute( builtPaths.add(pageData.route.pathname); } else { const route = pageData.route; - const result = await callGetStaticPaths({ + const staticPaths = await callGetStaticPaths({ mod, - route: pageData.route, + route, + routeCache: opts.routeCache, isValidate: false, logging: opts.logging, ssr: isServerLikeOutput(opts.settings.config), - }) - .then((_result) => { - const label = _result.staticPaths.length === 1 ? 'page' : 'pages'; - debug( - 'build', - `├── ${colors.bold(colors.green('✔'))} ${route.component} → ${colors.magenta( - `[${_result.staticPaths.length} ${label}]` - )}` - ); - return _result; - }) - .catch((err) => { - debug('build', `├── ${colors.bold(colors.red('✗'))} ${route.component}`); - throw err; - }); + }).catch((err) => { + debug('build', `├── ${colors.bold(colors.red('✗'))} ${route.component}`); + throw err; + }); - // Save the route cache so it doesn't get called again - opts.routeCache.set(route, result); + const label = staticPaths.length === 1 ? 'page' : 'pages'; + debug( + 'build', + `├── ${colors.bold(colors.green('✔'))} ${route.component} → ${colors.magenta( + `[${staticPaths.length} ${label}]` + )}` + ); - paths = result.staticPaths + paths = staticPaths .map((staticPath) => { try { return route.generate(staticPath.params); diff --git a/packages/astro/src/core/render/params-and-props.ts b/packages/astro/src/core/render/params-and-props.ts index 33b50eac94..9154a9ba93 100644 --- a/packages/astro/src/core/render/params-and-props.ts +++ b/packages/astro/src/core/render/params-and-props.ts @@ -27,17 +27,18 @@ export async function getParamsAndProps(opts: GetParamsAndPropsOptions): Promise validatePrerenderEndpointCollision(route, mod, params); - let routeCacheEntry = routeCache.get(route); // During build, the route cache should already be populated. // During development, the route cache is filled on-demand and may be empty. - // TODO(fks): Can we refactor getParamsAndProps() to receive routeCacheEntry - // as a prop, and not do a live lookup/populate inside this lower function call. - if (!routeCacheEntry) { - routeCacheEntry = await callGetStaticPaths({ mod, route, isValidate: true, logging, ssr }); - routeCache.set(route, routeCacheEntry); - } + const staticPaths = await callGetStaticPaths({ + mod, + route, + routeCache, + isValidate: true, + logging, + ssr, + }); - const matchedStaticPath = findPathItemByKey(routeCacheEntry.staticPaths, params, route); + const matchedStaticPath = findPathItemByKey(staticPaths, params, route); if (!matchedStaticPath && (ssr ? route.prerender : true)) { throw new AstroError({ ...AstroErrorData.NoMatchingStaticPathFound, diff --git a/packages/astro/src/core/render/route-cache.ts b/packages/astro/src/core/render/route-cache.ts index 227928267d..787b345518 100644 --- a/packages/astro/src/core/render/route-cache.ts +++ b/packages/astro/src/core/render/route-cache.ts @@ -17,23 +17,32 @@ import { generatePaginateFunction } from './paginate.js'; interface CallGetStaticPathsOptions { mod: ComponentInstance; route: RouteData; + routeCache: RouteCache; isValidate: boolean; logging: LogOptions; ssr: boolean; } export async function callGetStaticPaths({ - isValidate, - logging, mod, route, + routeCache, + isValidate, + logging, ssr, -}: CallGetStaticPathsOptions): Promise { +}: CallGetStaticPathsOptions): Promise { + const cached = routeCache.get(route); + if (cached?.staticPaths) return cached.staticPaths; + validateDynamicRouteModule(mod, { ssr, logging, route }); + // No static paths in SSR mode. Return an empty RouteCacheEntry. if (ssr && !route.prerender) { - return { staticPaths: Object.assign([], { keyed: new Map() }) }; + const entry: GetStaticPathsResultKeyed = Object.assign([], { keyed: new Map() }); + routeCache.set(route, { ...cached, staticPaths: entry }); + return entry; } + // Add a check here to make TypeScript happy. // This is already checked in validateDynamicRouteModule(). if (!mod.getStaticPaths) { @@ -66,12 +75,11 @@ export async function callGetStaticPaths({ keyedStaticPaths.keyed.set(paramsKey, sp); } - return { - staticPaths: keyedStaticPaths, - }; + routeCache.set(route, { ...cached, staticPaths: keyedStaticPaths }); + return keyedStaticPaths; } -export interface RouteCacheEntry { +interface RouteCacheEntry { staticPaths: GetStaticPathsResultKeyed; } @@ -99,7 +107,7 @@ export class RouteCache { // NOTE: This shouldn't be called on an already-cached component. // Warn here so that an unexpected double-call of getStaticPaths() // isn't invisible and developer can track down the issue. - if (this.mode === 'production' && this.cache[route.component]) { + if (this.mode === 'production' && this.cache[route.component]?.staticPaths) { warn( this.logging, 'routeCache',