base标签仅在HTML解析阶段影响src/href等纯相对路径,对fetch、import等JS运行时路径完全无效;必须置于head最前且唯一,href值须为绝对URL或结尾带/的根相对路径,否则静默失效导致404。

base标签不控制JS运行时路径,fetch和import完全无视它
很多人以为加了<base href="/app/">就能统一整个应用的路径逻辑,结果fetch('./api/user')还是报404,import('./pages/Home.vue')加载失败——因为<base>只在HTML解析阶段生效,对JS执行期构造的URL毫无影响。
浏览器明确区分两个阶段:HTML加载时解析src、href、action等属性;JS运行时调用fetch()、import()、new Worker()、@import(在CSS里)时,全部绕过<base>,按当前页面URL或模块解析规则处理。
常见误判点:
-
<img src="avatar.jpg">→ 受<base>控制,会变成/app/avatar.jpg -
document.createElement('img').src = 'avatar.jpg'→ 不受控,仍按当前页URL拼接 -
background: url(logo.png)在CSS文件里 → 受控(因CSS是HTML加载时解析的) -
@import "reset.css"在CSS文件里 → 不受控(CSS引擎自己resolve)
前端路由根本不读document.baseURI,配错就跳错路
<base href="/admin/">不会让Vue Router自动把router.push('/home')变成/admin/home,也不会让React Router v6+的<Link to="/about">生成正确路径。它们压根不查document.baseURI,必须显式传参。
立即学习“前端免费学习笔记(深入)”;
后果很直接:HTML里写了<base href="/admin/">,但Vue Router没配base: '/admin/',就会出现“图片从/admin/logo.png加载成功,点击<a href="/home">却跳到https://example.com/home”这种割裂行为。
必须同步配置:
- Vue Router:
createRouter({ base: '/admin/' }) - React Router v6+:
<Router basename="/admin"> - Vite:
build.base: '/admin/'(此时HTML中再写<base>属于冗余) - Webpack:
output.publicPath: '/admin/'(若同时手写<base>,可能拼出/admin//admin/js/app.js)
href="#section"在base下不是滚动,而是重载
这是最隐蔽也最容易被当成“JS没绑事件”的问题:<a href="#faq">常见问题</a>在有<base href="/app/">时,会被浏览器解析成/app/#faq,触发一次完整导航——地址栏变灰、页面闪一下、滚动回顶,Network里能看到一次对/app/的200响应(返回完整HTML)。
原因不是bug,是规范:所有不以/、http://、javascript:开头的href值,都被视为相对路径,强制拼接<base>值。
安全做法只有三种:
- 用
event.preventDefault()拦截后调用document.getElementById('faq').scrollIntoView() - 写成
href={window.location.pathname + '#faq'}(React/Vue客户端)或服务端注入href="${location.pathname}#faq" - 用
new URL('#faq', document.baseURI).href生成真正指向当前页的hash URL(注意:这个API能绕过base对hash的干扰)
base标签本身极易静默失效,且无任何提示
<base href="/app">结尾少个/,或者写成<base href="app/">(缺根斜杠),浏览器就直接丢弃整条标签——控制台零报错、零警告,但后续所有<img src="logo.png">都退回到按当前页面URL解析,上线后批量404。
合法值仅两种:
-
/myapp/(根相对路径,开头/、结尾/,缺一不可) -
https://cdn.example.com/v3/(绝对URL,协议+域名+路径全明确)
其他全是无效写法:assets/、../static/、%PUBLIC_PATH%/(未被构建工具替换时)、/myapp(结尾无/)——它们会让<base>形同虚设,而你根本不知道。
最容易被忽略的细节:它必须是<head>中第一个元数据标签,前面不能有<title>或<meta>;重复声明时,浏览器只认第一个,第二个起全部丢弃。



















