【问题标题】:Fetch error when building Next.js static website in production在生产中构建 Next.js 静态网站时获取错误
【发布时间】: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...) 对吗?但我不知道正确的那个。另外我只是在其项目中获取数据

标签: javascript node.js next.js


【解决方案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
猜你喜欢
  • 2022-06-27
  • 2021-04-19
  • 2020-12-27
  • 2019-10-28
相关资源
最近更新 更多