目录

Vercel 部署 Hugo + LoveIt 主题踩坑记录

本文全文由codex生成

最近把博客主题从 Stack 迁到了 LoveIt。本地预览一直是正常的,但一推到 Vercel 上,首页却直接变成了一份 RSS XML,后面又连续冒出了几层新的构建报错。

这篇文章就是把这次部署过程中遇到的问题、判断思路和最终修复方式完整整理下来。它不一定是最通用的教程,但如果你也在用 Hugo + Vercel + 主题子模块 这一套,应该会省掉不少时间。

问题是怎么开始的

最开始的现象其实很怪:

  • 本地 hugo server 一切正常
  • Vercel 显示部署成功
  • 但访问真实网站时,首页不是 HTML,而是一份 XML

最初看到这个页面的时候,我第一反应是:

  1. 是不是 Hugo 把首页构建错了
  2. 是不是 index.html 没有生成
  3. 是不是 Vercel 根本没有正确发布 Hugo 的输出目录

后来排查下来,第三个方向是对的。

第一个坑:仓库里混着旧静态产物

仓库根目录里还留着两套之前生成过的静态站内容:

  • isablerander/
  • isablerange/

而且它们不只是本地目录,而是真的被 Git 跟踪着

这会导致一个很麻烦的问题:
如果部署平台的根目录、输出目录或者构建逻辑稍微有一点偏差,它就有可能直接把这些旧静态文件当成整站发布出去。

这也是为什么线上首页会直接出现 XML。不是当前站点真的只构建出了 XML,而是部署链路很可能拿错了东西。

解决方法

先做了两件事:

  1. 在仓库根目录加了 .vercelignore
  2. 最后把 isablerander/isablerange/ 整体从 Git 中移除

.vercelignore 至少能先阻止这些目录继续被 Vercel 拿去部署;彻底从 Git 里删掉,则是从根上消除隐患。

第二个坑:Vercel 实际上没有正确拿到主题

把旧静态产物隔离掉之后,新的构建日志开始出现另一类报错:

found no layout file for "html" for kind "home"
found no layout file for "html" for layout "about" for kind "page"
found no layout file for "html" for kind "taxonomy"

这类错误说明的不是“文章有问题”,而是:

Hugo 在构建时找不到主题模板。

进一步看仓库,发现 themes/LoveIt 虽然在本地存在,但 .gitmodules 里居然没有对应的子模块映射。
也就是说,本地能跑,是因为我机器上已经有这个目录;而 Vercel 从远端克隆仓库时,并不知道它该去哪里拉这个主题。

解决方法

themes/LoveIt 的子模块信息补回 .gitmodules

[submodule "themes/LoveIt"]
	path = themes/LoveIt
	url = https://github.com/dillonzq/LoveIt.git

同时,把 Vercel 的构建命令改成先初始化子模块:

git submodule update --init --recursive && hugo --gc --minify

到这一步,Vercel 才真正开始拿到 LoveIt 的模板文件。

第三个坑:Vercel 默认 Hugo 版本太旧

主题拉下来之后,新的错误又出现了:

partial "init.html" not found

继续顺着查,发现 Vercel 当时用的是比较老的 Hugo 版本,而本地已经在用更新的版本。
LoveIt 当前主题内部使用了较新的模板组织方式,老版本 Hugo 在 partial 查找上兼容得不够好,于是就开始出现一连串“本地正常、线上找不到模板”的情况。

解决方法

把 Vercel 上的 Hugo 版本切到 0.152.0

我这次是直接在 Vercel 那边调整版本,构建日志里最后能看到:

Installing Hugo version 0.152.0

版本切上来以后,前面那层模板找不到的问题基本就过去了。

第四个坑:为兼容旧版本加的补丁,反过来把新版本绕坏了

在还没确认 Hugo 版本之前,我为了兼容老版本,临时补了一些 partial 文件。
结果切到新版本 Hugo 之后,其中有两个补丁反而成了新的错误来源:

no such template "_internal/opengraph.html"

这类问题的本质是:
在不同版本的 Hugo 里,内置模板的调用方式和可用入口并不完全一样。为了兼容旧版随手补上的模板,到了新版环境里反而不成立了。

解决方法

很简单,删掉那两个多余的兼容覆盖,让新版 Hugo 走它自己的内置实现。

这个问题反而提醒我一件事:
排障时“先补一层兼容”是有效策略,但一旦底层版本变化了,就要及时回头清理这些临时补丁,否则很容易进入下一轮误导。

第五个坑:Sass 编译器和 CSS 函数不完全兼容

等前面的部署链路打通之后,最后一个报错出现在样式编译阶段:

TOCSS: failed to transform "/css/style.scss"
Incompatible units: 'rem' and '%'

这个错误看起来像是某个 calc() 写错了,但实际定位下来,是我在自定义样式里写了:

width: min(100%, 16rem);

按现在的浏览器标准,这只是一个普通的 CSS 函数;
但 Vercel 那边的 Sass 编译链把 min() 当成了 Sass 的数学函数,于是试图拿 100%16rem 去比较大小,最后直接炸掉。

解决方法

把它改成更稳妥的写法:

width: 100%;
max-width: 16rem;

功能完全一样,但不会触发 Sass 对 min() 的错误解析。

这一层修完之后,站点终于顺利构建通过。

最后稳定下来的部署配置

这次排完之后,仓库里最终保留的关键配置大概是下面这些:

vercel.json

{
  "buildCommand": "git submodule update --init --recursive && hugo --gc --minify",
  "outputDirectory": "public"
}

Vercel 项目设置

  • Framework Preset: Hugo
  • Hugo version: 0.152.0
  • Build Command: git submodule update --init --recursive && hugo --gc --minify
  • Output Directory: public
  • Root Directory: 仓库根目录

仓库层面的清理

  • 不再提交旧的静态构建目录
  • .vercelignore 排除本地生成和无关目录
  • 主题子模块信息保持完整

这次排障里真正有用的判断顺序

回头看,这次真正有效的排障顺序其实是这样的:

  1. 先分清“是 Hugo 没构建出来”,还是“Vercel 发布错了目录”
  2. 再确认“本地主题存在”不等于“远端构建时也能拿到主题”
  3. 再确认“本地 Hugo 版本能跑”不等于“部署平台的 Hugo 版本也能跑”
  4. 最后再去看样式、函数兼容性这种更细节的问题

如果一开始就盯着页面长得不对、或者盯着 RSS XML 本身,很容易在表象里绕很久。
真正的关键,还是把“仓库内容”“构建环境”“部署输出”这三层拆开看。

写在最后

这次迁移的过程比我预想中折腾得多一些。
但从另一个角度看,主题迁移这种事,本来就不太可能只是改个 theme 字段然后一切如常。真正麻烦的部分,往往都藏在部署链路、主题依赖和历史遗留文件里。

把这些问题一个个拆开之后,反而会对自己的博客结构更熟悉一些。
至少现在再看这个仓库,哪些是内容,哪些是模板,哪些只是过去留下的构建产物,终于比之前清楚了很多。