Vercel 部署 Hugo + LoveIt 主题踩坑记录
本文全文由
codex生成
最近把博客主题从 Stack 迁到了 LoveIt。本地预览一直是正常的,但一推到 Vercel 上,首页却直接变成了一份 RSS XML,后面又连续冒出了几层新的构建报错。
这篇文章就是把这次部署过程中遇到的问题、判断思路和最终修复方式完整整理下来。它不一定是最通用的教程,但如果你也在用 Hugo + Vercel + 主题子模块 这一套,应该会省掉不少时间。
问题是怎么开始的
最开始的现象其实很怪:
- 本地
hugo server一切正常 - Vercel 显示部署成功
- 但访问真实网站时,首页不是 HTML,而是一份 XML
最初看到这个页面的时候,我第一反应是:
- 是不是 Hugo 把首页构建错了
- 是不是
index.html没有生成 - 是不是 Vercel 根本没有正确发布 Hugo 的输出目录
后来排查下来,第三个方向是对的。
第一个坑:仓库里混着旧静态产物
仓库根目录里还留着两套之前生成过的静态站内容:
isablerander/isablerange/
而且它们不只是本地目录,而是真的被 Git 跟踪着。
这会导致一个很麻烦的问题:
如果部署平台的根目录、输出目录或者构建逻辑稍微有一点偏差,它就有可能直接把这些旧静态文件当成整站发布出去。
这也是为什么线上首页会直接出现 XML。不是当前站点真的只构建出了 XML,而是部署链路很可能拿错了东西。
解决方法
先做了两件事:
- 在仓库根目录加了
.vercelignore - 最后把
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排除本地生成和无关目录 - 主题子模块信息保持完整
这次排障里真正有用的判断顺序
回头看,这次真正有效的排障顺序其实是这样的:
- 先分清“是 Hugo 没构建出来”,还是“Vercel 发布错了目录”
- 再确认“本地主题存在”不等于“远端构建时也能拿到主题”
- 再确认“本地 Hugo 版本能跑”不等于“部署平台的 Hugo 版本也能跑”
- 最后再去看样式、函数兼容性这种更细节的问题
如果一开始就盯着页面长得不对、或者盯着 RSS XML 本身,很容易在表象里绕很久。
真正的关键,还是把“仓库内容”“构建环境”“部署输出”这三层拆开看。
写在最后
这次迁移的过程比我预想中折腾得多一些。
但从另一个角度看,主题迁移这种事,本来就不太可能只是改个 theme 字段然后一切如常。真正麻烦的部分,往往都藏在部署链路、主题依赖和历史遗留文件里。
把这些问题一个个拆开之后,反而会对自己的博客结构更熟悉一些。
至少现在再看这个仓库,哪些是内容,哪些是模板,哪些只是过去留下的构建产物,终于比之前清楚了很多。