Open meds opened 10 months ago
This is not a bug. You need to return the array with an object with a parameter that indicates the dynamic route. Ex:
export function generateStaticParams() {
return [{ id: "test" }];
}
export default async function Page(props: any) {
return <div>{JSON.stringify(props.params)}</div>;
}
> yarn next info
Operating System:
Platform: linux
Arch: x64
Version: #1 SMP PREEMPT_DYNAMIC Mon Jan 1 20:31:07 UTC 2024
Binaries:
Node: 18.17.0
npm: 9.6.7
Yarn: 4.0.2
pnpm: N/A
Relevant Packages:
next: 14.0.4
eslint-config-next: 14.0.4
react: 18.2.0
react-dom: 18.2.0
typescript: 5.3.3
Next.js Config:
output: N/A
// apps/web/src/app/p/[slug]/page.tsx
import { DocumentRenderer } from '@keystatic/core/renderer';
import { NormalPageTemplate } from '@zenobius/ui-web-pagetemplates-normalpage';
import { Site } from '@zenobius/ui-web-components-sitelayout';
import { CmsContent } from '@zenobius/ui-web-components-cmscontent'
import { ContentStore } from '../../../services/ContentStore';
export default async function Post({ params }: {
params: { slug: string }
}) {
const post = await ContentStore.collections.pages.read(params.slug);
if (!post) {
return (
<Site>
<h1>Not found</h1>
</Site>
)
}
return (
<Site>
<NormalPageTemplate
title={post.title}
stage={post.stage}
>
<CmsContent>
<DocumentRenderer document={await post.content()} />
</CmsContent>
</NormalPageTemplate>
</Site>
);
}
type Params = {
slug: string;
}
export async function generateStaticParams(): Promise<Params[]> {
const pages = await ContentStore.collections.pages.all();
if (!pages) {
return [{ slug: 'not-found' }];
}
return pages.map(page => ({
slug: page.slug
}));
}
then
zenobi.us on git feat/keystatic [x!?] via nodejs v18.17.0 took 15s
x yarn nx build web
> nx run web:build:production
▲ Next.js 14.0.4
- Experiments (use at your own risk):
· typedRoutes
Creating an optimized production build ...
✓ Compiled successfully
Skipping linting
Checking validity of types ...
Collecting page data ...
> Build error occurred
Error: Page "/p/[slug]" is missing "generateStaticParams()" so it cannot be used with "output: export" config.
at /mnt/Store/Projects/Mine/Github/zenobi.us/node_modules/next/dist/build/index.js:1012:59
at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
at async Span.traceAsyncFn (/mnt/Store/Projects/Mine/Github/zenobi.us/node_modules/next/dist/trace/trace.js:147:20)
at async Promise.all (index 8)
at async /mnt/Store/Projects/Mine/Github/zenobi.us/node_modules/next/dist/build/index.js:892:17
at async Span.traceAsyncFn (/mnt/Store/Projects/Mine/Github/zenobi.us/node_modules/next/dist/trace/trace.js:147:20)
at async /mnt/Store/Projects/Mine/Github/zenobi.us/node_modules/next/dist/build/index.js:829:124
at async Span.traceAsyncFn (/mnt/Store/Projects/Mine/Github/zenobi.us/node_modules/next/dist/trace/trace.js:147:20)
at async build (/mnt/Store/Projects/Mine/Github/zenobi.us/node_modules/next/dist/build/index.js:187:29)
at async main (/mnt/Store/Projects/Mine/Github/zenobi.us/node_modules/next/dist/bin/next:157:5)
Error occurred while trying to run the build command
1
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
> NX Ran target build for project web (8s)
✖ 1/1 failed
✔ 0/1 succeeded [0 read from cache]
it can happen when you're "thing" only returns empty results.
so make sure you're checking for length too:
type Params = {
slug: string;
}
export async function generateStaticParams(): Promise<Params[]> {
const pages = await ContentStore.collections.pages.all();
if (!pages || pages.length === 0) {
return [{ slug: 'not-found' }];
}
return pages.map(page => ({
slug: page.slug
}));
}
now
zenobi.us on git feat/keystatic [x!?] via nodejs v18.17.0 took 7s
x yarn nx build web
> nx run web:build:production
▲ Next.js 14.0.4
- Experiments (use at your own risk):
· typedRoutes
Creating an optimized production build ...
✓ Compiled successfully
Skipping linting
Checking validity of types ...
Collecting page data ...
Generating static pages (0/14) ...
Generating static pages (3/14)
Generating static pages (6/14)
Generating static pages (10/14)
✓ Generating static pages (14/14)
Finalizing page optimization ...
Collecting build traces ...
Route (app) Size First Load JS
┌ ○ / 1.24 kB 83.5 kB
├ ○ /_not-found 916 B 83.2 kB
├ ○ /b 8.44 kB 104 kB
├ ● /b/[slug] 1.69 kB 97.5 kB
├ ├ /b/2014-05-01-bust-the-cache-out-of-it
├ ├ /b/2014-05-11-wintersmithplugin-externalmounter
├ ├ /b/2016-01-01-automation-what-i-have-learnt
├ └ [+3 more paths]
├ ○ /me 1.6 kB 92.4 kB
└ ● /p/[slug] 1.6 kB 92.4 kB
└ /p/not-found
+ First Load JS shared by all 82.3 kB
├ chunks/1dd3208c-db9eec636a334a07.js 53.3 kB
├ chunks/53-f2b3fdbbf4bc8eab.js 26.8 kB
├ chunks/main-app-b7bee2021889a694.js 267 B
└ chunks/webpack-1c9d7ab86a1268c6.js 1.89 kB
○ (Static) prerendered as static content
● (SSG) prerendered as static HTML (uses getStaticProps)
————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
> NX Successfully ran target build for project web (14s)
我懂了,你可以根据环境变量或者一些条件判断来按需打包自己需要的页面,不需要的统统打包到指定的垃圾桶目录,例如:'not-found' (I see. You can package the pages you need based on environment variables or some criteria. Everything that is not needed is packed into the designated bin directory, For example: 'not-found')
// apps/web/src/app/p/[slug]/page.tsx
export async function generateStaticParams(): Promise<Params[]> {
const pages = await ContentStore.collections.pages.all();
if (!pages || pages.length === 0) {
return [{ slug: 'not-found' }];
}
return pages.map(page => ({
slug: page.slug
}));
}
这样打包出来的out里面会有一个 “not-found” 垃圾桶目录,可以在build脚本里面手动删了这个目录就好了! (In this way, there will be a "not-found" garbage bin directory inside the packaged out, then you can manually delete this directory in the build script!)
This is not a bug. You need to return the array with an object with a parameter that indicates the dynamic route. Ex:
export function generateStaticParams() { return [{ id: "test" }]; } export default async function Page(props: any) { return <div>{JSON.stringify(props.params)}</div>; }
So I have a situation where I have no idea what the value will end up being. I cannot query a collection or DB or whatever. It is truly dynamic. How do I tell it that it needs to just pull it from the URL path on page load? The documentation is VERY unclear on this.
Link to the code that reproduces this issue
https://github.com/meds/nextjs-broken-export
To Reproduce
pnpm build
Current vs. Expected behavior
I expected nextjs to build and export to an output directory with static files.
Instead I got an error:
Error: Page "/test/[id]" is missing "generateStaticParams()" so it cannot be used with "output: export" config.
Verify canary release
Provide environment information
Which area(s) are affected? (Select all that apply)
App Router, Static HTML Export (output: "export")
Additional context
No response