Skip to content

资源

/assets 文件夹

<srcDir>/assets/文件夹中的任何资源将通过WXT的打包器进行处理。

要访问它们:

ts
import imageUrl from '~/assets/image.png';

const img = document.createElement('img');
img.src = imageUrl;
html
<!-- 在 HTML 标签中,您必须使用相对路径 -->
<img src="../assets/image.png" />
css
.bg-image {
  background-image: url(~/assets/image.png);
}
vue
<script>
import image from '~/assets/image.png';
</script>

<template>
  <img :src="image" />
</template>
jsx
import image from '~/assets/image.png';

<img src={image} />;

/public 文件夹

<srcDir>/public/文件夹中的文件将直接复制到输出文件夹中,不会通过WXT的打包器进行处理。

要访问它们:

ts
import imageUrl from '/image.png';

const img = document.createElement('img');
img.src = imageUrl;
html
<img src="/image.png" />
css
.bg-image {
  background-image: url(/image.png);
}
vue
<template>
  <img src="/image.png" />
</template>
jsx
<img src="/image.png" />

内容脚本中的资产

内容脚本中的资产与上述有所不同。默认情况下,当导入一个资产时,它只会返回资产的路径。这是因为Vite假设您从相同的主机加载资产。

但是,在内容脚本中,主机可以是当前窗口设置的任意网站。因此,如果您尝试从内容脚本中获取资产(作为 <img>src),它将从当前窗口的网站加载,而不是您的扩展。

要解决此问题,请使用 browser.runtime.getURL 将图像转换为完整 URL:

ts
// entrypoints/content.ts
import iconUrl from '/icon/128.png';

export default defineContentScript({
  matches: ['*://*.google.com/*'],
  main() {
    console.log(iconUrl); // "/icon/128.png"
    console.log(browser.runtime.getURL(iconUrl)); // "chrome-extension://<id>/icon/128.png"
  },
});

WASM

.wasm 文件的加载方式在各种包中有所不同,但大多数遵循基本设置:使用 JS API 加载和执行 .wasm 文件。

对于一个扩展来说,这意味着两件事:

  1. .wasm 文件必须在输出文件夹中存在,以便它可以被加载。
  2. 您必须导入加载并初始化 .wasm 文件的 JS API,通常由 NPM 包提供。

例如,假设您有一个内容脚本需要解析 TS 代码为 AST。我们将使用 @oxc-parser/wasm

首先,我们需要将 .wasm 文件复制到输出目录中。我们可以使用 WXT 模块(/guide/essentials/wxt-modules)来实现这一点:

ts
// modules/oxc-parser-wasm.ts
import { resolve } from 'node:path';

export default defineWxtModule((wxt) => {
  wxt.hook('build:publicAssets', (_, assets) => {
    assets.push({
      absoluteSrc: resolve(
        'node_modules/@oxc-parser/wasm/web/oxc_parser_wasm_bg.wasm',
      ),
      relativeDest: 'oxc_parser_wasm_bg.wasm',
    });
  });
});

运行 wxt build,您应该看到 WASM 文件被复制到您的 .output/chrome-mv3 目录中!

接下来,由于这是在内容脚本中,并且我们将在网络上加载该文件以加载它,因此我们需要将文件添加到 web_accessible_resources

ts
// wxt.config.ts
export default defineConfig({
  manifest: {
    web_accessible_resources: [
      {
        // 我们将在内容脚本中使用相同的匹配条件
        matches: ['*://*.github.com/*'],
        // 使用与 WXT 模块中相同的路径
        resources: ['/oxc_parser_wasm_bg.wasm'],
      },
    ],
  },
});

最后,我们需要在内容脚本中加载并初始化 .wasm 文件以使用它:

ts
// entrypoints/content.ts
import initWasm, { parseSync } from '@oxc-parser/wasm';

export default defineContentScript({
  matches: '*://*.github.com/*',
  async main(ctx) {
    if (!location.pathname.endsWith('.ts')) return;

    // 获取文本来自 GitHub
    const code = document.getElementById(
      'read-only-cursor-text-area',
    )?.textContent;
    if (!code) return;
    const sourceFilename = document.getElementById('file-name-id')?.textContent;
    if (!sourceFilename) return;

    // 加载 WASM 文件:
    await initWasm({
      module_or_path: browser.runtime.getURL('/oxc_parser_wasm_bg.wasm'),
    });

    // 一旦加载,我们可以使用 `parseSync`!
    const ast = parseSync(code, { sourceFilename });
    console.log(ast);
  },
});

此代码直接从 @oxc-parser/wasm 文档中获取,除了一个例外:我们手动传递文件路径。在标准 Node.js 或 Web 项目中,默认路径就足够了,因此您不需要传递任何内容。但是,扩展是不同的。您始终应该显式地将完整的 URL 传递到输出目录中的 WASM 文件(由 browser.runtime.getURL 返回)。