<base>标签本身不引发跨域,仅重写相对路径解析基准;它只影响HTML解析阶段的纯相对路径(如img/src),对fetch、import等运行时路径无效,错误配置可能导致资源误拼为跨域URL或静默失效。

<base> 标签本身不会引起跨域问题——它只改写相对路径的解析基准,不改变协议、域名或端口。所谓“base 引起的跨域”,其实是误配 <base href> 后,资源被错误拼出跨域 URL(比如本该请求 /api/user,却因 base 拼成 https://cdn.example.com/api/user),或更常见的是:你以为它生效了,其实它被浏览器静默丢弃,导致所有相对路径按当前页面 URL 解析,意外触发跨域请求。
检查 <base href> 是否真的生效
浏览器对 href 值校验极严:只要不是以 http://、https://、// 或 / 开头,整条 <base> 就被忽略——控制台无提示,Network 里看起来“路径正常”,但实际加载地址是错的。
- 非法写法(全部静默失效):
assets/、../static/、subapp/、%PUBLIC_URL%/(未被构建替换时就是字面量)、/myapp(结尾缺/,Firefox 会截断) - 合法写法(仅以下两种):
/myapp/(根相对路径,必须以/开头+结尾)、https://cdn.example.com/v3/(绝对 URL,协议+域名+路径,结尾带/) - 打开开发者工具 → Elements → 查看
<head>最顶部是否存在<base>,并确认其href值是否符合上述任一格式
确认哪些资源受 <base> 影响,哪些根本不受
<base> 只在 HTML 解析阶段起作用,且仅影响纯相对路径(即不以 /、: 或协议开头)的初始解析。它和跨域策略无关,但错误使用会让本该同源的请求变成跨域。
- ✅ 真正受影响(且可能被拼错成跨域):
<img src="logo.png">、<script src="app.js">、<link href="style.css">、CSS 中的background: url(avatar.jpg) - ❌ 完全不受影响(无论
<base>怎么写,都不会因此跨域):fetch('./api/user')、import('./utils.js')、@import "reset.css"、<iframe src="/admin/frame.html">(根相对路径)、<img srcset="logo-2x.png 2x"> - 特别注意:
background-image跨域失败时通常静默降级(无控制台报错),真正原因往往是后端没配Access-Control-Allow-Origin,而非<base>导致
避免 <base> 和前端路由 / 构建配置冲突
SPA 部署在子路径(如 https://example.com/a/b/c/)时,<base href="/a/b/c/"> 必须与框架路由和构建工具配置严格对齐,否则资源路径和跳转路径各走各的,结果一半同源、一半跨域。
立即学习“前端免费学习笔记(深入)”;
- Vue Router / React Router v6+ 不读
document.baseURI,必须显式传入base: '/a/b/c/',否则router.push('/home')会跳到根路径,而<img src="logo.png">却去/a/b/c/logo.png - Webpack 的
publicPath和手写的<base href="/a/b/c/">若同时存在且值相同,资源路径可能被拼两次(如/a/b/c//a/b/c/js/app.js) - Vite 构建时若已设
base: '/a/b/c/',HTML 中就不该再手动加<base>标签 - Service Worker 预缓存路径若依赖
self.location.origin + '/a/b/c/',而 HTML 没配<base>,缓存就错位
最易被忽略的点:动态创建元素、JS 模块导入、fetch 全部绕过 <base>。哪怕你写了 <base href="https://cdn.example.com/v2/">,import('./utils.js') 仍以模块自身位置为基准解析——它根本不看 <base>。



















