/base href> 必须以斜杠结尾(如/myapp/),否则浏览器将其视为文件导致路径拼接错误;仅接受绝对URL,相对路径会被忽略;不可与构建工具的base配置重复;须置于<head>最前且唯一。

Firefox/Opera 会把 /myapp 截成 /myappcss/ 这种拼接错误
浏览器对 <base href> 的路径拼接不是简单字符串连接,而是按 URL 规范做解析。当 href 值为 /myapp(结尾无斜杠)时,浏览器把它当作一个“文件”而非“目录”,后续相对路径如 css/app.css 就会被拼成 /myappcss/app.css —— 中间斜杠被吞掉。这不是 bug,是 URL 解析器把 /myapp 当作路径最后一段的文件名处理了。
这个问题在 Firefox 和 Opera 中最明显,Chrome 有时表现宽容,但不能依赖。实际部署后,<link rel="stylesheet" href="css/app.css"> 就会 404。
-
/myapp/✅ 合法:明确表示“根下的 myapp 子目录”,后续css/app.css→/myapp/css/app.css -
/myapp❌ 失效:被视作文件,css/app.css→/myappcss/app.css -
https://cdn.example.com/v3同样危险:结尾没斜杠 →js/app.js可能变成https://cdn.example.com/v3js/app.js
<base href> 写成 assets/ 或 ../static 会被静默忽略
浏览器只认以 http://、https://、// 或 / 开头的 href 值。写成 assets/、../static、static/ 等相对路径,整条 <base> 标签直接被丢弃——控制台零提示,但所有后续 src、href 全部回退到当前页面 URL 解析。
本地开发可能“碰巧”能跑,因为当前页 URL 恰好和资源位置匹配;一上线到子路径(比如 https://a.com/myapp/),<img src="logo.png"> 就请求 https://a.com/myapp/logo.png,而真实路径其实是 https://a.com/myapp/assets/logo.png,必 404。
立即学习“前端免费学习笔记(深入)”;
- ✅ 有效写法:
/myapp/、https://cdn.example.com/v3/、//cdn.example.com/v3/ - ❌ 无效写法:
assets/、../static/、%PUBLIC_URL%/(未被模板引擎替换时就是字面量) - 服务端模板若漏掉变量替换,比如发出去的是
<base href="%ASSET_BASE%">,浏览器看到的就是非法字符串,<base>失效
Vite/Webpack 的 build.base 或 publicPath 与 <base href> 冲突
构建工具已经通过配置把所有资源路径重写了,再手动加 <base href="/myapp/">,会导致路径被拼两次。例如 Vite 设了 build.base: '/myapp/',HTML 里又写 <base href="/myapp/">,那么 <script src="app.js"> 最终请求地址是 /myapp//myapp/app.js(双斜杠)。
Webpack 同理:publicPath: '/' + <base href="/myapp/"> → chunk 加载地址变成 /myapp/app.js,但实际文件在 /app.js,必然 404。
- 二选一:要么靠构建工具自动注入路径(推荐),要么手写
<base>并关掉构建工具的路径重写 - Vue Router / React Router v6+ 完全不读
document.baseURI,必须显式传base或basename参数 -
<base>不影响fetch()、import()、CSS 中的@import或url(),这些路径得单独处理
<base> 必须放在 <head> 最前面且只能有一个
<base> 的作用时机是 HTML 解析阶段,只对它之后出现的相对 URL 生效。如果写在 <title> 或 <link> 后面,那些标签里的 href、src 仍按当前页面 URL 解析,大概率 404。
重复声明多个 <base>,浏览器只用第一个,其余忽略,并在控制台提示 Multiple base elements detected. Only the first one is used.。SSR 模板若在 header 和 page 组件里各自 render 了一个 <base>,就容易中招。
- ✅ 正确位置:
<head>开头,<meta charset>之后、<title>之前 - ❌ 错误位置:
<body>里、<title>后、或由 JS 动态插入(document.head.appendChild(baseEl)) - JS 动态插入的
<base>对已解析的元素无效,只影响后续新创建的 DOM 节点



















