Skip to content

Commit

Permalink
Handle getStaticPaths with prerendered pages (#5734)
Browse files Browse the repository at this point in the history
* fix(#5661): ensure getStaticPaths is correctly handled for prerendered pages

* test: add prerender getStaticPaths cases

* chore: add changeset

* test: add props to test suite

* chore: update lockfile

Co-authored-by: Nate Moore <nate@astro.build>
  • Loading branch information
natemoo-re and natemoo-re committed Jan 4, 2023
1 parent cc4606d commit 55cea0a
Show file tree
Hide file tree
Showing 18 changed files with 408 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .changeset/lemon-eagles-worry.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Fix `prerender` when used with `getStaticPaths`
1 change: 1 addition & 0 deletions packages/astro/src/@types/astro.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1004,6 +1004,7 @@ export type AsyncRendererComponentFn<U> = (
export interface ComponentInstance {
default: AstroComponentFactory;
css?: string[];
prerender?: boolean;
getStaticPaths?: (options: GetStaticPathsOptions) => GetStaticPathsResult;
}

Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/build/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ async function getPathsForRoute(
route: pageData.route,
isValidate: false,
logging: opts.logging,
ssr: false,
ssr: opts.settings.config.output === 'server',
})
.then((_result) => {
const label = _result.staticPaths.length === 1 ? 'page' : 'pages';
Expand Down
2 changes: 2 additions & 0 deletions packages/astro/src/core/build/vite-plugin-ssr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,8 @@ function buildManifest(
const joinBase = (pth: string) => (bareBase ? bareBase + '/' + pth : pth);

for (const pageData of eachPrerenderedPageData(internals)) {
if (!pageData.route.pathname) continue;

const outFolder = getOutFolder(
opts.settings.config,
pageData.route.pathname!,
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/errors/errors-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,7 @@ but ${plural ? 'none were.' : 'it was not.'} able to server-side render \`${comp
'`getStaticPaths()` function is required for dynamic routes. Make sure that you `export` a `getStaticPaths` function from your dynamic route.',
hint: `See https://docs.astro.build/en/core-concepts/routing/#dynamic-routes for more information on dynamic routes.
Alternatively, set \`output: "server"\` in your Astro config file to switch to a non-static server build.
Alternatively, set \`output: "server"\` in your Astro config file to switch to a non-static server build. This error can also occur if using \`export const prerender = true;\`.
See https://docs.astro.build/en/guides/server-side-rendering/ for more information on non-static rendering.`,
},
/**
Expand Down
2 changes: 1 addition & 1 deletion packages/astro/src/core/render/route-cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export async function callGetStaticPaths({
}: CallGetStaticPathsOptions): Promise<RouteCacheEntry> {
validateDynamicRouteModule(mod, { ssr, logging, route });
// No static paths in SSR mode. Return an empty RouteCacheEntry.
if (ssr) {
if (ssr && !mod.prerender) {
return { staticPaths: Object.assign([], { keyed: new Map() }) };
}
// Add a check here to make TypeScript happy.
Expand Down
4 changes: 2 additions & 2 deletions packages/astro/src/core/routing/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,10 @@ export function validateDynamicRouteModule(
route: RouteData;
}
) {
if (ssr && mod.getStaticPaths) {
if (ssr && mod.getStaticPaths && !mod.prerender) {
warn(logging, 'getStaticPaths', 'getStaticPaths() is ignored when "output: server" is set.');
}
if (!ssr && !mod.getStaticPaths) {
if ((!ssr || mod.prerender) && !mod.getStaticPaths) {
throw new AstroError({
...AstroErrorData.GetStaticPathsRequired,
location: { file: route.component },
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "@test/ssr-prerender-get-static-paths",
"version": "0.0.0",
"private": true,
"dependencies": {
"astro": "workspace:*"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
export function getStaticPaths({ paginate }) {
if (globalThis.isCalledOnce) {
throw new Error("Can only be called once!");
}
globalThis.isCalledOnce = true;
return [
{params: {calledTwiceTest: 'a'}},
{params: {calledTwiceTest: 'b'}},
{params: {calledTwiceTest: 'c'}},
];
}
export const prerender = true;
const { params } = Astro;
---

<html>
<head>
<title>Page {params.calledTwiceTest}</title>
</head>
<body></body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
---
export async function getStaticPaths() {
return [
{ params: { year: '2022', slug: 'post-1' } },
{ params: { year: 2022, slug: 'post-2' } },
{ params: { slug: 'post-2', year: '2022' } },
]
}
export const prerender = true;
const { year, slug } = Astro.params
---

<html>
<head>
<title>{year} | {slug}</title>
</head>
<body></body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
export const prerender = true;

export async function getStaticPaths() {
return [
{ params: { slug: 'thing1' } },
{ params: { slug: 'thing2' } }
];
}

export async function get() {
return {
body: JSON.stringify({
title: '[slug]'
}, null, 4)
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
export async function getStaticPaths() {
return [
{
params: { name: 'tacos' },
props: { yum: 10 },
},
{
params: { name: 'potatoes' },
props: { yum: 7 },
},
{
params: { name: 'spaghetti' },
props: { yum: 5 },
}
]
}
export const prerender = true;
const { yum } = Astro.props;
---

<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Food</title>
</head>
<body>
<p id="url">{ Astro.url.pathname }</p>
<p id="props">{ yum }</p>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
---
export function getStaticPaths() {
return [
[ { params: {slug: "slug1"} } ],
[ { params: {slug: "slug2"} } ],
]
}
export const prerender = true;
---
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
---
export function getStaticPaths() {
return [{
params: { pizza: 'papa-johns' },
}, {
params: { pizza: 'dominos' },
}, {
params: { pizza: 'grimaldis/new-york' },
}]
}
export const prerender = true;
const { pizza } = Astro.params
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>{pizza ?? 'The landing page'}</title>
</head>
<body>
<h1>Welcome to {pizza ?? 'The landing page'}</h1>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
---
export function getStaticPaths() {
return [{
params: { cheese: 'mozzarella', topping: 'pepperoni' },
}, {
params: { cheese: 'provolone', topping: 'sausage' },
}]
}
export const prerender = true;
const { cheese, topping } = Astro.params
---
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>{cheese}</title>
</head>
<body>
<h1>🍕 It's pizza time</h1>
<p>{cheese}-{topping}</p>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
---
export async function getStaticPaths() {
return [
{
params: { page: 1 },
},
{
params: { page: 2 },
},
{
params: { page: 3 }
}
]
};
export const prerender = true;
const { page } = Astro.params
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
---

<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>Posts Page {page}</title>
<link rel="canonical" href={canonicalURL.href}>
</head>
<body>
<h1>Welcome to page {page}</h1>
</body>
</html>

0 comments on commit 55cea0a

Please sign in to comment.