WXT浏览器插件开发中文教程(3)----WXT全部入口项详解

494 阅读6分钟

前言

大家好,我是倔强青铜三。是一名热情的软件工程师,我热衷于分享和传播IT技术,致力于通过我的知识和技能推动技术交流与创新,欢迎关注我,微信公众号:倔强青铜三。欢迎点赞、收藏、关注,一键三连!!!

入口项

WXT 在捆绑扩展时,将 entrypoints/ 目录中的文件作为输入。这些文件可以是 HTML、JS、CSS 或 Vite 支持的任何变体(如 Pug、TS、JSX、SCSS 等)。

以下是一个入口项示例:

📂 entrypoints/
   📂 popup/
      📄 index.html
      📄 main.ts
      📄 style.css
   📄 background.ts
   📄 content.ts

已列出与未列出

对于网络扩展,有两种类型的入口项:

  • 已列出:在 manifest.json 中引用
  • 未列出:不在 manifest.json 中引用

在 WXT 的其余文档中,已列出的入口项按名称引用。例如:

  • 弹出窗口
  • 选项
  • 背景
  • 内容脚本
  • 等等

一些“未列出”的入口项示例:

  • 扩展安装时显示的欢迎页面
  • 内容脚本注入到页面主世界中的 JS 文件

提示

无论入口项是已列出还是未列出,它都会被捆绑到扩展中,并在运行时可用。

添加入口项

入口项可以定义为单个文件或包含 index 文件的目录。

单个文件目录

📂 entrypoints/
   📄 background.ts
📂 entrypoints/
   📂 background/
      📄 index.ts

入口项的名称决定其类型,即已列出与未列出。在此示例中,“background” 是 背景入口项 的名称。

有关已列出入口项的完整列表及其文件名模式,请参阅 入口项类型 部分。

定义清单选项

大多数已列出的入口点需要添加到 manifest.json 的选项。但使用 WXT 时,无需在单独的文件中定义这些选项,而是 在入口项文件本身内定义这些选项

例如,以下是如何为内容脚本定义 matches

entrypoints/content.ts

export default defineContentScript({
  matches: ['*://*.wxt.dev/*'],
  main() {
    // ...
  },
});

对于 HTML 入口项,选项配置为 <meta> 标签。例如,要为 MV2 弹出窗口使用 page_action

<!doctype html>
<html lang="en">
  <head>
    <meta name="manifest.type" content="page_action" />
  </head>
</html>

请参阅 入口项类型 部分,以获取可在每个入口项内配置的选项列表及其定义方法。

构建扩展时,WXT 会查看入口项中定义的选项,并据此生成清单。

入口项类型

background脚本

Chrome 文档Firefox 文档

对于 MV2,background脚本作为脚本添加到后台页面。对于 MV3,background脚本变为服务工作线程。

文件名输出路径
entrypoints/background.[jt]s/background.js
entrypoints/background/index.[jt]s/background.js

最小化并带有清单选项

export default defineBackground(() => {
  // 背景加载时执行
});
export default defineBackground({
  // 设置清单选项
  persistent: undefined | true | false,
  type: undefined | 'module',
  // 如果背景应从某些构建中移除,则设置 include/exclude
  include: undefined | string[],
  exclude: undefined | string[],
  main() {
    // 背景加载时执行,不能是异步的
  },
});

书签

Chrome 文档Firefox 文档

文件名输出路径
entrypoints/bookmarks.html/bookmarks.html
entrypoints/bookmarks/index.html/bookmarks.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>标题</title>
    <!-- 如果页面应从某些构建中移除,则设置 include/exclude -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

内容脚本

Chrome 文档Firefox 文档

有关在内容脚本中创建 UI 和包含 CSS 的更多信息,请参阅 内容脚本 UI

文件名输出路径
entrypoints/content.[jt]sx?/content-scripts/content.js
entrypoints/content/index.[jt]sx?/content-scripts/content.js
entrypoints/<name>.content.[jt]sx?/content-scripts/<name>.js
entrypoints/<name>.content/index.[jt]sx?/content-scripts/<name>.js
export default defineContentScript({
  // 设置清单选项
  matches: string[],
  excludeMatches: undefined | [],
  includeGlobs: undefined | [],
  excludeGlobs: undefined | [],
  allFrames: undefined | true | false,
  runAt: undefined | 'document_start' | 'document_end' | 'document_idle',
  matchAboutBlank: undefined | true | false,
  matchOriginAsFallback: undefined | true | false,
  world: undefined | 'ISOLATED' | 'MAIN',
  // 如果背景应从某些构建中移除,则设置 include/exclude
  include: undefined | string[],
  exclude: undefined | string[],
  // 配置 CSS 如何注入到页面
  cssInjectionMode: undefined | "manifest" | "manual" | "ui",
  // 配置内容脚本的注册方式
  registration: undefined | "manifest" | "runtime",
  main(ctx: ContentScriptContext) {
    // 内容脚本加载时执行,可以是异步的
  },
});

开发者工具

Chrome 文档Firefox 文档

请遵循 开发者工具示例 以添加不同的面板和窗格。

文件名输出路径
entrypoints/devtools.html/devtools.html
entrypoints/devtools/index.html/devtools.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- 如果页面应从某些构建中移除,则设置 include/exclude -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

