Next.js 静态导出部署 GitHub Pages:output: export、basePath 与 git subtree 完整实战
【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js
本篇以 Next.js 官方仓库中的 github-pages 示例 为主体,讲解如何将一个纯静态的 Next.js 应用导出为静态文件并发布到 GitHub Pages。读完后你将掌握:output: "export"静态导出的配置方式、basePath前缀的正确写法及其在源码中的校验规则,以及基于git subtree push的免 CI 部署脚本的完整原理与操作步骤。
场景说明:为什么 Next.js 可以部署到 GitHub Pages
GitHub Pages 只能托管纯静态文件,没有 Node.js 运行时。因此部署到 Pages 的前提是:应用不依赖任何服务端渲染或 API 路由,能够被 Next.js 完整地静态导出为一组 HTML/CSS/JS 文件。官方 github-pages 示例 正是为此设计的最小可运行模板,其 README 开头即说明:
This example supports deploying a statically exported Next.js application to GitHub Pages.
示例同时给出一条关键约束:导出的out目录不应被版本控制系统忽略(若.gitignore中写有out/,需将其移除),因为部署脚本会把out/内容提交到 Git 并推送。
示例代码结构
该示例采用 App Router 组织代码,文件布局如下:
| 文件 | 作用 |
|---|---|
| app/layout.tsx | 根布局,注入 Inter 字体与metadata(title/description) |
| app/page.tsx | 首页,通过next/link链接到/about |
| app/about/page.tsx | 关于页,包含返回首页的链接 |
| next.config.js | 核心配置文件,启用静态导出与 basePath |
| package.json | 定义dev/build/deploy三个脚本 |
三个页面全部是纯静态内容(组件直接返回 JSX,没有任何async数据获取),这是它能被成功静态导出的根本原因。根布局还使用了next/font/google加载 Inter 字体——字体文件会在构建时本地化处理,同样不需要运行时。
核心配置:output: "export" 与 basePath
next.config.js 的全部内容只有两行,它们是整篇部署方案的灵魂:
/** @type {import('next').NextConfig} */ const nextConfig = { output: "export", basePath: "/gh-pages-test", }; module.exports = nextConfig;1. output: "export"
output: "export"告诉 Next.js 在next build时不做常规的.next服务端产物输出,而是执行静态导出:把所有页面预渲染为 HTML,连同客户端 JS、字体等静态资源一起写入项目根目录的out/文件夹。部署脚本后续操作的正是这个out/目录。
2. basePath: 与仓库名匹配的路径前缀
GitHub Pages 的项目站点地址形如https://<github-user-name>.github.io/<github-project-name>/,站点挂载在仓库名构成的路径前缀下,而不是域名根路径。因此所有页面、路由、静态资源 URL 都必须带上这个前缀,这就是basePath的职责。
README 给出的配置规则是:对于形如https://github.com/<user>/<repo>的仓库,将basePath更新为/repo。示例中写的/gh-pages-test即是一个仓库名占位符,使用时需替换为你自己的仓库名。
basePath的写法在 Next.js 源码中有严格校验,见 packages/next/src/server/config.ts:
- 必须为空字符串或以
/开头,否则抛出Specified basePath has to start with a /; - 不能以
/结尾,否则抛出Specified basePath should not end with /; - 当
basePath有效且未显式配置assetPrefix时,assetPrefix会默认继承为basePath(即静态资源 URL 自动带上同一前缀)——这正是示例无需额外配置资源前缀的原因。
另外,从 请求归一化层 的不变量basePath must be set and cannot be "/"可以看出,basePath 一旦被设置,它必须是一个有意义的路径前缀,单独一个/是非法值。
提示:如果你把应用部署到 GitHub 用户/组织主页(
<user>.github.io根路径)而非项目子路径,则不需要basePath;本方案针对的是项目站点这一最常见场景。
部署脚本:一条命令完成构建与推送
package.json 中的deploy脚本是整套方案的自动化核心:
next build && touch out/.nojekyll && git add out/ && git commit -m "Deploy" && git subtree push --prefix out origin gh-pages逐段拆解:
next build:执行静态导出,生成out/目录;touch out/.nojekyll:创建空的.nojekyll文件。GitHub Pages 默认使用 Jekyll 处理仓库文件,遇到下划线开头的目录(Next.js 静态资源中常见_next风格的路径约定)可能引发处理异常或行为差异;.nojekyll的存在会显式关闭 Jekyll 处理,保证文件原样发布;git add out/ && git commit -m "Deploy":把导出产物提交到本地仓库(再次印证 README 中“out目录不应被.gitignore忽略”的要求);git subtree push --prefix out origin gh-pages:这是整个脚本的精髓。它无需 CI、无需额外依赖,利用 Git 原生的subtree机制,把out/子目录的全部历史与最新内容单独推送到远端的gh-pages分支。gh-pages分支的根目录就对应out/的内容,与 GitHub Pages“以分支根目录为站点根”的要求(即下文 Steps 中的/root选项)完全吻合。
完整部署步骤
以下 7 步完整继承自 examples/github-pages/README.md:
- 新建一个public的 GitHub 仓库;
- 编辑
next.config.js,让basePath与你的 GitHub 仓库名匹配:给定https://github.com/<user>/<repo>,把basePath更新为/repo; - 把脚手架代码推送到
main分支; - 运行
deploy脚本(如npm run deploy),它会自动创建gh-pages分支; - 在 GitHub 仓库Settings → Pages → Branch中,选择
gh-pages分支并指定/root文件夹,点击Save; - 对项目做一次任意改动;
- 再次运行
deploy脚本,把改动推送到 GitHub Pages。
完成后,站点地址形如:
https://<github-user-name>.github.io/<github-project-name>/获取示例工程
仓库 README 提供了通过create-next-app脚手架一键生成该示例的命令,三种包管理器任选其一(在目标目录执行即可):
npx create-next-app --example github-pages github-pages-appyarn create next-app --example github-pages github-pages-apppnpm create next-app --example github-pages github-pages-app生成的工程依赖仅包含next、react、react-dom及 TypeScript 相关包(见示例 package.json),dev脚本对应本地开发,build脚本对应纯构建验证,deploy脚本对应一键发布。
使用边界与注意事项
- 仅适用于纯静态应用:
output: "export"导出的产物没有服务端运行时,API 路由、getServerSideProps、服务端组件数据获取等能力都不可用。仓库错误文档目录中专门收录了 api-routes-static-export 错误说明 和 export-no-custom-routes 错误说明,描述的就是静态导出场景下这些能力受限时的报错,可作为排查参考。 - basePath 必须与仓库名同步:若后续重命名 GitHub 仓库,务必同步更新
next.config.js中的basePath并重新部署,否则页面可访问但样式、脚本等资源会因前缀不匹配而加载失败。 - out 目录保持可提交:确认
.gitignore没有把out/排除,否则git add out/阶段会静默失败。 - 部署链路无 CI:本方案完全依赖本地
git subtree push,适合个人博客、文档站等低频更新场景;对频繁迭代的项目,可参考仓库中另一个 with-static-export 示例 了解静态导出的更多配置变体,或自行将deploy步骤迁移到 CI 中执行。
总结来说,该方案的技术内核只有三件事:output: "export"产出纯静态out/目录、basePath对齐 Pages 的子路径挂载前缀、git subtree push把产物推上gh-pages分支。三者缺一,站点都会出现页面 404、资源 404 或分支不存在的典型故障;按上述步骤完整执行后,即可得到一个可直接访问的 GitHub Pages 站点。
【免费下载链接】next.jsThe React Framework项目地址: https://gitcode.com/GitHub_Trending/next/next.js
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考