发布于 更新于 约 3 分钟读完 · 1,090 字

本文目录 7 节
  1. 一句话总结
  2. 根因(决策链)
  3. 判据 / 排查法
  4. 修法
  5. 补充:markdown 正文里的站内互链走相对路径(2026-07-24 回验)
  6. 教训(可复用)
  7. 关联文档

双部署目标的 base 路径陷阱 · 根路径拼出 //slug 全站内链失效

入档:2026-06-25 来源:蛛网之上(Astro 静态站)同时部署 GitHub Pages 子路径 + 香港服务器根路径,自定义域名站全站「关联文档」链接点击跳错 状态:已定位修复并上线验证(线上双斜杠内链 0 个)

一句话总结

一套代码部署到两个 base 不同的目标(Pages 子路径 /above-the-web vs 自定义域名根路径 /)时,凡是手动拼接 `${BASE}/${slug}` 的地方,在 BASE='/' 下会拼出 //slug——浏览器把 // 开头当成协议相对 URL(等价 https://slug),于是整站内链全跳错。而它只在根路径那个镜像现形,子路径镜像完全正常,极易漏测。

根因(决策链)

  • base 改成环境变量驱动:BASE = process.env.BASE_PATH || '/above-the-web',一套代码兼容两种部署。
  • wikilink 解析里手写:return slug ? ${BASE}/${encodeURI(slug)}/ : null。
  • 子路径:'/above-the-web' + '/' + slug = /above-the-web/slug/ ✅。
  • 根路径:'/' + '/' + slug = //slug/ ❌ → 协议相对 URL → 浏览器当域名解析 → 点击跳到 https://slug/。

判据 / 排查法

  • 现象:鼠标悬停链接,状态栏显示 //开头 而非 /开头;或点击跳到一个莫名其妙的「域名」。
  • 快速验证:curl 线上页面 | grep 'href="//',过滤掉 //www///cdn 等真实协议相对资源,剩下的就是 bug。
  • 构建后自检:grep -roh 'href="//[^h]' dist/ 计数,应为 0。

修法

base 拼接归一化:先去掉 base 尾部斜杠再统一拼一个:

const BASE_PREFIX = BASE.endsWith('/') ? BASE.slice(0, -1) : BASE;
// 用 `${BASE_PREFIX}/${slug}/`,两种 base 都只得到单斜杠

注:框架自带的 import.meta.env.BASE_URL 已被归一化为总是以 / 结尾,所以用它的地方(${BASE_URL}slug)不会出 bug;只有自己读 process.env.BASE_PATH 手拼的地方才会踩。优先用框架归一化过的变量。

补充:markdown 正文里的站内互链走相对路径(2026-07-24 回验)

上面的归一化前提是能拿到 BASE_URL 变量。但内容集合的 markdown 正文(经 <Content/> 渲染)是静态文本,注入不了 import.meta.env.BASE_URL——于是正文里写站内链接有个双 base 死角:

  • 写死绝对路径 [规范](/tasks/spec/) → 在 Pages 子路径镜像下缺了 /above-the-web 前缀,404;
  • 又没法在 md 里拼 ${BASE_URL}。

解法:用相对路径,让浏览器按当前 URL 解析。 任务书详情页部署在 {base}/tasks/{slug}/,正文里写 [教程类任务规范](../spec/),浏览器以当前页 URL 为基准解析 ../spec/ → {base}/tasks/spec/——当前 URL 本就带着正确的 base,所以两种部署下都自动对,md 里一个字都不用改。

前提与判据:

  • 依赖 URL 带尾斜杠:Astro 静态构建产出 /tasks/{slug}/index.html,页面 URL 带尾斜杠,../ 才退到 /tasks/。若站点配了去尾斜杠,../spec/ 会多退一层,需改成 spec/。
  • 一句话规律:能用框架变量拼就归一化拼;拼不到变量的静态内容层(md/json 正文),站内链一律走相对路径,别写死绝对路径。
  • 验证同上:两个镜像都点一遍,别只看根路径镜像。

教训(可复用)

  1. 多 base 部署 = 必须两个镜像都测链接。链接类 bug 会「只在一个镜像现形」,在另一个上验证会得出「没问题」的错误结论。—— 又一例「所见非真相」:看子路径镜像 ≠ 看根路径镜像。
  2. 本地复现根路径构建有坑:git-bash(MSYS)会把 BASE_PATH=/ 的值路径转换成 C:/Program Files/Git/,导致构建产物路径错乱。→ 用 PowerShell 设环境变量,或 MSYS_NO_PATHCONV=1。
  3. 凡「环境变量可能为 /」的路径拼接,默认写归一化,不要裸 ${A}/${B}。

关联文档

类型/平台工程