当前位置: 首页 > 知识库问答 >
问题:

前端 - 使用 wxt 框架开发浏览器扩展遇到的问题?

岳茂
2024-12-18

这是 A 扩展注入的 content 代码

export default defineContentScript({
  matches: ['<all_urls>'],
  cssInjectionMode: 'ui',
  runAt: 'document_end',
  async main(ctx) {
    console.log('执行 main 函数');
    const ui = await createShadowRootUi(ctx, {
      name: 'example-ui',
      position: 'inline',
      onMount: (uiContainer) => {
        console.log('执行 onMount 函数');
        const app = document.createElement('div');
        uiContainer.append(app);
        const root = createRoot(app);
        root.render(
          <StrictMode>
            <App></App>
          </StrictMode>,
        );
        return root;
      },
      onRemove: (root) => {
        console.log('执行 unmount 函数');
        root?.unmount();
      },
    });
    ui.mount();
  },
});

这是 B 扩展注入的 content 代码

export default defineContentScript({
  matches: ['<all_urls>'],
  async main(ctx) {
    // 给 window 注入 __cls-context__  表示这个是 content 脚本
    window['__cls-context__'] = 'content';
    const ui = await createIntegratedUi(ctx, {
      position: 'inline',
      onMount: (uiContainer) => {
        const app = document.createElement('div');
        uiContainer.append(app);
        const root = createRoot(app);
        root.render(
          <StrictMode>
            <App></App>
          </StrictMode>,
        );
        return root;
      },
      onRemove: (root) => {
        root?.unmount();
      },
    });
    ui.mount();
  },
});

这两个扩展都独立打包。
有用户反映装了 B 扩展后 A 扩展就失效了,通过调试发现如果扩展 B 安装后,扩展 A 的 unmount 函数就会执行,导致扩展 A 的功能不见了。
不知道大家在使用 wxt 时是否遇到这种问题,这问题感觉太奇怪了

共有2个答案

桂飞翼
2024-12-18

使用 Shadow DOM 来隔离它们的样式和 DOM 结构,这样两个扩展不会相互干扰。

A扩展的改动

在 onMount 函数中,添加了 Shadow DOM 的创建:

const shadowRoot = uiContainer.attachShadow({ mode: 'open' });
const app = document.createElement('div');
shadowRoot.append(app);

B扩展的改动

同样在 onMount 函数中,添加了 Shadow DOM 的创建:

const shadowRoot = uiContainer.attachShadow({ mode: 'open' });
const app = document.createElement('div');
shadowRoot.append(app);

完整改动示例

A 扩展的 content 代码

export default defineContentScript({
  matches: ['<all_urls>'],
  cssInjectionMode: 'ui',
  runAt: 'document_end',
  async main(ctx) {
    console.log('执行 main 函数');
    const ui = await createShadowRootUi(ctx, {
      name: 'example-ui',
      position: 'inline',
      onMount: (uiContainer) => {
        console.log('执行 onMount 函数');
        const shadowRoot = uiContainer.attachShadow({ mode: 'open' }); // 添加了这行
        const app = document.createElement('div');
        shadowRoot.append(app); // 修改了这行
        const root = createRoot(app);
        root.render(
          <StrictMode>
            <App></App>
          </StrictMode>,
        );
        return root;
      },
      onRemove: (root) => {
        console.log('执行 unmount 函数');
        root?.unmount();
      },
    });
    ui.mount();
  },
});

B 扩展的 content 代码

export default defineContentScript({
  matches: ['<all_urls>'],
  async main(ctx) {
    // 给 window 注入 __cls-context__ 表示这个是 content 脚本
    window['__cls-context__'] = 'content';
    const ui = await createIntegratedUi(ctx, {
      position: 'inline',
      onMount: (uiContainer) => {
        const shadowRoot = uiContainer.attachShadow({ mode: 'open' }); // 添加了这行
        const app = document.createElement('div');
        shadowRoot.append(app); // 修改了这行
        const root = createRoot(app);
        root.render(
          <StrictMode>
            <App></App>
          </StrictMode>,
        );
        return root;
      },
      onRemove: (root) => {
        root?.unmount();
      },
    });
    ui.mount();
  },
});
司寇星海
2024-12-18

回答

在使用 wxt 框架开发浏览器扩展时,如果两个扩展都试图在相同的页面上注入 UI,可能会发生冲突。这通常是因为两个扩展都试图修改相同的 DOM 结构或使用了相同的挂载机制。

在你的案例中,扩展 A 使用 createShadowRootUi 方法创建了一个 Shadow Root UI,而扩展 B 使用 createIntegratedUi 方法创建了一个集成 UI。这两个方法可能在内部有不同的 DOM 挂载逻辑,但都可能影响到页面的 DOM 结构。

