从 Hexo 迁到 Hugo 又换了电脑,博客图片为什么总挂?一次图片资产整理记录

29 阅读7分钟

我维护个人技术博客有几年了,文章里的截图、示意图、流程图一直不少。前段时间连着做了两件事:把博客从 Hexo 迁到 Hugo,又顺手换了一台新电脑。本以为是"装个环境、拉个仓库"的小事,结果本地预览和部署上线后,各种图片问题集中爆发——有的本地好好的、线上全裂,有的旧文章正常、新文章图出不来,还有一批老图在新电脑上干脆找不到。

这篇把这次排查和整理完整记录下来。结论先说:图片问题大多不是图床本身,而是"图片路径和具体框架、具体电脑绑得太死"。

一、先分清图片是怎么"挂"的

动手改之前,我先把现象分成几类,因为它们的根因完全不同,混在一起改只会越改越乱:

  1. 本地预览正常,部署到线上全裂 —— 多半是路径或 baseURL 的问题,图片文件其实在。
  2. 旧文章图片正常,新文章不显示 —— 是资源目录的组织方式变了,新文章没按新框架的约定放图。
  3. 换电脑 clone 仓库后,一批老图缺失 —— 图片当初就没完整提交进版本库,或散落在仓库外的目录里。
  4. 本地没问题,CI 构建后个别图 404 —— 常见于文件名大小写:macOS 默认大小写不敏感,而线上构建机是 Linux,Image.PNG 和 image.png 在它眼里是两个文件。

不先区分这几种情况,很容易一通操作却没解决真正的问题。

二、为什么静态博客的图片特别容易在迁移时翻车

静态站点没有运行时、也没有数据库,图片本质上就是"一个文件 + 一个写死的路径",构建器只负责把 Markdown 里的引用按规则搬到输出目录。问题在于,Hexo 和 Hugo 对"图片放哪、怎么引用"的约定并不一样:

  • Hexo 常见做法是开启文章资源目录,在 source/_posts/ 下给文章配一个同名文件夹,用相对路径引用;或者统一丢进 source/images/。
  • Hugo 更推荐 Page Bundle(index.md 和图片放在同一个目录,作为 Page Resources),全局共用的图放 static/,再配合 Markdown 渲染钩子处理。

于是 Markdown 里这几种写法——./diagram.png、/images/cover.png、../assets/a.png——在两种框架、以及站点部署在子路径(比如 username.github.io/blog/)时,解析出来的最终地址可能完全不同。再加上图片一直跟着源码走,换框架要搬目录、换电脑要保证仓库完整,仓库还会随着截图越攒越大,而 Git 本就不擅长管理大量二进制文件。

三、我是怎么定位的(可复现的几步)

第一步,用线上地址做一次本地构建,而不是只看开发服务器。 Hugo 可以显式带上线上 baseURL 构建,然后直接看输出目录 public/:

# 按线上地址构建,而不是只跑 hugo server
hugo --baseURL "https://你的域名/博客路径/"

第二步,打开 public/ 里生成的 HTML,看 img 的 src 到底是什么,再对照图片在 public/ 里的实际位置。 这一步能立刻区分两类问题:是路径写错了,还是文件压根没被拷过去。

第三步,把所有文章里的图片引用抽出来,和真实存在的文件做比对。 用一条 grep 先把引用列出来:

# 抽出 Markdown 里所有图片链接
grep -rn -E '!\[.*?\]\(([^)]+)\)' content/

对照文件系统,能找出两类东西:引用了但文件不存在的(迁移时漏拷),以及存在但没有任何文章引用的(可以清理的冗余)。

第四步,确认图片到底有没有进版本库。 换电脑后缺图,多半是图片目录被 .gitignore 误伤,或图本来就在仓库外:

# 列出 Git 实际跟踪的图片,确认该留的都在
git ls-files | grep -E '\.(png|jpg|jpeg|gif|webp)$'

