WXT浏览器插件开发中文教程(15)----资源加载详解

前言

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

资源加载

加载/assets 目录中的资源

<srcDir>/assets/ 目录中导入或引用的任何资源都将由 WXT 的打包器处理。

以下是访问它们的方法:

在 JS/TS 中访问 /assets 目录下的文件的方法

ts 复制代码
import imageUrl from '~/assets/image.png';
const img = document.createElement('img');
img.src = imageUrl;

在 HTML 中访问 /assets 目录下的文件的方法

html 复制代码
<!-- 在 HTML 标签中,必须使用相对路径 -->
<img src="../assets/image.png" />

在 CSS 中访问 /assets 目录下的文件的方法

css 复制代码
.bg-image {
  background-image: url(~/assets/image.png);
}

在 Vue 中访问 /assets 目录下的文件的方法

vue 复制代码
<script>
import image from '~/assets/image.png';
</script>
<template>
  <img :src="image" />
</template>

在 JSX 中访问 /assets 目录下的文件的方法

jsx 复制代码
import image from '~/assets/image.png';
<img src={image} />;

/public 目录 [​](#/public 目录 "#public-directory")

<rootDir>/public/ 目录中的文件将被原样复制到输出目录中,不会被 WXT 的打包器处理。

以下是访问它们的方法:

在 JS/TS 中访问 /public 目录下的文件的方法

ts 复制代码
import imageUrl from '/image.png';
const img = document.createElement('img');
img.src = imageUrl;

在 HTML 中访问 /public 目录下的文件的方法

html 复制代码
<img src="/image.png" />

在 CSS 中访问 /public 目录下的文件的方法

css 复制代码
.bg-image {
  background-image: url(/image.png);
}

在 Vue 中访问 /public 目录下的文件的方法

vue 复制代码
<template>
  <img src="/image.png" />
</template>

在 JSX 中访问 /public 目录下的文件的方法

jsx 复制代码
<img src="/image.png" />

警告

默认情况下,public/ 目录中的资源 无法 在内容脚本中访问。要在内容脚本中使用公共资源,必须将其添加到清单的 web_accessible_resources 数组 中。

在内容脚本中加载资源

内容脚本中的资源稍有不同。默认情况下,当你导入一个资源时,它只返回资源的路径。这是因为 Vite 假设你正在从相同的主机名加载资源。

但是,在内容脚本中,主机名是当前标签页设置的主机名。因此,如果你尝试手动加载资源,或者将其作为 <img>src 属性加载,它将从标签页的网站加载,而不是从你的扩展程序加载。

要解决这个问题,你需要使用 browser.runtime.getURL 将图片转换为完整的 URL:

entrypoints/content.ts

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 模块 来完成:

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 文件夹中!

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

wxt.config.ts

ts 复制代码
export default defineConfig({
  manifest: {
    web_accessible_resources: [
      {
        // 我们将在内容脚本中使用此匹配规则
        matches: ['*://*.github.com/*'],
        // 使用与 WXT 模块中 `relativeDest` 相同的路径
        resources: ['/oxc_parser_wasm_bg.wasm'],
      },
    ],
  },
});

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

entrypoints/content.ts

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 文档,唯一的区别是我们手动传递了一个文件路径。在标准的 NodeJS 或 Web 项目中,默认路径完全可以正常工作,因此你不需要传递任何内容。然而,扩展程序是不同的。你应该始终明确传递输出目录中 WASM 文件的完整 URL,这就是 browser.runtime.getURL 返回的内容。

运行你的扩展程序,你应该会看到 OXC 解析了 TS 文件!

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

相关推荐
GISer_Jing1 小时前
WebGL跨端兼容实战:移动端适配全攻略
前端·aigc·webgl
daols881 小时前
vue 甘特图 vxe-gantt 自定义任务条插槽模板的用法
vue.js·vxe-gantt
迦南giser1 小时前
前端性能——传输优化
前端
小白_ysf1 小时前
Vue 中常见的加密方法(对称、非对称、杂凑算法)
前端·vue.js·算法
2501_944448002 小时前
Flutter for OpenHarmony衣橱管家App实战:支持我们功能实现
android·javascript·flutter
人工智能训练7 小时前
【极速部署】Ubuntu24.04+CUDA13.0 玩转 VLLM 0.15.0:预编译 Wheel 包 GPU 版安装全攻略
运维·前端·人工智能·python·ai编程·cuda·vllm
会跑的葫芦怪8 小时前
若依Vue 项目多子路径配置
前端·javascript·vue.js
xiaoqi9229 小时前
React Native鸿蒙跨平台如何进行狗狗领养中心,实现基于唯一标识的事件透传方式是移动端列表开发的通用规范
javascript·react native·react.js·ecmascript·harmonyos
jin1233229 小时前
React Native鸿蒙跨平台剧本杀组队消息与快捷入口组件,包含消息列表展示、快捷入口管理、快捷操作触发和消息详情预览四大核心功能
javascript·react native·react.js·ecmascript·harmonyos
烬头882111 小时前
React Native鸿蒙跨平台实现二维码联系人APP(QRCodeContactApp)
javascript·react native·react.js·ecmascript·harmonyos