attachShadow样式隔离和JavaScript 沙箱

微服务样式隔离的原理是利用 Shadow DOM 技术来隔离各个微前端应用的样式。Shadow DOM 是 Web 标准的一部分,它允许将 DOM 树封装到一个隔离的影子 DOM 中,这样各个微前端应用的样式就不会相互影响,从而实现样式的隔离。
Qiankun 在每个微前端应用中使用 Shadow DOM 来包裹应用内部的 DOM 结构,以及应用所需的 CSS 样式。这样一来,即使各个微前端应用使用了相同的 CSS 类名,它们也不会相互影响,从而确保了样式的隔离。

dom的attachShadow创建影子节点,节点内和节点之外有什么关联吗?会互相影响?

attachShadow 方法创建的影子节点(shadow root)与宿主元素存在一定的关联,但是它们之间具有一定的隔离性,不会互相影响。

宿主元素(host element)是指通过 attachShadow 创建影子节点的元素,它拥有一个独立的影子节点。在影子节点内部定义的样式和元素,以及事件处理程序,都会局限在影子节点内部生效,不会泄漏到宿主元素所在的文档中。

具体来说,影子节点内的样式(CSS)不会影响到宿主元素,宿主元素的样式也不会影响影子节点内的元素。这意味着你可以在影子节点内定义特定的样式,而不用担心与外部样式的冲突。

同样,影子节点内的事件处理程序也是隔离的。在影子节点内注册的事件处理程序只会响应影子节点内的事件,不会响应宿主元素或其他元素的事件。这样可以确保影子节点内的事件逻辑不会影响到宿主元素及其周围的元素。

需要注意的是,影子节点内部的内容可以与宿主元素内部的内容进行交互。例如,在影子节点内部触发的事件可以通过事件冒泡机制传递到宿主元素或其他位于宿主元素之外的元素。但是,它们仍然保持了相对的独立性和隔离性。

通过使用 Shadow DOM 技术,我们可以将页面的功能和样式封装到独立的影子节点中,从而实现更好的代码组织和维护性,避免全局样式和事件的冲突,并改善模块化的开发体验。

Shadow DOM 技术原理,用代码去表达出来

当然可以!下面是一个更详细的代码示例,使用中文解释 Shadow DOM 技术的原理:

DOCTYPE html>
<html>
<head>
  <style>
    /* 外部样式 */
    .container {
      border: 1px solid #ccc;
      padding: 10px;
    }
  style>
head>
<body>
  
  <div id="host-element" class="container">
    
    <p>这是宿主元素内的文本。p>
    <button>点击我button>
  div>

  <script>
    // 获取宿主元素
    const hostElement = document.getElementById('host-element');

    // 创建影子根节点
    const shadowRoot = hostElement.attachShadow({ mode: 'open' });

    // 创建影子 DOM 的样式
    const styles = `
      /* 影子 DOM 样式 */
      .container {
        background-color: #f5f5f5;
        border: 1px solid #999;
        padding: 20px;
      }
      p {
        color: blue;
      }
    `;

    // 创建样式元素并将样式添加到影子根节点中
    const stylesElement = document.createElement('style');
    stylesElement.textContent = styles;
    shadowRoot.appendChild(stylesElement);

    // 创建影子 DOM 中的内容
    const shadowContent = document.createElement('div');
    shadowContent.textContent = '这是影子 DOM 内的文本。';
    shadowRoot.appendChild(shadowContent);

    // 在影子 DOM 中注册事件
    shadowContent.addEventListener('click', () => {
      console.log('点击了影子 DOM 内的内容');
    });
    
    // 将影子元素添加到影子根节点中
    shadowRoot.appendChild(shadowElement);
  script>
body>
html>

在这个示例中,我们有一个 HTML 文档,其中包含了一个宿主元素(

),宿主元素内有一些文本内容和一个按钮。

通过 JavaScript,我们首先获取了宿主元素,并使用 attachShadow 方法为它创建了一个影子根节点(shadow root),并指定 mode: 'open' 以允许外部访问影子 DOM。这样宿主元素就有了一个独立的影子 DOM。

接下来,我们创建了影子 DOM 的样式,定义在影子 DOM 内有效的 CSS 样式。我们通过创建一个样式元素,并设置其 textContent 为样式字符串,然后将样式元素添加到影子根节点中。这样,宿主元素内的样式不会影响到影子 DOM,而影子 DOM 内的样式也不会影响到宿主元素以及其他部分的样式。

然后,我们创建了影子 DOM 内的内容,这个例子中是一个 div 元素,内容为 “这是影子 DOM 内的文本。”。我们将内容元素添加到影子根节点中,这样影子 DOM 内的内容就与宿主元素内的内容进行了分离。

最后,我们在影子 DOM 中注册了一个点击事件的监听器,并打印了相关信息。这样,当点击影子 DOM 内的内容时,我们就会在控制台中看到相应的日志信息。这展示了影子 DOM 的事件隔离性,影子 DOM 内的事件不会影响到宿主元素以及其他部分。

通过 Shadow DOM 技术,我们可以实现样式和内容的封装、隔离和作用域限制,使得宿主元素和影子 DOM 内的元素可以独立开发和维护,相互之间不会产生冲突或干扰。

Shadow DOM 技术来隔离各个微前端应用的样式,进一步介绍Shadow DOM 技术底层原理

