Bugfix: fix getStaticPaths() cache miss (#1602)

This commit is contained in:
Drew Powers 2021-10-20 08:45:52 -06:00 committed by Drew Powers
parent d1f42353e8
commit e1b52506f7
4 changed files with 50 additions and 56 deletions

View file

@ -1,3 +1,4 @@
import type { InputHTMLOptions } from '@web/rollup-plugin-html';
import type { AstroConfig, ComponentInstance, GetStaticPathsResult, ManifestData, RouteCache, RouteData, RSSResult } from '../../@types/astro-core'; import type { AstroConfig, ComponentInstance, GetStaticPathsResult, ManifestData, RouteCache, RouteData, RSSResult } from '../../@types/astro-core';
import type { LogOptions } from '../logger'; import type { LogOptions } from '../logger';
@ -69,16 +70,15 @@ class AstroBuilder {
const viteServer = await vite.createServer(viteConfig); const viteServer = await vite.createServer(viteConfig);
// 2. get all routes // 2. get all routes
const allPages: Promise<{ html: string; name: string }>[] = []; const input: InputHTMLOptions[] = [];
const assets: Record<string, string> = {}; // additional assets to be written const assets: Record<string, string> = {}; // additional assets to be written
await Promise.all( for (const route of this.manifest.routes) {
this.manifest.routes.map(async (route) => {
const { pathname } = route; const { pathname } = route;
const filePath = new URL(`./${route.component}`, this.config.projectRoot); const filePath = new URL(`./${route.component}`, this.config.projectRoot);
// static pages // static pages (note: should these be )
if (pathname) { if (pathname) {
allPages.push( input.push(
ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname, viteServer }).then((html) => ({ await ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname, viteServer }).then((html) => ({
html, html,
name: pathname.replace(/\/?$/, '/index.html').replace(/^\//, ''), name: pathname.replace(/\/?$/, '/index.html').replace(/^\//, ''),
})) }))
@ -98,20 +98,18 @@ class AstroBuilder {
assets[fileURLToPath(rssFile)] = staticPaths.rss.xml; assets[fileURLToPath(rssFile)] = staticPaths.rss.xml;
} }
// TODO: throw error if conflict // TODO: throw error if conflict
staticPaths.paths.forEach((staticPath) => { for (const staticPath of staticPaths.paths) {
allPages.push( input.push(
ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname: staticPath, viteServer }).then( await ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname: staticPath, viteServer }).then(
(html) => ({ (html) => ({
html, html,
name: staticPath.replace(/\/?$/, '/index.html').replace(/^\//, ''), name: staticPath.replace(/\/?$/, '/index.html').replace(/^\//, ''),
}) })
) )
); );
});
} }
}) }
); }
const input = await Promise.all(allPages);
// 3. build with Vite // 3. build with Vite
await vite.build({ await vite.build({
@ -177,6 +175,7 @@ class AstroBuilder {
validateGetStaticPathsModule(mod); validateGetStaticPathsModule(mod);
const rss = generateRssFunction(this.config.buildOptions.site, route); const rss = generateRssFunction(this.config.buildOptions.site, route);
const staticPaths: GetStaticPathsResult = (await mod.getStaticPaths!({ paginate: generatePaginateFunction(route), rss: rss.generator })).flat(); const staticPaths: GetStaticPathsResult = (await mod.getStaticPaths!({ paginate: generatePaginateFunction(route), rss: rss.generator })).flat();
this.routeCache[route.component] = staticPaths;
validateGetStaticPathsResult(staticPaths, this.logging); validateGetStaticPathsResult(staticPaths, this.logging);
return { return {
paths: staticPaths.map((staticPath) => staticPath.params && route.generate(staticPath.params)).filter(Boolean), paths: staticPaths.map((staticPath) => staticPath.params && route.generate(staticPath.params)).filter(Boolean),

View file

@ -77,10 +77,10 @@ export async function ssr({ astroConfig, filePath, logging, mode, origin, pathna
// Important this happens before load module in case a renderer provides polyfills. // Important this happens before load module in case a renderer provides polyfills.
const renderers = await resolveRenderers(viteServer, astroConfig.renderers); const renderers = await resolveRenderers(viteServer, astroConfig.renderers);
// 1.5. load module // 2. load module
const mod = (await viteServer.ssrLoadModule(fileURLToPath(filePath))) as ComponentInstance; const mod = (await viteServer.ssrLoadModule(fileURLToPath(filePath))) as ComponentInstance;
// 2. handle dynamic routes // 3. handle dynamic routes
let params: Params = {}; let params: Params = {};
let pageProps: Props = {}; let pageProps: Props = {};
if (route && !route.pathname) { if (route && !route.pathname) {
@ -91,9 +91,8 @@ export async function ssr({ astroConfig, filePath, logging, mode, origin, pathna
} }
} }
validateGetStaticPathsModule(mod); validateGetStaticPathsModule(mod);
routeCache[route.component] = if (!routeCache[route.component]) {
routeCache[route.component] || routeCache[route.component] = await (
(
await mod.getStaticPaths!({ await mod.getStaticPaths!({
paginate: generatePaginateFunction(route), paginate: generatePaginateFunction(route),
rss: () => { rss: () => {
@ -101,6 +100,7 @@ export async function ssr({ astroConfig, filePath, logging, mode, origin, pathna
}, },
}) })
).flat(); ).flat();
}
validateGetStaticPathsResult(routeCache[route.component], logging); validateGetStaticPathsResult(routeCache[route.component], logging);
const routePathParams: GetStaticPathsResult = routeCache[route.component]; const routePathParams: GetStaticPathsResult = routeCache[route.component];
const matchedStaticPath = routePathParams.find(({ params: _params }) => JSON.stringify(_params) === JSON.stringify(params)); const matchedStaticPath = routePathParams.find(({ params: _params }) => JSON.stringify(_params) === JSON.stringify(params));
@ -110,7 +110,7 @@ export async function ssr({ astroConfig, filePath, logging, mode, origin, pathna
pageProps = { ...matchedStaticPath.props } || {}; pageProps = { ...matchedStaticPath.props } || {};
} }
// 3. render page // 4. render page
const Component = await mod.default; const Component = await mod.default;
if (!Component) throw new Error(`Expected an exported Astro component but received typeof ${typeof Component}`); if (!Component) throw new Error(`Expected an exported Astro component but received typeof ${typeof Component}`);
@ -144,12 +144,12 @@ export async function ssr({ astroConfig, filePath, logging, mode, origin, pathna
let html = await renderPage(result, Component, pageProps, null); let html = await renderPage(result, Component, pageProps, null);
// 4. modify response // 5. modify response
if (mode === 'development') { if (mode === 'development') {
html = await viteServer.transformIndexHtml(fileURLToPath(filePath), html, pathname); html = await viteServer.transformIndexHtml(fileURLToPath(filePath), html, pathname);
} }
// 5. finish // 6. finish
return html; return html;
} catch (e: any) { } catch (e: any) {
viteServer.ssrFixStacktrace(e); viteServer.ssrFixStacktrace(e);

View file

@ -1,7 +1,5 @@
/**
* UNCOMMENT: fix "Error: can only be called once!"
import { expect } from 'chai'; import { expect } from 'chai';
import { loadFixture } from './test-utils'; import { loadFixture } from './test-utils.js';
let fixture; let fixture;
@ -22,6 +20,3 @@ describe('getStaticPaths()', () => {
expect(true).to.equal(true); expect(true).to.equal(true);
}); });
}); });
*/
it.skip('is skipped', () => {});