资源与 WASM assets
assets 管理插件自带资源,挂在三个全局变量上(wadLogicLayer.assets / wadRenderLayer.assets / wadPanelLayer.assets)。单 HTML 插件没有资产目录;zip 安装的插件,包内 assets/(或任意子目录)下的文件都能按相对路径取到,根地址是:
text
/v1/plugins/<id>/file/<相对路径>本页你将学到
- assets 在三层的可用性差异(script/css 仅渲染/面板);
- 每个加载方法的签名与失败行为;
- wasm 的加载与实战;
- zip 插件怎么组织资产。
API 总表
| API | 逻辑层 | 渲染层 | 面板层 |
|---|---|---|---|
url(p) | ✅ | ✅ | ✅ |
text(p) / json(p) / arrayBuffer(p) | ✅ | ✅ | ✅ |
wasm(p, imports) | ✅ | ✅ | ✅ |
script(p) / css(p) | ❌ Promise.reject(E_LAYER_ONLY) | ✅ | ✅ |
preload(paths) / clear() | ✅ | ✅ | ✅ |
url(p)
把相对路径转成可访问的绝对 URL(已是 http(s):// 的原样返回)。
js
wadPanelLayer.assets.url('assets/logo.png')
// 'http://127.0.0.1:9400/v1/plugins/my-plugin/file/assets/logo.png?ignore_wmpf_network_debug=1'text(p) / json(p)
读文本与 JSON(json 内置 JSON.parse 一步到位)。
js
(async () => {
const tpl = await wadPanelLayer.assets.text('assets/template.html');
const rules = await wadPanelLayer.assets.json('assets/rules.json');
})();注意点:失败(404 等)reject Error('HTTP 404')。
arrayBuffer(p)
读二进制。
js
(async () => {
const buf = await wadPanelLayer.assets.arrayBuffer('assets/key.bin');
const u8 = new Uint8Array(buf);
})();wasm(p, imports)
下载 + WebAssembly.instantiate。逻辑/渲染层返回 {module, instance, exports} 并缓存;面板层返回原生 {module, instance}(不缓存),用 w.instance.exports 取导出。
js
(async () => {
const w = await wadPanelLayer.assets.wasm('assets/gw.wasm');
const out = (w.exports || w.instance.exports).wad_v3_decode(key, bodyB64, 0);
})();实战:Rust 编译的解码模块
rust
// src-lib/lib.rs(wasm32-unknown-unknown)
#[no_mangle]
pub extern "C" fn wad_alloc(len: usize) -> *mut u8 { /* ... */ }
#[no_mangle]
pub extern "C" fn wad_decode(ptr: i32, len: i32) -> i32 { /* 返回结果字符串指针 */ }js
(async () => {
// 面板侧使用
const w = await wadPanelLayer.assets.wasm('assets/codec.wasm');
const ex = w.exports || w.instance.exports;
const p = ex.wad_alloc(bytes.length);
new Uint8Array(ex.memory.buffer).set(bytes, p);
const outPtr = ex.wad_decode(p, bytes.length);
})();script(p) / css(p)
注入脚本与样式。仅渲染层与面板层可用(逻辑层调用返回 Promise.reject E_LAYER_ONLY)。
js
(async () => {
// 渲染层
await wadRenderLayer.assets.css('assets/dark.css');
const mod = await wadRenderLayer.assets.script('assets/enhance.js'); // 返回脚本返回值
})();js
// 逻辑层调用会 reject:
wadLogicLayer.assets.script('assets/x.js').catch(function (e) {
e.code === 'E_LAYER_ONLY'; // true
});preload(paths) / clear()
预热缓存与清空缓存。
js
(async () => {
await wadPanelLayer.assets.preload(['assets/a.json', 'assets/b.wasm']); // 并行预热缓存
wadPanelLayer.assets.clear(); // 清空 arrayBuffer 缓存(wasm/script/css 缓存不清)
})();实战:zip 插件组织资产
text
my-plugin.zip
├── plugin.html ← 入口
├── README.md ← 市场详情页
├── logo.png ← 市场图标(wad:logo 未内联时用)
└── assets/
├── rules.json
├── codec.wasm
└── panel.csshtml
<!-- plugin.html 里按相对路径引用 -->
<script>
wadPanelLayer.ready.then(async function () {
const rules = await wadPanelLayer.assets.json('assets/rules.json');
const css = await wadPanelLayer.assets.url('assets/panel.css');
document.getElementById('css').href = css;
});
</script>