<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>web-components on </title>
    <link>/tags/web-components/</link>
    <description>Recent content in web-components on </description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Tue, 22 Sep 2026 21:30:00 +0800</lastBuildDate><atom:link href="/tags/web-components/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>同一页面挂多个 UI 叠加层时，接口该定在哪里？</title>
      <link>/posts/embeddable-overlay-custom-element-shadow-dom/</link>
      <pubDate>Tue, 22 Sep 2026 21:30:00 +0800</pubDate>
      
      <guid>/posts/embeddable-overlay-custom-element-shadow-dom/</guid>
      <description>宿主页面在运行时加载一个自己不参与构建的 UI 叠加层，常见做法是一段 &amp;lt;script src&amp;gt;：bundle 拉进来，自己找个容器渲染，宿主只负责给它一个位置和一份 token。社交分享按钮、地图嵌入、客服浮窗都是这个路子。micro frontend 里组合可以发生在三处：网关按路径把流量分给各自的 SPA、宿主和远端模块共享同一批依赖（Module Federation 走的是这条，共享项在构建期声明、装载时才协商版本）、运行时直接往页面里插一段 bundle。本篇是第三种。前两种在这里都用不上，因为宿主不参与 bundle 的构建，而且 N 个叠加层要同时活在同一个页面上。
要定的就是名字：入口叫什么，这个名字归谁定。
讨论有几个前提，下面每一节的结论都只在这个范围内成立：
宿主和叠加层是两套代码，两个仓库，各自发版。宿主不参与 bundle 的构建，运行时只做一件事：用 &amp;lt;script src&amp;gt; 把它拉进来。 bundle 跑在宿主页面的同一个 JS 上下文里，不是 iframe，它摸到的 window 就是宿主自己的。选同上下文是为了让叠加层直接操作宿主 DOM，省掉 postMessage 那层协议，代价是 token 和宿主的 JS 待在一起，隔离强度比 iframe 低，第三方嵌入选 iframe 通常就是为了这层隔离。本篇所有冲突都从这个前提来；它跑在什么浏览器上，也由宿主说了算。 支持范围按「两年前发布的版本」算下限：Chrome / Edge 129（2024-09-17）、Safari 18（2024-09-16）、Firefox 130（2024-09-03），iOS 跟着 Safari 18。下面每处「能不能用」都按这几个版本判，不按最新版判。构建产物的语法目标比它们还宽松：Vite 8 的 build.target 默认值 &#39;baseline-widely-available&#39; 在这个 major 固定成 [&#39;chrome111&#39;, &#39;edge111&#39;, &#39;firefox114&#39;, &#39;safari16.4&#39;, &#39;ios16.4&#39;]，默认不动就够，自己改过的要回去对一遍。 叠加层的 DOM 和样式渲染在 shadow root 里。 叠加层的定位和层级不在本篇范围。宿主祖先上的 transform、filter、contain 会换掉 position: fixed 的包含块，z-index 也要跟宿主争，这一类问题交给 top layer，但按上面那条下限得挑着用：dialog.</description>
    </item>
    
  </channel>
</rss>
