Skip to content

常见问题(FAQ)

关于如何使用 WXT 或者了解其行为方式的常见问题。

为什么不在 manifest 中添加内容脚本?

在开发过程中,WXT 动态注册内容脚本以允许它们在每次文件保存时不重新加载整个扩展而单独加载。

要查看开发中注册的内容脚本,请打开服务 worker 的控制台并运行:

javascript
await chrome.scripting.getRegisteredContentScripts();

如何在开发期间关闭浏览器的自动打开?

参见 https://wxt.dev/guide/essentials/config/browser-startup.html#disable-browser-opening

如何在开发期间保持登录到网站?

参见 https://wxt.dev/guide/essentials/config/browser-startup.html#persist-data

我的组件库在内容脚本中不起作用!

这通常是由以下两种情况(或两者兼有)导致的,当使用 createShadowRootUi 时:

  1. 添加了超出 ShadowRoot 的样式

    Details

    一些组件库会手动添加 CSS 到页面上,通过在文档的 <head> 中添加 <style><link> 元素。它们默认将此元素放在文档的 <head> 中。这导致你的样式被放置在 ShadowRoot 外面,并且隔离阻止了样式应用到你的 UI。

    当一个库这样做时,你需要告诉该库在哪里放置它的样式。以下是几种流行的组件库的文档链接:

    如果你的库不在上面列出的列表中,尝试搜索它的文档或 issues 中是否有“阴影根”、“阴影 DOM”或“CSS 容器”的相关问题。不是所有库支持阴影 DOM,你可能需要提交一个请求来请求这个功能。

    下面是为 Antd 配置样式的一个示例:

    tsx
    import { StyleProvider } from '@ant-design/cssinjs';
    import ReactDOM from 'react-dom/client';
    import App from './App.tsx';
    
    const ui = await create`ShadowRoot`Ui(ctx, {
      // ...
      onMount: (container, shadow) => {
        const cssContainer = shadow.querySelector('head')!;
        const root = ReactDOM.createRoot(container);
        root.render(
          <StyleProvider container={cssContainer}>
            <App />
          </StyleProvider>,
        );
        return root;
      },
    });
  2. UI 元素超出 ShadowRoot 外围

    Details

    这主要是由于 TeleportPortal 组件渲染元素到 DOM 的其他地方,通常在文档的 <body> 中。这通常是用于对话框或弹出窗口组件完成的。将元素渲染到 ShadowRoot 之外,因此样式不会应用到它。

    要解决此问题,你需要告诉该库提供给你的应用目标,并将其传递给 Teleport/Portal

    首先,存储 ShadowRoot 体内 <body> 元素的引用(而不是文档的 <body>):

    ts
    import { createApp } from 'vue';
    import App from './App.vue';
    
    const ui = await create`ShadowRoot`Ui(ctx, {
      // ...
      onMount: (container, shadow) => {
        const teleportTarget = shadow.querySelector('body')!;
        const app = createApp(App)
          .provide('TeleportTarget', teleportTarget)
          .mount(container);
        return app;
      },
    });
    ui.mount();
    tsx
    // hooks/PortalTargetContext.ts
    import { createContext } from 'react';
    
    export const PortalTargetContext = createContext<HTMLElement>;
    
    // entrypoints/example.content.ts
    import ReactDOM from 'react-dom/client';
    import App from './App.tsx';
    import PortalTargetContext from '~/hooks/PortalTargetContext';
    
    const ui = await create`ShadowRoot`Ui(ctx, {
      // ...
      onMount: (container, shadow) => {
        const portalTarget = shadow.querySelector('body')!;
        const root = ReactDOM.createRoot(container);
        root.render(
          <PortalTargetContext.Provider value={portalTarget}>
            <App />
          </PortalTargetContext.Provider>,
        );
        return root;
      },
    });
    ui.mount();

    然后在将 UI 部分移动到 DOM 的其他地方时使用参考:

    vue
    <script lang="ts" setup>
    import { Teleport } from 'vue';
    
    const teleportTarget = inject('TeleportTarget');
    </script>
    
    <template>
      <div>
        <Teleport :to="teleportTarget">
          <dialog>My dialog</dialog>
        </Teleport>
      </div>
    </template>
    tsx
    import { useContext } from 'react';
    import { createPortal } from 'react-dom';
    import PortalTargetContext from '~/hooks/PortalTargetContext';
    
    const MyComponent = () => {
      const portalTarget = useContext(PortalTargetContext);
    
      return <div>{createPortal(<dialog>My dialog</dialog>, portalTarget)}</div>;
    };

    如果你使用 ShadCN,参见这篇博客文章

    ::::::

两者都导致同一问题:图书馆将某些元素放在 ShadowRoot 之外,而 ShadowRoot 的隔离阻止了这些元素的样式应用到你的 UI。

两者都有相同的解决方法:告诉图书馆将元素放在 ShadowRoot 内而不是外面。有关每种情况的具体修复示例,请参阅上面提供的详细信息。

我在 WXT 上有一个 LLM 模型吗?

目前还没有,但我们正在开发中。现在,访问 https://wxt.dev 即可获取所有文档的知识库文件,这些文件包含网站上所有文档的预汇总和预格式化版本:

你不需要从整个网站爬取,这些文件已经包含了训练 WXT 上 LLM 所需的所有相关文档。但如果你愿意,也可以自己爬取并生成自己的文件!