'next build' 期间 ECONNREFUSED。适用于 'next dev'

ECONNREFUSED during 'next build'. Works fine with 'next dev'

我有一个非常简单的 NextJS 9.3.5 项目。 目前,它有一个 pages/users 和一个 pages/api/users 可以从本地 MongoDB table

检索所有用户

它在本地使用 'next dev' 构建良好 但是,它在 'next build' 上失败,出现 ECONNREFUSED 错误

page/users

import fetch from "node-fetch"
import Link from "next/link"

export async function getStaticProps({ params }) {
  const res = await fetch(`http://${process.env.VERCEL_URL}/api/users`)
  const users = await res.json()
  return { props: { users } }
}

export default function Users({ users }) {
  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>
          <Link href="/user/[id]" as={`/user/${user._id}`}>
            <a>{user.name}</a>
          </Link>
        </li>
      ))}
    </ul>
  );
}

pages/api/users

import mongoMiddleware from "../../lib/api/mongo-middleware";
import apiHandler from "../../lib/api/api-handler";

export default mongoMiddleware(async (req, res, connection, models) => {
  const {
    method
  } = req

  apiHandler(res, method, {
    GET: (response) => {
      models.User.find({}, (error, users) => {
        if (error) {
          connection.close();
          response.status(500).json({ error });
        } else {
          connection.close();
          response.status(200).json(users);
        }
      })
    }
  });
})

纱线构建

yarn run v1.22.4
$ next build
Browserslist: caniuse-lite is outdated. Please run next command `yarn upgrade`
> Info: Loaded env from .env
Creating an optimized production build

Compiled successfully.

> Info: Loaded env from .env
Automatically optimizing pages ..
Error occurred prerendering page "/users". Read more: https://err.sh/next.js/prerender-error:
FetchError: request to http://localhost:3000/api/users failed, reason: connect ECONNREFUSED 127.0.0.1:3000

知道出了什么问题吗?特别是当它与 'next dev' ?

配合使用时

谢谢。

我几天前尝试过同样的方法但没有成功...因为当我们构建应用程序时,我们没有可用的本地主机...检查文档的这一部分 - https://nextjs.org/docs/basic-features/data-fetching#write-server-side-code-directly -那说:"You should not fetch an API route from getStaticProps..." -

(Next.js 9.3.6)

只是在 Ricardo Canelas 所说的基础上更加明确:

当您执行 next build 时,Next 遍历它检测到的可以静态构建的所有页面,即所有未定义 getServerSideProps 但可能定义 [=13= 的页面] 和 getStaticPaths.

要构建这些页面,Next 调用 getStaticPaths 来决定要构建哪些页面,然后 getStaticProps 来获取构建页面所需的实际数据。

现在,如果您在 getStaticPathsgetStaticProps 中进行了 API 调用,例如到 JSON 后端 REST 服务器,然后这将被 next build.

调用

但是,如果您已将前端和后端很好地集成到单个服务器中,则很可能您刚刚退出开发服务器 (next dev),现在正在尝试构建以查看是否有问题在部署前仍可作为健全性检查。

所以在那种情况下,构建将尝试访问您的服务器,但不会 运行ning,所以您会收到类似的错误。

正确的方法是,不要通过 REST API,而是直接从 getStaticPathsgetStaticProps 进行数据库查询。无论如何,该代码永远不会在客户端上获得 运行,只有服务器,它也比无用地访问 API,然后间接调用数据库更有效。我在这里有一个演示:https://github.com/cirosantilli/node-express-sequelize-nextjs-realworld-example-app/blob/b34c137a9d150466f3e4136b8d1feaa628a71a65/lib/article.ts#L4

export const getStaticPathsArticle: GetStaticPaths = async () => {
  return {
    fallback: true,
    paths: (await sequelize.models.Article.findAll()).map(
      article => {
        return {
          params: {
            pid: article.slug,
          }
        }
      }
    ),
  }
}

请注意在该示例中,getStaticPathsgetStaticProps(此处为重用的广义 HoC,另请参阅:)如何通过 sequelize ORM 进行直接数据库查询,并且不不对外部服务器进行任何 HTTP 调用 API.

你应该只在初始页面加载后从浏览器上的 React 组件进行客户端 API 调用(即来自 useEffect 等),而不是来自 getStaticPathsgetStaticProps。顺便说一句,请注意,如上所述:What is the difference between fallback false vs true vs blocking of getStaticPaths with and without revalidate in Next.js SSR/ISR? 尽可能减少客户端调用并在服务器上进行预渲染可大大降低应用程序的复杂性。