You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Next.js+GraphCMS项目Vercel构建失败,报document未定义错误

Next.js + GraphCMS 部署Vercel构建崩溃排查

错误信息

TypeError: Cannot read properties of undefined (reading 'document')
at Object.parseRequestExtendedArgs (/vercel/path0/node_modules/graphql-request/dist/parseArgs.js:37:25)
at /vercel/path0/node_modules/graphql-request/dist/index.js:422:42
at step (/vercel/path0/node_modules/graphql-request/dist/index.js:63:23)
at Object.next (/vercel/path0/node_modules/graphql-request/dist/index.js:44:53)
at /vercel/path0/node_modules/graphql-request/dist/index.js:38:71
at new Promise ()
at __awaiter (/vercel/path0/node_modules/graphql-request/dist/index.js:34:12)
at request (/vercel/path0/node_modules/graphql-request/dist/index.js:418:12)
at getPosts (/vercel/path0/.next/server/chunks/104.js:1143:82)
at getStaticPaths (/vercel/path0/.next/server/pages/post/[slug].js:98:86)
Build error occurred
Error: Failed to collect page data for /post/[slug]
at /vercel/path0/node_modules/next/dist/build/utils.js:959:15
at processTicksAndRejections (node:internal/process/task_queues:96:5) {
type: 'Error'
}
error Command failed with exit code 1.

问题背景

本地环境可正常构建运行,但部署至Vercel时构建崩溃,错误触发链为getStaticPaths调用getPosts,进而调用graphql-request时尝试访问浏览器专属的document对象。

相关代码

pages/post/[slug].js

import React from "react";
import { useRouter } from "next/router";

import {
  PostDetail,
  Categories,
  PostWidget,
  Author,
  Comments,
  CommentsForm,
  Loader,
} from "../../components";
import { getPosts, getPostDetails } from "../../services";
import { AdjacentPosts } from "../../sections";

const PostDetails = ({ post }) => {
  const router = useRouter();

  if (router.isFallback) {
    return <Loader />;
  }

  return (
    <>
      <div className="container mx-auto px-10 mb-8">
        <div className="grid grid-cols-1 lg:grid-cols-12 gap-12">
          <div className="col-span-1 lg:col-span-8">
            <PostDetail post={post} />
            <Author author={post.author} />
            <AdjacentPosts slug={post.slug} createdAt={post.createdAt} />
            <CommentsForm slug={post.slug} />
            <Comments slug={post.slug} />
          </div>
          <div className="col-span-1 lg:col-span-4">
            <div className="relative lg:sticky top-8">
              <PostWidget
                slug={post.slug}
                categories={post.categories.map((category) => category.slug)}
              />
              <Categories />
            </div>
          </div>
        </div>
      </div>
    </>
  );
};
export default PostDetails;

// Fetch data at build time
export async function getStaticProps({ params }) {
  const data = await getPostDetails(params.slug);
  return {
    props: {
      post: data,
    },
  };
}

// Specify dynamic routes to pre-render pages based on data.
// The HTML is generated at build time and will be reused on each request.
export async function getStaticPaths() {
  const posts = await getPosts();

  return {
    paths: posts.map(({ node: { slug } }) => ({ params: { slug } })),
    fallback: false,
  };
}

getPosts 查询

export const getPosts = async () => {
  const query = gql`
    query MyQuery {
      postsConnection {
        edges {
          cursor
          node {
            author {
              bio
              name
              id
              photo {
                url
              }
            }
            createdAt
            slug
            title
            excerpt
            displayedDate
            featuredImage {
              url
            }
            categories {
              name
              slug
            }
          }
        }
      }
    }
  `;

  const result = await request(graphqlAPI, query);

  return result.postsConnection.edges;
};

getPostDetails 查询

export const getPostDetails = async (slug) => {
  const query = gql`
    query GetPostDetails($slug: String!) {
      post(where: { slug: $slug }) {
        title
        excerpt
        featuredImage {
          url
          id
        }
        author {
          name
          bio
          photo {
            url
          }
        }
        createdAt
        slug
        content {
          raw
        }
        categories {
          name
          slug
        }
        displayedDate
      }
    }
  `;

  const result = await request(graphqlAPI, query, { slug });

  return result.post;
};

排查方案

1. 环境变量验证

确认Vercel项目设置的环境变量中,graphqlAPI对应的GraphCMS端点以及API密钥已正确配置,且勾选了"在构建时暴露"选项。本地.env文件的变量需要同步到Vercel。

2. 修复graphql-request版本问题

该错误大概率是graphql-request版本兼容问题,部分新版本在Node.js环境(Vercel构建时为服务端环境)中错误地调用了浏览器的document对象:

  • 卸载当前版本:npm uninstall graphql-request
  • 安装稳定兼容版本:npm install graphql-request@4.3.0(此版本经过验证可在服务端环境正常运行)

3. 检查graphql-request调用参数

确保调用request方法时,没有传递依赖浏览器环境的参数(如包含document.cookie的headers),所有请求配置需适配Node.js环境。

4. 本地模拟构建测试

在本地执行next build命令,模拟Vercel的构建流程,若能复现错误,可直接在本地调试,更快定位问题。

内容的提问来源于stack exchange,提问作者SuperPanda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 21:50:34