第五步,统一文件名大小写。 把图片名一律改成小写、用连字符,避免本地能过、线上 404。

四、几种图片管理思路的取舍

排查清楚后,我把常见的三种思路整理成一张表:

方式做法优点主要的坑
图片随仓库走(Page Bundle)图片和 md 放同目录,相对路径引用离线可写、Git 可追溯、不依赖第三方仓库膨胀,换框架要改路径,二进制 diff 难看
统一静态目录 + 固定绝对路径图集中放 static/images/,引用 /images/xx.png规则简单,调整文章结构不受影响图仍在仓库里,图文分离后容易对不上
图片外链托管md 里直接写完整 https 链接仓库只剩文本,换框架/电脑/平台图片都不动依赖外链是否稳定可直开,老图需要迁移

结论是没有银弹。文章不多、在意纯 Git 工作流,随仓库走完全没问题;但如果截图多、又经常换环境,把图片外链解耦会省心很多。核心目标只有一个:让图片链接和"用什么框架、在哪台电脑"彻底无关。

五、我最后固定的做法

这套是平台无关的,换 Hexo、Hugo 或别的构建器都适用:

  1. 新文章截图统一走外链,Markdown 里只存完整 https 图片链接。这样不管换成什么框架,甚至把稿子丢进别的写作平台,图片都不依赖构建器的路径解析。
  2. 对图源提几个明确要求:能直接打开、不挑 Referer(这点我之前聊 Referer 防盗链时踩过坑,见这篇 juejin.cn/post/768676… )、走 https、域名固定、改版图片能同名覆盖而链接不变;需要品牌统一时还能绑自己的域名。
  3. 历史老图批量迁移:先把旧文章里的本地路径批量抽出来,借助本地构建拿到可访问的地址或直接定位源文件,用"按链接列表批量抓取转存"的方式统一搬到图床,再用脚本把 Markdown 里的本地路径批量替换成新链接,不必一张张手传。替换就是一条正则的事,例如把 ](./assets/ 开头的本地引用统一换成新的外链前缀,替换后抽查几篇确认。
  4. 做一次全新环境验证:新目录 clone 仓库 → 构建 → 部署,确认整个过程不依赖旧电脑上的任何图片文件。

至于图源具体放在哪个服务,其实不是重点,自己用对象存储套一层 CDN 也完全可以。我自己图省事、也想让博客图片域名长期固定,外链这一层放在图床小镇:图片直开不挑 Referer、改版时同名覆盖链接不用动、老文章支持按链接批量转存、需要时还能绑自己的域名。但这只是我个人的选择,并不是标准答案,各位按自己博客的规模和习惯来挑就好,不必照搬。

六、迁移 / 换电脑前的图片自检清单

  • 用线上 baseURL 本地构建,public/ 里图片路径和实际文件对得上
  • 抽全所有 Markdown 图片引用,没有"引用了但文件不存在",没有大小写混用
  • git ls-files 确认要保留的图片都进了版本库(或已经外链)
  • 外链图片走 https、无痕窗口直开正常、不带 Referer 也能打开
  • 老图已批量迁移、Markdown 链接已批量替换并抽查过
  • 在全新环境 clone + 构建 + 部署演练一遍,不依赖旧电脑的任何文件
  • 仓库里二进制图片的体积心里有数,外链解耦后仓库明显瘦身

写在最后

静态博客的"简单",某种程度上是把路径问题都留给了作者自己。这次迁移做完,我最大的体会是:别让图片链接和某个框架、某台电脑绑在一起,把这层耦合解开,以后无论 Hexo 换 Hugo、换机器还是换部署平台,图片都不用再跟着动一遍。

文中提到的、我自己博客图片在用的图床:imgbed.cn 。同类服务和自建方案都不少,这篇更想讲清楚的是迁移排查的思路,而不是某一个工具,大家按自己的需求选择就好。