base href静默失效时所有相对路径资源均404;仅http://、https://、//或/开头且合法格式(如结尾带斜杠)的值才生效,否则浏览器丢弃标签不报错,导致img、script等按当前页url解析而批量404。

base href 静默失效时,所有相对路径资源都会 404
浏览器对 <base href> 的校验极其严格:只要值不是以 http://、https://、// 或 / 开头,整条标签就被静默丢弃——控制台零提示,Network 面板里也看不到异常请求,但 <img src="logo.png">、<script src="app.js"></script> 全部按当前页面 URL 解析,部署在子路径时必现批量 404。
常见无效写法包括:
-
<base href="assets/">(缺协议和根斜杠) -
<base href="../static/">(含..) -
<base href="/myapp">(结尾无/,Firefox/Opera 会截断成/myappcss/) -
<base href="%PUBLIC_PATH%/">(构建工具未替换时就是字面量字符串)
真正安全的只有两种形式:<base href="https://cdn.example.com/v3/">(推荐 CDN 场景),或 <base href="/myapp/">(根相对路径,结尾斜杠不可省)。
哪些资源真被 base 控制,哪些完全绕过它
<base> 只在 HTML 解析阶段起作用,只改写纯相对路径(即不以 /、: 或协议开头)的初始解析逻辑。它不是运行时重写器,更不干预 JS/CSS 模块系统。
✅ 真正受影响的(HTML 属性中硬编码的纯相对路径):
<img src="icon.png"><script src="app.js"></script><link href="style.css"><form action="submit.php"></form>- CSS 文件内的
background: url(avatar.jpg)(注意:这是 HTML 解析时计算的,不是 CSS 引擎自己 resolve)
❌ 完全不受影响的(全部绕过 <base>):
fetch('./api/user')import('./utils.js')-
@import "reset.css"(仍以该 CSS 文件自身位置为基准) -
<iframe src="/admin/frame.html"></iframe>(根相对路径) <img srcset="logo-2x.png 2x">
SPA 部署子路径时,base 和路由配置必须字面量对齐
<base href="/a/b/c/"> 不会让 Vue Router 或 React Router v6+ 自动识别子路径——它们完全不读 document.baseURI,必须显式传入 base 参数。若只配了 HTML 的 <base>,没设路由的 base,router.push('/home') 会跳到 https://example.com/home 而非预期的 /a/b/c/home;反之,若只配路由 base,资源加载又会 404。
关键细节:
-
createWebHistory('/a/b/c/')和<base href="/a/b/c/">必须字面量完全一致(包括末尾斜杠) - Vite 构建已设
build.base: '/a/b/c/',HTML 中再手动加<base>会导致路径拼两次(如/a/b/c//a/b/c/js/app.js) - Webpack 项目中
publicPath: '/a/b/c/'和手写<base href="/a/b/c/">同时存在,chunk 加载地址可能错位
base 标签位置错误或重复声明毫无提示但效果丢失
<base> 必须是 的直接子元素,且整个文档中只能有一个。放错位置或重复注入,浏览器不会报错,但行为直接失效。
典型翻车点:
- 放在
里 → 浏览器静默忽略 - 模板拼接时 SSR 多次注入(比如 header + 页面模板各塞一个)→ 只有第一个生效,后续被丢弃
- 用 JS 动态插入(如
document.head.appendChild(baseEl))→ 已解析的src/href不会重算,只影响之后新创建的元素
最稳妥的做法:在 HTML 源码中手动确保它出现在 最顶部,且仅一次。调试时打开 DevTools → Elements → 确认 内有且只有一个 <base href="">,再右键检查任意相对链接的 “Request URL” 是否符合预期。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











