
示例工程【免费下载链接】chrome-extensions-samplesChrome Extensions Samples项目地址https://gitcode.com/gh_mirrors/ch/chrome-extensions-samples点击查看免费下载本篇技术指南基于 chrome-extensions-samples 仓库中的 functional-samples/cookbook.wasm-helloworld-print 示例讲解如何在 Manifest V3MV3扩展的 Service Worker 中通过 ES Module 方式加载并调用 WebAssemblyWASM模块。读完本文你将掌握 MV3 下wasm-unsafe-evalCSP 指令的配置方法、type: module声明 Service Worker 的要点以及基于 Rust wasm-pack 的完整构建与调用链路。为什么 MV3 中加载 WASM 需要特殊配置Manifest V3 扩展默认执行严格的内容安全策略Content Security PolicyCSP扩展页面与 Service Worker 的默认策略不允许执行不受信任的代码。WASM 模块的实例化在 CSP 语境下被视作一种不安全求值unsafe-eval行为因此在 MV3 中加载 WASM 之前必须先在 manifest 中为extension_pages显式声明wasm-unsafe-eval指令否则浏览器会直接拒绝实例化 WASM 模块。本示例的 manifest.json 正是这样配置的{ name: WASM Load Example - Helloworld, version: 1.0, manifest_version: 3, description: Shows how to use WebAssembly (WASM) as a module in Manifest V3., background: { service_worker: background.js, type: module }, content_security_policy: { extension_pages: default-src self wasm-unsafe-eval } }两个关键点content_security_policy.extension_pages设置为default-src self wasm-unsafe-eval在默认self的基础上放行 WASM 求值background.service_worker增加type: module将 Service Worker 声明为 ES Module这是导入 wasm-pack 生成的 ES Module 胶水代码的前提详见下文。运行扩展并验证 WASM 输出加载方式克隆本仓库git clone后进入chrome-extensions-samples目录。打开 Chrome 的扩展管理页开启开发者模式选择加载已解压的扩展程序指向本示例目录functional-samples/cookbook.wasm-helloworld-print。在扩展列表中定位名为WASM Load Example - Helloworld的扩展打开其 Service Worker 的调试控制台点击Service Worker链接。预期输出扩展安装触发chrome.runtime.onInstalled事件后Service Worker 控制台会打印出以下三行日志[from wasm] Inited. [from wasm] Hello World! [from wasm] Hello John这三行日志分别来自 Rust 侧的main、print、print_with_value三个导出函数详见下文源码分析它们通过web_sys::console直接写入浏览器控制台直观证明 WASM 模块已在 MV3 Service Worker 环境中成功实例化并完成函数调用。源码链路分析从 Rust 到浏览器控制台整个示例的调用链可以分为三层我们可以逐一在仓库中核对源码实现。第一层Rust 侧导出函数wasm/src/lib.rsuse wasm_bindgen::prelude::*; use web_sys::console; // will be called when the wasm module is loaded // https://rustwasm.github.io/docs/wasm-bindgen/reference/attributes/on-rust-exports/start.html #[wasm_bindgen(start)] pub fn main() { console::log_1([from wasm] Inited..into()); } #[wasm_bindgen] pub fn print() { console::log_1([from wasm] Hello World!.into()); } #[wasm_bindgen] pub fn print_with_value(value: str) { // with 2-args log function console::log_2([from wasm] Hello.into(), value.into()); }需要留意的三个细节#[wasm_bindgen(start)]标注的main函数会在 WASM 模块实例化完成后自动执行对应 wasm-bindgen 的 start 属性因此Inited.日志不需要显式调用就会出现#[wasm_bindgen]宏把普通 Rust 函数导出为可被 JS 调用的接口web_sys::console提供的log_1/log_2分别对应浏览器console.log的单参数与双参数形式str通过.into()转换为JsValue。工程配置见 wasm/Cargo.toml[package] name helloworld-demo version 0.1.0 edition 2021 [lib] crate-type [cdylib] [dependencies] wasm-bindgen 0.2.84 web-sys { version 0.3.61, features [console] }其中crate-type [cdylib]是编译成 WASM 动态库的标准配置web-sys显式开启consolefeature 才能使用控制台相关 API。第二层wasm-pack 生成的胶水代码wasm/pkg/wasm-pack build --target web会在wasm/pkg目录产出四类文件helloworld_demo_bg.wasm真正的二进制 WASM 模块helloworld_demo.jsES Module 形式的 JS 胶水代码负责加载与实例化 WASM、在 JS 与 WASM 内存之间搬运字符串等helloworld_demo.d.ts与helloworld_demo_bg.wasm.d.tsTypeScript 类型声明。从生成的 helloworld_demo.d.ts 可以看到对外暴露的接口与 Rust 侧一一对应export function main(): void; export function print(): void; export function print_with_value(value: string): void; export default function __wbg_init(module_or_path?: InitInput | PromiseInitInput): PromiseInitOutput;胶水代码内部做了几件关键的事见 helloworld_demo.js通过new URL(helloworld_demo_bg.wasm, import.meta.url)基于模块自身 URL 定位.wasm文件这正是 ES Module 方式能正确解析资源的机制优先使用WebAssembly.instantiateStreaming流式实例化服务器未以application/wasmMIME 类型提供文件时自动回退到WebAssembly.instantiatepassStringToWasm0负责把 JS 字符串编码为 UTF-8 并拷入 WASM 线性内存getStringFromWasm0负责反向解码配合__wbindgen_malloc/__wbindgen_realloc完成内存管理。第三层Service Worker 中的导入与调用background.jsimport init, { print, print_with_value } from ./wasm/pkg/helloworld_demo.js; chrome.runtime.onInstalled.addListener(() { runDemo(); }); async function runDemo() { // Initialize the WASM module await init(); // Call the exported functions from the WASM module print(); print_with_value(John); }调用流程非常清晰先await init()完成 WASM 实例化此时#[wasm_bindgen(start)]的main已自动运行并打印Inited.随后调用print()打印Hello World!再调用print_with_value(John)把字符串传入 WASM由 Rust 侧以console.log双参数形式打印Hello John。扩展安装事件onInstalled作为演示触发器确保每次安装扩展都会执行一次演示。关键配置深入为什么 Service Worker 必须声明为 ES ModuleMV3 的 Service Worker 默认按经典脚本处理无法使用import/export语法。而 wasm-pack 以--target web生成的胶水代码是标准 ES Module内部使用了import.meta.url、export default等模块专有特性因此必须在 manifest 中通过background: { service_worker: background.js, type: module }把 Service Worker 声明为 ES Module浏览器才能正确解析import init, { print, print_with_value } from ./wasm/pkg/helloworld_demo.js这条语句。原文档以 diff 形式给出了这一改动的要点// manifest.json ... background: { service_worker: background.js, type: module }, ...本地构建 WASM 的完整流程仓库已经预构建好了 WASM 产物wasm/pkg目录直接加载即可运行。若想从源码自行构建按以下步骤操作安装 Rust 工具链rustup 安装即可。安装 wasm-packcargo install wasm-pack进入wasm目录并构建cd wasm wasm-pack build --target web注意--target web是关键参数它决定了胶水代码的形态ES Module配合type: module使用。构建产物会输出到wasm/pkg/重新加载扩展或点击 Service Worker 控制台的刷新按钮后即可看到效果。与 no-modules 方案的对比参考仓库中还提供了配套的对照示例 functional-samples/cookbook.wasm-helloworld-print-nomodule其 README 几乎一致唯一区别是构建命令改为wasm-pack build --target no-modules该方案生成的是传统全局脚本形态的胶水代码Service Worker 无需声明type: module。两个示例共用同一份 Rust 源码思路与同样的wasm-unsafe-evalCSP 配置正好构成一组模块化导入 vs 全局脚本的对照实验前者展示了本文主题MV3 下以 ES Module 方式使用 WASM后者展示了不使用 ES Module 时的替代路径。需要说明的是--target no-modules生成物依赖全局变量与脚本加载顺序而--target web的模块化方案与现代前端工程习惯更一致且能利用import.meta.url精确定位.wasm资源。常见问题与注意事项控制台无任何 WASM 日志优先检查 manifest 是否缺少content_security_policy.extension_pages中的wasm-unsafe-eval以及background是否带type: module修改 manifest 后需在扩展管理页重新加载扩展。import语句报语法错误说明 Service Worker 未被声明为 ES Module确认type: module已就位。.wasm文件 404--target web生成的胶水代码通过new URL(helloworld_demo_bg.wasm, import.meta.url)定位资源务必保持.js胶水与.wasm文件同目录即wasm/pkg内的文件要一起随扩展发布。流式实例化警告若看到WebAssembly.instantiateStreaming failed的警告说明服务器未按application/wasmMIME 返回文件扩展打包加载通常不触发该问题胶水代码也会自动回退到WebAssembly.instantiate功能不受影响。小结通过本示例可以完整掌握 MV3 扩展加载 WASM 的三要素CSP 中声明wasm-unsafe-eval、Service Worker 声明type: module、使用 wasm-pack 的--target web产物。结合 background.js、manifest.json、Rust 源码 与 wasm/pkg 生成物 逐层对照阅读即可在自有扩展中复刻这套调用链路将 Rust 编写的计算密集逻辑无缝集成进 Manifest V3 的 Service Worker。赞分享示例工程【免费下载链接】chrome-extensions-samplesChrome Extensions Samples项目地址https://gitcode.com/gh_mirrors/ch/chrome-extensions-samples点击查看免费下载相关推荐在 Manifest V3 中加载 WASMcookbook.wasm-helloworld-print-nomodule 实战指南在 Manifest V3 中加载 WASMcookbook.wasm helloworld print nomodule 实战指南 本文以 chrome e示例工程如何用convformer_s36.sail_in22k_ft_in1k提取图像特征3种实用方法详解如何用convformer_s36.sail_in22k_ft_in1k提取图像特征3种实用方法详解 ConvFormer_s36.sail_in22k_ft在 webpack 中以 ES Module 方式打包使用 wasm-pack 生成的 Rust WebAssembly 模块在 webpack 中以 ES Module 方式打包使用 wasm pack 生成的 Rust WebAssembly 模块 导读 本文基于 examples前端构建开发工具上一篇Grbl系统设置接口$参数的读取与修改方法下一篇Jackett 10分钟跑通种子聚合搜索:装好、配站、自动追更一次搞定创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考