当扩展 B 安装后,扩展 A 的 unmount 函数被执行,这通常意味着扩展 A 的 UI 被从 DOM 中移除。这可能是因为扩展 B 的 UI 挂载逻辑导致了 DOM 结构的变化,从而触发了扩展 A 的卸载逻辑。

为了解决这个问题,你可以尝试以下几种方法:

  1. 确保 UI 挂载位置不冲突

    • 检查两个扩展的 UI 是否挂载到了相同的 DOM 元素上。
    • 尝试为扩展 A 和扩展 B 指定不同的挂载点或使用不同的挂载方法。
  2. 使用命名空间或唯一标识符

    • 在创建 UI 时,为扩展 A 和扩展 B 使用不同的命名空间或唯一标识符,以避免冲突。
  3. 调试和日志记录

    • 增加更多的日志记录,以便更好地理解扩展 A 的 unmount 函数被触发的原因。
    • 使用浏览器的开发者工具来观察 DOM 结构的变化。
  4. 检查 wxt 框架的文档和社区

    • 查看 wxt 框架的官方文档,了解是否有关于多个扩展共存的最佳实践或指导。
    • 搜索或询问 wxt 框架的社区,看看是否有人遇到过类似的问题并找到了解决方案。

这个问题可能涉及到多个方面的因素,需要仔细调试和分析才能找到根本原因。希望这些建议能帮助你解决问题。

 类似资料:
  • 当读完了这个综述和入门之后,就可以开始创建应用(扩展)和WebApp了。注意:WebApp 是通过应用(扩展)的方式实现的,所以除非特别声明,本页所有内容都适用于WebApp。

  • 每个桌面浏览器都有一套开发工具,开箱即用,您可以将他们添加到您的浏览器的扩展或插件。 以下是两个具有一些实用功能的Chrome扩展程序,可帮助您调试设计。 Emmet Re:View Emmet Re:View是一个工具,它可以让你轻松查看您的网站在每个媒体查询(media queries)中的样子,并同步所有页面的滚动。 你可以在他们的网站上看到它的演示。 Download on the Chr

  • 问题内容: 我正在尝试使用Play输出生成的图像。我不确定我的问题是否特定于Play。我正在尝试执行以下PHP代码相同的操作: 它看起来像我需要使用的,但我不知道如何从获取到的是希望作为其参数。 行动: 问题答案: 我在源代码中找到了导致该解决方案的示例: 在视图模板中使用引用。 由于某种原因,即使没有指定内容类型它也可以工作,但是我不确定如何。代码中包含了它,所以我保留了它,至少直到找到不使用它

  • 我想为我的浏览器扩展写一个验收测试。我尝试通过selenium启动扩展,但似乎无法访问Popup的内容。有人能建议我如何用selenium或任何其他方法来为浏览器扩展编写UI/验收测试吗?多谢了。

  • 第十三章介绍了如何开发一个Web框架,通过介绍MVC、路由、日志处理、配置处理完成了一个基本的框架系统,但是一个好的框架需要一些方便的辅助工具来快速的开发Web,那么我们这一章将就如何提供一些快速开发Web的工具进行介绍,第一小节介绍如何处理静态文件,如何利用现有的twitter开源的bootstrap进行快速的开发美观的站点,第二小节介绍如何利用前面介绍的session来进行用户登录处理,第三小

  • 问题内容: 我正在从Firefox 3.5开始为新服务开发Web应用程序。 界面设计是无表的,仅使用divs + CSS和性能良好的做法。 现在,尽管与Safari兼容仅花费了很少的时间,但IE还是很痛苦。 我的问题是:有什么可以用来加速跨浏览器检查的吗?例如,我已经知道FF和IE之间的许多区别,但是使用特定工具可能会有所帮助。 你能建议一个吗? 谢谢, 猩红 问题答案: 跨浏览器开发 没有工具可

  • 问题内容: 我是浏览器扩展开发的新手,我了解浏览器扩展更改页面并向其中注入代码的概念。 有没有办法可以扭转这个方向?我编写了一个扩展程序,提供了一组API,想要使用该扩展程序的网站可以检测到该扩展程序的存在,如果存在,该网站可以调用诸如这样的API方法。在Chrome,Firefox和Safari中可能吗? 例: Google创建了一个名为BeautifierExtension的新扩展。它具有一组

  • Mooa 是一个为 Angular 服务的微前端框架,它是一个基于 single-spa,针对 IE 10 及 IFRAME 优化的微前端解决方案。 Mooa 概念 Mooa 框架与 Single-SPA 不一样的是,Mooa 采用的是 Master-Slave 架构,即主-从式设计。 对于 Web 页面来说,它可以同时存在两个到多个的 Angular 应用:其中的一个 Angular 应用作为主