在生产中构建 Next.js 静态网站时获取错误

Posted

技术标签:

【中文标题】在生产中构建 Next.js 静态网站时获取错误【英文标题】:Fetch error when building Next.js static website in production 【发布时间】:2021-07-08 00:09:52 【问题描述】:

当我导出为生产 npm run build 时,我不理解这些错误,但是当我测试 npm run dev 时,它工作得很好。我使用 getStaticPropsgetStaticPath 从 API 路由获取。

第一次当我npm run build

FetchError: invalid json response body at https://main-website-next.vercel.app/api/products reason: Unexpected token T in JSON at position
0
    at D:\zummon\Main Website\main-website-next\node_modules\node-fetch\lib\index.js:272:32
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async getStaticPaths (D:\zummon\Main Website\main-website-next\.next\server\pages\product\[slug].js:1324:18)
    at async buildStaticPaths (D:\zummon\Main Website\main-website-next\node_modules\next\dist\build\utils.js:16:80)
    at async D:\zummon\Main Website\main-website-next\node_modules\next\dist\build\utils.js:26:612
    at async D:\zummon\Main Website\main-website-next\node_modules\next\dist\build\tracer.js:1:1441 
  type: 'invalid-json'

\pages\product\[slug]

import  assetPrefix  from '../../next.config'

export default function Page()...

export const getStaticProps = async ( params:  slug , locale ) => 
  const res = await fetch(`$assetPrefix/api/products/$slug`)
  const result = await res.json()
  const data = result.filter(item => item.locale === locale)[0]
  const  title, keywords, description  = data
  return 
    props: 
      data,
      description,
      keywords, 
      title
    
  


export const getStaticPaths = async () => 
  const res = await fetch(`$assetPrefix/api/products`)
  const result = await res.json()
  const paths = result.map(( slug, locale ) => ( params:  slug: slug , locale ))
  return 
    fallback: true,
    paths,
  

next.config.js

const isProd = process.env.NODE_ENV === 'production'

module.exports = 
  assetPrefix: isProd ? 'https://main-website-next.vercel.app' : 'http://localhost:3000',
  i18n: 
    localeDetection: false,
    locales: ['en', 'th'],
    defaultLocale: 'en',
  

API 路由

// pages/api/products/index.js
import data from '../../../data/products'
export default (req, res) => 
  res.status(200).json(data)


// pages/api/products/[slug].js
import db from '../../../data/products'
export default ( query:  slug  , res) => 
  const data = db.filter(item => item.slug === slug)
  if (data.length > 0) 
    res.status(200).json(data)
   else 
    res.status(404).json( message: `$slug not found` )
  


// ../../../data/products (data source)
module.exports = [
   locale: "en", slug: "google-sheets-combine-your-cashflow",
    title: "Combine your cashflow",
    keywords: ["Google Sheets","accounting"],
    description: "...",
  ,
    ...
]

第二次删除生产域时,我运行 npm run build 但仍然收到类似的错误

TypeError: Only absolute URLs are supported
    at getNodeRequestOptions (D:\zummon\Main Website\main-website-next\node_modules\node-fetch\lib\index.js:1305:9)
    at D:\zummon\Main Website\main-website-next\node_modules\node-fetch\lib\index.js:1410:19
    at new Promise (<anonymous>)
    at fetch (D:\zummon\Main Website\main-website-next\node_modules\node-fetch\lib\index.js:1407:9)
    at getStaticPaths (D:\zummon\Main Website\main-website-next\.next\server\pages\[slug].js:938:21)
    at buildStaticPaths (D:\zummon\Main Website\main-website-next\node_modules\next\dist\build\utils.js:16:86)
    at D:\zummon\Main Website\main-website-next\node_modules\next\dist\build\utils.js:26:618
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
    at async D:\zummon\Main Website\main-website-next\node_modules\next\dist\build\tracer.js:1:1441 
  type: 'TypeError'

删除后我的next.config.js

const isProd = process.env.NODE_ENV === 'production'

module.exports =       //remove
  assetPrefix: isProd ? '' : 'http://localhost:3000',
  i18n: 
    localeDetection: false,
    locales: ['en', 'th'],
    defaultLocale: 'en',
  

我的package.json当我npm run build脚本


  "name": "main-website-next",
  "version": "0.1.0",
  "private": true,
  "scripts": 
    "dev": "next dev",
    "build": "next build && next export",
    "start": "next start"
  ,
  "dependencies": 
    "next": "10.0.6",
    "react": "17.0.1",
    "react-dom": "17.0.1"
  

【问题讨论】:

你能分享你的 API 路由代码吗?与其调用 API 路由,不如直接在 getStaticProps/getStaticPaths 中使用数据获取逻辑。 谢谢。我在上面的问题中添加了更多信息,如果我理解正确,如果这不是你要找的,请告诉我你需要什么。我对下一个 js 真的很陌生 @juliomalves 直接使用数据获取逻辑fetch('$assetPrefix/api/products/$slug') 更改为fetch('$assetPrefix/data/products')fetch(/next/server...) 对吗?但我不知道正确的那个。另外我只是在其项目中获取数据 【参考方案1】:

您不应在getStaticProps 内调用内部 API 路由。相反,您可以直接在getStaticProps/getStaticPaths 中安全地使用您的 API 逻辑。这些只发生在服务器端,所以你可以write server-side code directly。

由于getStaticProps 只在服务器端运行,它永远不会在服务器端运行 客户端。它甚至不会包含在 JS 包中 浏览器,因此您可以编写直接的数据库查询而无需它们 发送到浏览器。

这意味着不是从 getStaticProps(它本身从外部源获取数据), 可以直接在getStaticProps写服务端代码。

此外,您的 API 路由在构建时不可用,因为此时服务器尚未启动。


这里是你的代码的一个小重构来解决这个问题。

// /pages/product/[slug]

import db from '../../../data/products'

// Remaining code..

export const getStaticProps = async ( params:  slug , locale ) => 
    const result = db.filter(item => item.slug === slug)
    const data = result.filter(item => item.locale === locale)[0]
    const  title, keywords, description  = data
    return 
        props: 
            data,
            description,
            keywords, 
            title
        
    


export const getStaticPaths = async () => 
    const paths = db.map(( slug, locale ) => ( params:  slug: slug , locale ))
    return 
        fallback: true,
        paths,
    

【讨论】:

谢谢我现在明白了更多,但是这次显示Error occurred prerendering page "/en/product/[slug]" - TypeError: Cannot read property 'contents' of undefined。但测试服务器运行正常 确保检查您的数据以避免访问undefined 触发类似错误的道具。 非常感谢,这应该已经解决了我提出的问题的错误。对于我面临的下一个错误超出范围,还有一些我可以自己修复但我还没有看到的东西 *我认为只是测试 npm run dev 工作得很好,但它显然不一样生产构建 @juliomalves 我如何执行未定义的检查? @Sushilzzz 在访问其属性之一之前检查对象不是undefined

以上是关于在生产中构建 Next.js 静态网站时获取错误的主要内容,如果未能解决你的问题,请参考以下文章

API 数据不会在生产中更新,但在本地工作

Vercel 中的 Next.js 与 Sentry - 在生产中忽略源映射

getServerSideProps 在生产中不渲染动态页面,并显示 404 错误

Taiwlind CSS:样式在生产中不加载,在开发中工作。将 Next.js 与 MDX 一起使用

尝试在生产中构建 Angular 应用程序时出现数据表错误

在生产中找不到模块“worker_threads”错误