<base href>仅对HTML解析阶段的相对路径生效,必须以/、http://、https://或//开头,否则静默失效;JS/CSS运行时路径(如fetch、import、@import)完全不受其控制。

base href 写成相对路径就静默失效
浏览器对 <base href> 的校验非常严格:只要值不是以 http://、https://、// 或 / 开头,整条标签就被丢弃——控制台不报错、不警告,但所有 <img src="logo.png">、<script src="app.js"> 都退回到按当前页面 URL 解析,上线后批量 404。
常见无效写法包括:href="assets/"、href="../static/"、href="subapp/"、href="%PUBLIC_PATH%/"(未被构建工具替换时就是字面量)。这些写法等于没写。
真正合法的只有两种形式:
-
href="/myapp/":根相对路径,开头必须是/,结尾必须带/;否则 Firefox/Opera 会截断路径(如css/app.css变成/myappcss/app.css) -
href="https://cdn.example.com/v3/":绝对 URL,协议、域名、路径全明确,推荐用于 CDN 场景
前端路由和 base 标签完全不互通
<base href="/admin/"> 不会让 Vue Router 或 React Router v6+ 自动识别子路径。它们根本不读 document.baseURI,必须显式配置 base 参数,否则导航和资源加载行为割裂。
立即学习“前端免费学习笔记(深入)”;
典型症状:
- HTML 中写了
<base href="/admin/">,但 Vue Router 没设base: '/admin/'→router.push('/home')跳到https://example.com/home,而非/admin/home -
<img src="logo.png">加载/admin/logo.png,但点击链接却跳到根路径,行为不一致
对应配置必须严格对齐:
- Vue Router:
createRouter({ base: '/admin/' }) - React Router v6+:
<Router basename="/admin"> - Vite:
build.base或base配置项设为/admin/
构建工具 publicPath 和手写 base 混用引发双斜杠
Webpack 的 publicPath 或 Vite 的 base 配置,如果和 HTML 中手写的 <base href="/a/b/c/"> 值相同,会导致资源路径被拼两次。
例如预期加载 /a/b/c/js/app.js,实际请求的是 /a/b/c//a/b/c/js/app.js(中间两个 //),结果静态资源 404,Service Worker 预缓存失败,微前端子应用 chunk 加载中断。
构建工具生成的 HTML 通常已注入正确路径,手动再加 <base> 属于冗余操作,反而引入冲突风险。
更稳妥的做法:
- Vite 项目:直接配
base: '/myapp/',构建后 HTML 中不要手动加<base> - Webpack 项目:设
publicPath: '/myapp/',确保html-webpack-plugin输出的 HTML 不含重复<base> - 本地开发调试时,可用
href="http://localhost:3000/"替代/,避免和后端路由冲突
JS/CSS 运行时路径完全绕过 base 控制
<base> 只在 HTML 解析阶段生效,不影响 JS/CSS 运行时构造的 URL。这是最容易被忽略的盲区。
以下全部不受 <base> 影响:
fetch('./api/user')import('./utils.js')@import "reset.css"-
<iframe src="/frame.html">(以/开头) <img srcset="logo-2x.png 2x">
而以下才真正受控:
<img src="icon.png"><link href="style.css">- CSS 文件中
background: url(avatar.jpg)(注意:这是 HTML 解析 CSS 时计算的,不是 CSS 引擎自己 resolve)
很多人误以为设了 <base href="/v3/"> 就能统一管住所有路径,其实运行时模块导入、API 请求、CSS @import 全都不买账——它们各自按文件位置或当前域名解析。



















