document.createelement('base')动态插入无效,因浏览器仅在html解析阶段读取首个,js执行时解析已完成,此时插入被静默忽略,不重试、不报错,已加载及后续资源仍按原始页面url解析。

document.createElement('base') 不能动态重置相对路径基准,浏览器只在 HTML 解析阶段读取第一个 <base>,DOM 操作插入或修改它完全无效。
为什么 JS 动态注入 <base> 总是失败
浏览器解析 HTML 是单向、不可逆的过程:<base href="..."> 必须在 内、且在任何依赖路径的标签(如 <link>、<script></script>、<img>)之前被解析到。JS 执行时,HTML 已完成解析,此时插入 <base>:
- Chrome / Firefox / Safari 全部静默忽略
- 不报错、不警告、不重试
- 已加载的资源(比如 <link href="style.css">)不会重新解析
- 后续新插入的 <img src="logo.png"> 仍按原始页面 URL 解析,不是你期望的新基准
document.write('<base href="/myapp/">') 也不行
即使在 内用 document.write() 尝试“抢在解析前写入”,也存在严重兼容问题:
- 在现代浏览器中,document.write() 只能在文档仍在解析时调用;一旦 DOMContentLoaded 触发,再调用会清空整个页面
- Firefox 和旧 IE 曾出现双路径尝试行为:先按当前 URL 加载一次资源,再按 base 加载一次,造成重复请求和竞态
- 所有主流框架(Vue/React)和构建工具(Vite/Webpack)均明确禁止此用法
真正可行的替代方案
如果你需要“动态”适配不同预览路径(如 /preview/v2/、/staging/),必须把 href 值确定在 HTML 输出前:
- 服务端模板中注入:<base href="%7B%7B%20previewBase%20%7D%7D">,确保 previewBase 是绝对 URL(如 https://preview.example.com/v2/)或合法根相对路径(如 /preview/v2/,结尾带斜杠)
- 构建时插值:Vite 中用 html.inject 插件 + process.env.BASE_URL;Webpack 中用 HtmlWebpackPlugin 的 templateParameters
- 静态站点生成器(Hugo/Jekyll):直接用内置变量,如 <base href="%7B%7B%20.Site.BaseURL%20%7D%7D">
- 纯静态托管(GitHub Pages 子目录):手动写死 <base href="/my-project/">,并确认所有资源路径是纯相对路径(如 js/app.js),而非 ../ 或 assets/
容易被忽略的关键细节
即便你成功让 <base> 生效,它也只影响三类内容:
- HTML 属性中的纯相对路径:<img src="logo.png">、<script src="app.js"></script>、<form action="submit.php"></form>
- CSS 中的 url() 函数(如 background: url(avatar.jpg))
- 但完全不影响:fetch('./api')、import('./utils.js')、@import "reset.css"、new Worker('./worker.js')
这意味着:光靠 <base> 无法统一 JS 运行时路径,必须配合构建工具的 publicPath 或 build.base 配置,否则资源加载和路由跳转会割裂
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