Shadow DOM 技术是 Web 标准中一种用于创建封装的、独立的 DOM 子树的技术。它的设计目的是为了将组件的样式、结构和行为封装起来,从而避免全局 CSS 样式或 JavaScript 代码的影响,特别适用于组件化开发和构建复杂的 Web 应用程序。

Shadow DOM 技术的底层原理:

  1. Shadow DOM 树:在使用 Shadow DOM 技术时,一个元素可以拥有一个或多个 Shadow DOM 树(shadow tree),每个 Shadow DOM 树是一个完全隔离的 DOM 子树。在 Shadow DOM 树中,可以包含自己的 HTML 结构、CSS 样式和 JavaScript 逻辑,与外部 DOM 结构相互独立。

  2. Shadow Host:拥有 Shadow DOM 的元素是其所属的 Shadow DOM 树的宿主元素,称为 Shadow Host。Shadow Host 可以是普通的 HTML 元素,也可以是自定义的 Web 组件。

  3. Shadow Root:每个 Shadow Host 对应一个 Shadow Root,它是 Shadow DOM 树的根节点,包含了该树的全部内容,包括 HTML 结构、CSS 样式和 JavaScript 逻辑。

  4. 封闭性:通过 Shadow DOM 技术创建的 Shadow DOM 树是封闭的,意味着它的内部内容对外部是不可见的。这意味着样式和脚本不会泄露或影响 Shadow DOM 外部的文档。

  5. 作用域 CSS:Shadow DOM 中的样式表会默认地被封装在 Shadow DOM 内部,这样它们不会影响到外部文档或其他 Shadow DOM 中的元素。这意味着即使使用全局选择器,也难以破坏 Shadow DOM 的封装性。

通过 Shadow DOM 技术,开发者可以创建独立的、封闭的 DOM 子树,每棵树都有自己的作用域和样式隔离,从而可以更好地构建大型 Web 应用中的组件化结构,并解决全局样式和脚本的污染问题。这种技术非常适合于构建现代的 Web 应用,特别是在微前端架构中实现独立应用的样式和行为隔离。

JavaScript 沙箱

JavaScript 沙箱的原理是通过使用浏览器的 JavaScript 的隔离机制来隔离各个微前端应用的 JavaScript 代码。Qiankun 利用了浏览器提供的 iframe 标签,将各个微前端应用作为独立的 iframe 加载到主应用中。每个 iframe 都有自己独立的 JavaScript 执行环境,因此它们之间的 JavaScript 代码是相互隔离的。

此外,在配合使用沙箱工具(如 openKyle 的 single-spa 库)时,Qiankun 还能对微前端应用中的一些敏感 DOM 操作进行拦截,通过代理机制和特定的沙箱环境来限制微前端应用对主应用的影响,从而保证了微前端应用之间的安全隔离。

综合来看,Qiankun 借助 Shadow DOM 和 iframe 技术,以及相关的沙箱工具,实现了微服务样式隔离和 JavaScript 沙箱的功能,确保了各个微前端应用在样式和 JavaScript 代码上的相互隔离,从而使得多个微前端应用可以安全、独立地运行在同一个页面上。

qiankun 微服务的 JS 沙箱,是指 qiankun 在每个子应用之间搭建的一种隔离机制,使用该机制可以构建一个安全的 JavaScript 运行环境,防止应用之间的相互干扰和污染。

该机制的实现原理,是通过将各个子应用中的 JS 代码加以隔离,使用 iframe 创建子应用,并在 iframe 中启动应用的 JS 代码,使每个子应用之间的 JS 运行环境互相隔离。这种嵌套式的运行环境,像是每个子应用都运行在自己的“沙箱”中一样,避免了子应用之间的干扰和污染。

在实现上,qiankun 通过封装一个 proxy 对象,将子应用中通过 window 对象访问全局变量的方式进行拦截,并将其映射到子应用自己的沙箱运行环境中。这样,即使不同子应用中使用了相同的全局变量名,也不会产生冲突,保证子应用之间的隔离性。

下面是一个简单的示例,展示了如何在子应用中访问全局变量和局部变量,并进行拦截和映射:

// proxy 对象对外暴露了一个 get 方法,用于拦截对象的属性访问
const sandboxProxy = new Proxy(window, {
  get(target, key) {
    // 如果访问的是全局变量,将其映射到当前子应用的沙箱环境,避免与其他子应用冲突
    if (key in target) {
      return Reflect.get(target, key);
    }
    // 如果访问的是局部变量,则返回当前子应用自己的变量
    return Reflect.get(自己的变量, key);
  }
});

// 创建一个 iframe,并将其设置为子应用的沙箱环境
const appContainer = document.createElement('iframe');
appContainer.src = 'http://localhost:8080'; // 子应用的入口地址
appContainer.sandbox = 'allow-scripts'; // 允许执行 JS 脚本,但不允许访问同源策略外的内容
appContainer.contentWindow = sandboxProxy; // 使用自定义的 proxy 对象作为 window 对象
document.body.appendChild(appContainer);

通过使用 qiankun 微服务的 JS 沙箱,我们可以在微前端架构中实现各个子应用之间的隔离和安全性,提高应用的可维护性和可靠性。

你可能感兴趣的:(javascript)