Bugfix: fix getStaticPaths() cache miss (#1602)
This commit is contained in:
parent
d1f42353e8
commit
e1b52506f7
4 changed files with 50 additions and 56 deletions
|
@ -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 { LogOptions } from '../logger';
|
||||
|
||||
|
@ -69,49 +70,46 @@ class AstroBuilder {
|
|||
const viteServer = await vite.createServer(viteConfig);
|
||||
|
||||
// 2. get all routes
|
||||
const allPages: Promise<{ html: string; name: string }>[] = [];
|
||||
const input: InputHTMLOptions[] = [];
|
||||
const assets: Record<string, string> = {}; // additional assets to be written
|
||||
await Promise.all(
|
||||
this.manifest.routes.map(async (route) => {
|
||||
const { pathname } = route;
|
||||
const filePath = new URL(`./${route.component}`, this.config.projectRoot);
|
||||
// static pages
|
||||
if (pathname) {
|
||||
allPages.push(
|
||||
ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname, viteServer }).then((html) => ({
|
||||
html,
|
||||
name: pathname.replace(/\/?$/, '/index.html').replace(/^\//, ''),
|
||||
}))
|
||||
for (const route of this.manifest.routes) {
|
||||
const { pathname } = route;
|
||||
const filePath = new URL(`./${route.component}`, this.config.projectRoot);
|
||||
// static pages (note: should these be )
|
||||
if (pathname) {
|
||||
input.push(
|
||||
await ssr({ astroConfig: this.config, filePath, logging, mode: 'production', origin, route, routeCache: this.routeCache, pathname, viteServer }).then((html) => ({
|
||||
html,
|
||||
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
|
||||
await vite.build({
|
||||
|
@ -177,6 +175,7 @@ class AstroBuilder {
|
|||
validateGetStaticPathsModule(mod);
|
||||
const rss = generateRssFunction(this.config.buildOptions.site, route);
|
||||
const staticPaths: GetStaticPathsResult = (await mod.getStaticPaths!({ paginate: generatePaginateFunction(route), rss: rss.generator })).flat();
|
||||
this.routeCache[route.component] = staticPaths;
|
||||
validateGetStaticPathsResult(staticPaths, this.logging);
|
||||
return {
|
||||
paths: staticPaths.map((staticPath) => staticPath.params && route.generate(staticPath.params)).filter(Boolean),
|
||||
|
|
|
@ -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.
|
||||
const renderers = await resolveRenderers(viteServer, astroConfig.renderers);
|
||||
|
||||
// 1.5. load module
|
||||
// 2. load module
|
||||
const mod = (await viteServer.ssrLoadModule(fileURLToPath(filePath))) as ComponentInstance;
|
||||
|
||||
// 2. handle dynamic routes
|
||||
// 3. handle dynamic routes
|
||||
let params: Params = {};
|
||||
let pageProps: Props = {};
|
||||
if (route && !route.pathname) {
|
||||
|
@ -91,9 +91,8 @@ export async function ssr({ astroConfig, filePath, logging, mode, origin, pathna
|
|||
}
|
||||
}
|
||||
validateGetStaticPathsModule(mod);
|
||||
routeCache[route.component] =
|
||||
routeCache[route.component] ||
|
||||
(
|
||||
if (!routeCache[route.component]) {
|
||||
routeCache[route.component] = await (
|
||||
await mod.getStaticPaths!({
|
||||
paginate: generatePaginateFunction(route),
|
||||
rss: () => {
|
||||
|
@ -101,6 +100,7 @@ export async function ssr({ astroConfig, filePath, logging, mode, origin, pathna
|
|||
},
|
||||
})
|
||||
).flat();
|
||||
}
|
||||
validateGetStaticPathsResult(routeCache[route.component], logging);
|
||||
const routePathParams: GetStaticPathsResult = routeCache[route.component];
|
||||
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 } || {};
|
||||
}
|
||||
|
||||
// 3. render page
|
||||
// 4. render page
|
||||
const Component = await mod.default;
|
||||
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);
|
||||
|
||||
// 4. modify response
|
||||
// 5. modify response
|
||||
if (mode === 'development') {
|
||||
html = await viteServer.transformIndexHtml(fileURLToPath(filePath), html, pathname);
|
||||
}
|
||||
|
||||
// 5. finish
|
||||
// 6. finish
|
||||
return html;
|
||||
} catch (e: any) {
|
||||
viteServer.ssrFixStacktrace(e);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
/**
|
||||
* UNCOMMENT: fix "Error: can only be called once!"
|
||||
import { expect } from 'chai';
|
||||
import { loadFixture } from './test-utils';
|
||||
import { loadFixture } from './test-utils.js';
|
||||
|
||||
let fixture;
|
||||
|
||||
|
@ -22,6 +20,3 @@ describe('getStaticPaths()', () => {
|
|||
expect(true).to.equal(true);
|
||||
});
|
||||
});
|
||||
*/
|
||||
|
||||
it.skip('is skipped', () => {});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
---
|
||||
export function getStaticPaths({paginate}) {
|
||||
export function getStaticPaths({ paginate }) {
|
||||
if (globalThis.isCalledOnce) {
|
||||
throw new Error("Can only be called once!");
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ export function getStaticPaths({paginate}) {
|
|||
{params: {test: 'c'}},
|
||||
];
|
||||
}
|
||||
const { params} = Astro.request;
|
||||
const { params } = Astro.request;
|
||||
---
|
||||
|
||||
<html>
|
||||
|
|
Loading…
Reference in a new issue