历史记录

Chrome 文档Firefox 文档

文件名输出路径
entrypoints/history.html/history.html
entrypoints/history/index.html/history.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>标题</title>
    <!-- 如果页面应从某些构建中移除,则设置 include/exclude -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

新标签页

Chrome 文档Firefox 文档

文件名输出路径
entrypoints/newtab.html/newtab.html
entrypoints/newtab/index.html/newtab.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>标题</title>
    <!-- 如果页面应从某些构建中移除,则设置 include/exclude -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

选项

Chrome 文档Firefox 文档

文件名输出路径
entrypoints/options.html/options.html
entrypoints/options/index.html/options.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>选项标题</title>
    <!-- 自定义清单选项 -->
    <meta name="manifest.open_in_tab" content="true|false" />
    <meta name="manifest.chrome_style" content="true|false" />
    <meta name="manifest.browser_style" content="true|false" />
    <!-- 如果页面应从某些构建中移除,则设置 include/exclude -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

弹出窗口

Chrome 文档Firefox 文档

文件名输出路径
entrypoints/popup.html/popup.html
entrypoints/popup/index.html/popup.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <!-- 在清单中设置 `action.default_title` -->
    <title>默认弹出窗口标题</title>
    <!-- 自定义清单选项 -->
    <meta
      name="manifest.default_icon"
      content="{
        16: '/icon-16.png',
        24: '/icon-24.png',
        ...
      }"
    />
    <meta name="manifest.type" content="page_action|browser_action" />
    <meta name="manifest.browser_style" content="true|false" />
    <!-- 如果页面应从某些构建中移除,则设置 include/exclude -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

沙盒

Chrome 文档

仅限 Chromium

Firefox 不支持沙盒页面。

文件名输出路径
entrypoints/sandbox.html/sandbox.html
entrypoints/sandbox/index.html/sandbox.html
entrypoints/<name>.sandbox.html/<name>.html
entrypoints/<name>.sandbox/index.html/<name>.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>标题</title>
    <!-- 如果页面应从某些构建中移除,则设置 include/exclude -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

侧边面板

Chrome 文档Firefox 文档

在 Chrome 中,侧边面板使用 side_panel API,而在 Firefox 中则使用 sidebar_action API。

文件名输出路径
entrypoints/sidepanel.html/sidepanel.html
entrypoints/sidepanel/index.html/sidepanel.html
entrypoints/<name>.sidepanel.html/<name>.html`
entrypoints/<name>.sidepanel/index.html/<name>.html`
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>默认侧边面板标题</title>
    <!-- 自定义清单选项 -->
    <meta
      name="manifest.default_icon"
      content="{
        16: '/icon-16.png',
        24: '/icon-24.png',
        ...
      }"
    />
    <meta name="manifest.open_at_install" content="true|false" />
    <meta name="manifest.browser_style" content="true|false" />
    <!-- 如果页面应从某些构建中移除,则设置 include/exclude -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

未列出的 CSS

按照 Vite 的指南设置首选的预处理器:vitejs.dev/guide/featu…

CSS 入口点总是未列出的。要将 CSS 添加到内容脚本,请参阅 内容脚本 文档。

文件名输出路径
entrypoints/<name>.(css|scss|sass|less|styl|stylus)/<name>.css
entrypoints/<name>/index.(css|scss|sass|less|styl|stylus)/<name>.css
entrypoints/content.(css|scss|sass|less|styl|stylus)/content-scripts/content.css
entrypoints/content/index.(css|scss|sass|less|styl|stylus)/content-scripts/content.css
entrypoints/<name>.content.(css|scss|sass|less|styl|stylus)/content-scripts/<name>.css
entrypoints/<name>.content/index.(css|scss|sass|less|styl|stylus)/content-scripts/<name>.css
body {
  /* ... */
}

未列出的页面

文件名输出路径
entrypoints/<name>.html/<name>.html
entrypoints/<name>/index.html/<name>.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>标题</title>
    <!-- 如果页面应从某些构建中移除,则设置 include/exclude -->
    <meta name="manifest.include" content="['chrome', ...]" />
    <meta name="manifest.exclude" content="['chrome', ...]" />
  </head>
  <body>
    <!-- ... -->
  </body>
</html>

页面可通过 /<name>.html 访问:

const url = browser.runtime.getURL('/<name>.html');
console.log(url); // "chrome-extension://<id>/<name>.html"

未列出的脚本

文件名输出路径
entrypoints/<name>.[jt]sx?/<name>.js
entrypoints/<name>/index.[jt]sx?/<name>.js

最小化并带有选项

export default defineUnlistedScript(() => {
  // 脚本加载时执行
});
export default defineUnlistedScript({
  // 如果脚本应从某些构建中移除,则设置 include/exclude
  include: undefined | string[],
  exclude: undefined | string[],
  main() {
    // 脚本加载时执行
  },
});

脚本可从 /<name>.js 访问:

const url = browser.runtime.getURL('/<name>.js');
console.log(url); // "chrome-extension://<id>/<name>.js"

你需要负责在需要的地方加载/运行这些脚本。如果需要,别忘了将脚本及相关资源添加到 web_accessible_resources

最后感谢阅读!欢迎关注我,微信公众号倔强青铜三。欢迎点赞收藏关注,一键三连!!!