0
Fork 0
mirror of https://github.com/withastro/astro.git synced 2025-01-06 22:10:10 -05:00

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,49 +70,46 @@ 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 (note: should these be )
// static pages if (pathname) {
if (pathname) { input.push(
allPages.push( await ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname, viteServer }).then((html) => ({
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(/^\//, ''), }))
})) );
}
// dynamic pages
else {
const staticPaths = await this.getStaticPathsForRoute(route, viteServer);
// handle RSS (TODO: improve this?)
if (staticPaths.rss && staticPaths.rss.xml) {
const rssFile = new URL(staticPaths.rss.url.replace(/^\/?/, './'), this.config.dist);
if (assets[fileURLToPath(rssFile)]) {
throw new Error(
`[getStaticPaths] RSS feed ${staticPaths.rss.url} already exists.\nUse \`rss(data, {url: '...'})\` to choose a unique, custom URL. (${route.component})`
);
}
assets[fileURLToPath(rssFile)] = staticPaths.rss.xml;
}
// TODO: throw error if conflict
for (const staticPath of staticPaths.paths) {
input.push(
await ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname: staticPath, viteServer }).then(
(html) => ({
html,
name: staticPath.replace(/\/?$/, '/index.html').replace(/^\//, ''),
})
)
); );
} }
// dynamic pages }
else { }
const staticPaths = await this.getStaticPathsForRoute(route, viteServer);
// handle RSS (TODO: improve this?)
if (staticPaths.rss && staticPaths.rss.xml) {
const rssFile = new URL(staticPaths.rss.url.replace(/^\/?/, './'), this.config.dist);
if (assets[fileURLToPath(rssFile)]) {
throw new Error(
`[getStaticPaths] RSS feed ${staticPaths.rss.url} already exists.\nUse \`rss(data, {url: '...'})\` to choose a unique, custom URL. (${route.component})`
);
}
assets[fileURLToPath(rssFile)] = staticPaths.rss.xml;
}
// TODO: throw error if conflict
staticPaths.paths.forEach((staticPath) => {
allPages.push(
ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname: staticPath, viteServer }).then(
(html) => ({
html,
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', () => {});

View file

@ -1,5 +1,5 @@
--- ---
export function getStaticPaths({paginate}) { export function getStaticPaths({ paginate }) {
if (globalThis.isCalledOnce) { if (globalThis.isCalledOnce) {
throw new Error("Can only be called once!"); throw new Error("Can only be called once!");
} }
@ -10,7 +10,7 @@ export function getStaticPaths({paginate}) {
{params: {test: 'c'}}, {params: {test: 'c'}},
]; ];
} }
const { params} = Astro.request; const { params } = Astro.request;
--- ---
<html> <html>