base href值必须以/开头且结尾带斜杠,否则浏览器静默忽略导致资源路径全错;常见错误如/subapp、assets/、%public_url%/等均失效,须严格校验格式并分层验证html、路由与网络请求。

base href 值必须以 / 开头且结尾带斜杠,否则测试中资源路径全错
自动化测试(如 Puppeteer、Playwright)加载页面后,若 <base href> 写成 /subapp 或 assets/,浏览器会静默忽略该标签——测试脚本里 page.locator('img') 能找到元素,但 img.src 实际解析为当前 URL 拼接,导致断言失败或截图空白。这不是测试代码问题,是 HTML 解析阶段就崩了。
常见翻车点:
-
href="/subapp"→ Firefox 截断为/subappcss/,style.css请求变成/subappcss/style.css -
href="static/"→ 缺协议和根斜杠,整条<base>被丢弃,script src="app.js"仍按http://localhost:3000/page1/app.js加载 -
href="%PUBLIC_URL%/"→ 构建未替换,字面量发到浏览器,等同于无效
测试前务必检查渲染后的 HTML 源码,确认 <base href="/subapp/"> 真实存在且位置正确。
测试脚本里不能依赖 document.baseURI 做路径断言
document.baseURI 确实返回 <base href> 的值,但它只是只读快照,不参与资源加载逻辑。在 Playwright 中执行 await page.evaluate(() => document.baseURI) 可能返回预期值,但 page.waitForURL('/subapp/home') 依然失败——因为前端路由根本没配 basename,router.push('/home') 还是跳到 /home。
真实路径匹配必须分层验证:
- HTML 层:检查
<base href="/subapp/">是否在最顶部 - JS 路由层:Vue Router 要有
createRouter({ base: '/subapp/' }),React Router v6+ 要包<router basename="/subapp"></router> - 网络层:用
page.route()拦截请求,确认script和css真的从/subapp/js/app.js加载
Playwright/Puppeteer 中检测 base 标签是否生效的最小验证法
别等整个页面跑完再查,用 DOM 快照第一时间抓问题:
await page.evaluate(() => {
const base = document.querySelector('base');
if (!base || !base.href) throw new Error('missing or empty <base>');
if (!base.href.startsWith('http') && !base.href.startsWith('/'))
throw new Error(`invalid base.href: ${base.href}`);
if (base.href.endsWith('/')) return;
throw new Error(`base.href must end with '/' but got ${base.href}`);
});
这个检查应放在 page.goto() 后立即执行。它比等 page.waitForLoadState('networkidle') 更早暴露配置错误,避免后续所有断言都因资源 404 而失败。
微前端或子应用场景下,base 标签和 publicPath 双重叠加的测试陷阱
Webpack 的 publicPath: '/subapp/' 和 HTML 的 <base href="/subapp/"> 同时存在,会导致 chunk 加载路径变成 /subapp/subapp/js/app.js。测试时表现为白屏、控制台报 Failed to load module script,但错误堆栈里看不出根源。
排查要点:
- 打开 DevTools → Network → 刷一次页面,看 JS/CSS 请求的真实 URL 是什么
- 对比构建产物中
index.html里的script src是写死的/subapp/js/app.js,还是相对路径js/app.js - 若
script src是相对路径,则<base>生效;若是绝对路径,则publicPath已介入,<base>多余
真正安全的做法是:构建工具管资源路径(publicPath),HTML 只管路由基准(<base>),二者绝不重叠。测试脚本里要分别断言这两层是否被正确注入。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











