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

Next.js动态路由部署Github Pages后直接访问出现404问题排查

问题分析与解决方案

核心问题

  1. 路由参数名不匹配:你声明的动态路由是experiments/[id],但代码中getStaticPaths返回的参数是{url: ...},getStaticProps读取的是params.url,这会导致路由参数无法正确绑定,即使预生成的页面也无法正常匹配。
  2. Github Pages静态托管限制:Github Pages仅能返回预先构建好的静态文件,不支持Next.js fallback: true依赖的服务器端动态生成逻辑。直接访问未预生成的URL时,Github Pages找不到对应静态文件会返回404;而页面跳转用的是Next.js客户端路由,无需请求服务器,因此能正常加载。

第一步:修复路由参数名不匹配

如果你的路由文件是pages/experiments/[id].js,修改getStaticPaths和getStaticProps的参数名,与路由文件名保持一致:

export async function getStaticPaths() {
  const experimentIds = await fetchExperimentUrls();
  const paths = experimentIds.urls.map((id) => ({
    params: { id: id.toString() }, // 参数名改为id,匹配路由文件名
  }));

  return { paths, fallback: true };
}

export async function getStaticProps({ params }) {
  const { id } = params; // 读取id参数
  const res = await fetch(
    `${process.env.NEXT_PUBLIC_API_URL}/experiments/${id}`,
    {
      method: "GET",
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json",
      },
    }
  );
  const experimentProps = await res.json();
  return { props: { experimentProps }, revalidate: 60 };
}

第二步:解决Github Pages的404问题

方案1:自定义404页面做路由转发

利用Github Pages将所有不存在的路径指向404.html的特性,通过脚本将请求路径转发给Next.js客户端路由处理:

  1. 在项目public目录下创建404.html:
<!DOCTYPE html>
<html>
<head>
  <script>
    // 提取当前请求路径
    const path = window.location.pathname;
    // 将路径转为hash,跳转到首页让Next.js处理
    window.history.replaceState({}, '', '/#' + path);
    window.location.replace('/');
  </script>
</head>
<body></body>
</html>
  1. 在pages/_app.js中添加逻辑处理hash中的路径:
import { useEffect } from 'react';
import { useRouter } from 'next/router';

export default function MyApp({ Component, pageProps }) {
  const router = useRouter();

  useEffect(() => {
    if (window.location.hash) {
      // 去掉hash前缀,获取原始路径
      const targetPath = window.location.hash.slice(1);
      // 跳转到目标路由
      router.push(targetPath);
      // 清除hash,避免刷新后重复处理
      window.history.replaceState({}, '', '/');
    }
  }, []);

  return <Component {...pageProps} />;
}

方案2:完全客户端渲染动态页面

如果不需要SEO优化,可以放弃静态生成,直接在组件内获取数据,所有动态路径由客户端处理:
修改pages/experiments/[id].js:

import { useEffect, useState } from 'react';
import { useRouter } from 'next/router';

export default function ExperimentPage() {
  const router = useRouter();
  const { id } = router.query;
  const [experiment, setExperiment] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    if (!id) return;

    const fetchData = async () => {
      try {
        setLoading(true);
        const res = await fetch(
          `${process.env.NEXT_PUBLIC_API_URL}/experiments/${id}`,
          {
            method: 'GET',
            headers: {
              'Content-Type': 'application/json',
              Accept: 'application/json',
            },
          }
        );
        if (!res.ok) throw new Error('实验不存在或加载失败');
        const data = await res.json();
        setExperiment(data);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [id]);

  if (loading) return <div>加载中...</div>;
  if (error) return <div>错误:{error}</div>;
  if (!experiment) return <div>未找到该实验</div>;

  // 渲染实验内容
  return (
    <div>
      <h1>{experiment.title}</h1>
      <p>{experiment.description}</p>
    </div>
  );
}

同时在next.config.js中配置静态导出:

module.exports = {
  basePath: '/your-repo-name', // 替换为你的Github仓库名
  trailingSlash: true,
  output: 'export',
};

额外注意事项

  • 如果部署在用户名.github.io/仓库名/路径下,必须配置basePath指向仓库名;
  • 部署时需将静态导出的out目录内容推送到Github Pages对应的分支。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 12:17:53