NextJS 14 App Router中generateStaticParams未生成静态文件
我正在使用NextJS 14的App Router,通过配置output: "export"生成生产环境静态文件。在/leslessives/[id]/page.tsx中用generateStaticParams函数为动态路由导出静态文件,但构建完成后,out文件夹里找不到对应的文件。
构建过程结果
✓ Generating static pages (18/18) ✓ Finalizing page optimization Route (app) Size First Load JS ┌ ○ / 99.1 kB 302 kB ├ ○ /_not-found 870 B 85 kB ├ ○ /api/health 0 B 0 B ├ ○ /conditions-generales-d-utilisation 1.29 kB 98.6 kB ├ ○ /ideesetconseils 174 B 89.3 kB ├ ○ /lamarque 25.3 kB 170 kB ├ ○ /leslessives 2.32 kB 112 kB ├ ● /leslessives/[id] 7.46 kB 159 kB ├ ├ /leslessives/9 ├ ├ /leslessives/39 ├ ├ /leslessives/23 ├ └ [+2 more paths] ├ ○ /mentions-legales 1.29 kB 98.6 kB ├ ○ /politique-de-confidentialite 1.29 kB 98.6 kB └ ○ /reglement 1.19 kB 98.5 kB + First Load JS shared by all 84.2 kB ├ chunks/472-31075e7adf75b534.js 28.9 kB ├ chunks/fd9d1056-986279e933d4449d.js 53.3 kB ├ chunks/main-app-ff928e97f8293f3b.js 219 B └ chunks/webpack-f76f5768c7c52192.js 1.78 kB
/leslessives/[id]/page.tsx代码
// Generate static parameters export async function generateStaticParams() { try { // Fetch product data from the API const { data: products } = await getStrapiData("/api/products") // Map product IDs to static paths return products.map((product) => ({ id: product.id.toString(), })) } catch (error) { console.error("Error fetching product IDs:", error) return [] // Return an empty array in case of an error } } // Multiple versions of this page will be statically generated // using the `params` returned by `generateStaticParams` export default async function Web({ params }: { params: { id: string } }) { const { id } = params const product = await getProductById(`/api/products/${id}`) console.log(product) return ( <> </> ) }
next.config.mjs代码
import withBundleAnalyzer from "@next/bundle-analyzer" import withPlugins from "next-compose-plugins" import { env } from "./env.mjs" /** * @type {import('next').NextConfig} */ const config = withPlugins([[withBundleAnalyzer({ enabled: env.ANALYZE })]], { output: "export", trailingSlash: true, reactStrictMode: true, experimental: { instrumentationHook: true }, images: { unoptimized: true, remotePatterns: [ { protocol: "https", hostname: "admin.heritagefrance.fr", port: "", pathname: "/uploads/**/*", }, { protocol: "http", hostname: "127.0.0.1", port: "1337", pathname: "/uploads/**/*", }, { protocol: "https", hostname: "placehold.co", }, ], }, env: { NEXT_PUBLIC_STRAPI_URL: "https://admin.heritagefrance.fr/api", NEXT_STRAPI_MEDIA_URL: "https://admin.heritagefrance.fr", HOTJAR_ID: process.env.HOTJAR_ID, IMPROOV_URL: process.env.IMPROOV_URL, IMPROOV_TOKEN: process.env.IMPROOV_TOKEN, }, webpack: (config) => { config.resolve.alias.canvas = false return config }, }) export default config console.log("Next.js config:", config)
解决方案
核对文件路径结构
从构建输出看,动态路由是/leslessives/[id],所以你的页面文件必须放在app/leslessives/[id]/page.tsx,而非根目录的[id]/page.tsx,路径不匹配会导致Next.js无法生成对应静态文件。检查静态文件的生成结构
你设置了trailingSlash: true,生成的静态文件会是out/leslessives/{id}/index.html的格式(比如out/leslessives/9/index.html),而非直接的{id}.html文件,去对应子目录下找index.html即可。验证
generateStaticParams的返回值
在generateStaticParams中添加日志,确认返回的参数数组是否正确包含所有产品ID:console.log("生成的静态参数:", products.map(p => ({id: p.id.toString()})))构建时查看控制台输出,确保没有返回空数组或错误ID。
排查页面数据获取错误
页面组件中的getProductById如果抛出异常,会导致对应路径的静态文件无法生成。添加错误捕获逻辑:export default async function Web({ params }: { params: { id: string } }) { const { id } = params let product = null try { product = await getProductById(`/api/products/${id}`) console.log(product) } catch (err) { console.error(`获取产品${id}失败:`, err) // 可返回错误页面或默认内容 } return ( <> {/* 页面内容 */} </> ) }确保每个ID对应的产品数据都能正常获取,无404或其他异常。
清理缓存后重新构建
删除.next和out文件夹,再执行npm run build,避免缓存导致的异常。
内容的提问来源于stack exchange,提问作者Rom-888

