shadow dom 中 url(./icon.svg) 会 404,因其路径解析仍以宿主页面 url 为基准,而非组件文件位置;需显式重写为绝对路径、data url 或通过 adoptedstylesheets 注入预处理样式。

为什么直接写 url(./icon.svg) 在 Shadow DOM 里会 404
Shadow DOM 不改写 CSS 中的相对路径解析上下文——它仍以当前页面的 <base> 或 document URL 为基准,而不是以组件所在 JS 文件或 HTML 模板位置为准。所以 url(./icon.svg) 实际请求的是宿主页面根目录下的 /icon.svg,而非组件包内的 ./assets/icon.svg。
- 所有
@import、url()、src(如<img src="./a.png">)都受此影响 -
<link rel="stylesheet" href="./theme.css">加载后样式逃逸到全局,且路径解析失败率高 - Safari 对相对路径 resolve 更严格,Chrome 可能“碰巧”成功,但不可靠
如何安全处理 <style></style> 和 <link> 的资源路径
不能把含 <style></style> 或 <link> 的 HTML 字符串直接赋给 shadowRoot.innerHTML——前者被当文本忽略,后者加载到全局,路径失效且污染 CSP。
- 用
DOMParser解析字符串,提取<style></style>内容和<link>的href - 对提取出的 CSS 文本做路径重写:把
url(./xxx)替换为绝对 URL 或 data URL(如url(/components/my-btn/assets/xxx)) - 构造
CSSStyleSheet实例:const sheet = new CSSStyleSheet(); sheet.replaceSync(cssText); - 通过
shadowRoot.adoptedStyleSheets = [sheet]注入(注意:Firefox 115+、Chrome 73+、Safari 16.4+ 支持)
<img>、<iframe></iframe> 等元素的 src 怎么写才不丢路径
这些属性不受 Shadow DOM 隔离机制保护,路径解析完全依赖宿主文档上下文。必须显式补全,不能依赖相对路径。
- 避免
<img src="./logo.png">,改用<img src="/components/my-card/logo.png">或构建时内联为 data URL -
<iframe></iframe>同理:动态创建后设iframe.src = new URL('./widget.html', import.meta.url).href(ESM 环境) - 若用
<template></template>,里面的src仍按模板所在 HTML 文件位置解析——不是组件 JS 位置,这点极易混淆
第三方图标库(如 Font Awesome)怎么进 Shadow DOM
不能在 全局引入,也不能把 <link rel="stylesheet"> 塞进 shadowRoot——它会逃逸并可能因 CORS 失败。
- 下载 CSS 文件内容(如通过
fetch('/node_modules/@fortawesome/fontawesome-free/css/all.min.css')) - 预处理:替换所有
url(../webfonts/...)为绝对路径或 base64 data URL - 转成
CSSStyleSheet后注入adoptedStyleSheets - 字体文件(woff2 等)必须托管在同源可访问路径,否则
@font-face会静默失败
路径问题不是“写对了就能跑通”,而是必须在构建时或运行时做显式代理或重写;任何依赖浏览器默认解析的行为,在 Shadow DOM 场景下都大概率出错。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











