The*_*wth 11 webpack webassembly wasm-bindgen wasm-pack webpack-5
我有一些 Rust 代码,可以使用wasm-pack和编译为 Web 程序集wasm-bindgen。我想从网络工作集/工作人员调用此代码。整个应用程序最终应该只是一个 *.js 文件,其他所有内容都内联。
这就是我想象的构建过程:
wasm-pack将 Rust 代码编译为 *.wasm 和 *.js 绑定(此步骤效果很好)webpack构建一个独立的 *.js 文件,我可以将其作为工作集/工作线程加载。*.wasm 必须包含在此文件中。(这一步失败)webpack来构建我的最终应用程序/包,内联步骤 2 中的工作集/工作文件。(此步骤效果很好)我的问题出在步骤 2 中:我无法将webpack*.wasm 内联到 worklet/worker 文件中。我在我的 webpack 配置中尝试了这个:
entry: {
worker: {
import: './src/worker.ts',
filename: '../lib/worker.js',
}
},
// ...
module: {
rules: [
// ...
{
test: /\.wasm$/,
// 1st option: type: 'webassembly/sync',
// 2nd option: type: 'asset/inline',
},
// ...
],
},
Run Code Online (Sandbox Code Playgroud)
无论我做什么,webpack总是发出两个文件,一个worker.js包含我的工作集/工作线程脚本本身,另一个文件vendor_my_package_name_wasm_js.js仅包含 *.wasm 及其绑定。显然,当作为 Web Worker 加载时worker.js,它会失败 - 无法从 Worker 范围加载第二个文件。
我的目标是包含所有内容worker.js,而不是发出单独的文件。但我该怎么做呢?
编辑:记录解决方案的步骤:
Webpack 本机 wasm 加载似乎不允许内联 wasm 文件。我们可以尝试使用常规的原始加载器:
// in module.rules
{
test: /\.wasm$/,
loader: 'raw-loader',
},
Run Code Online (Sandbox Code Playgroud)
这会导致以下错误:
ERROR in ./node_modules/my-module/my-wasm-file.wasm
Module parse failed: magic header not detected
File was processed with these loaders:
* ../../node_modules/raw-loader/dist/cjs.js
You may need an additional loader to handle the result of these loaders.
Run Code Online (Sandbox Code Playgroud)
发生这种情况是因为仍然存在隐式默认规则。我们可以通过覆盖默认规则以仅考虑json和js文件来禁用它:
ERROR in ./node_modules/my-module/my-wasm-file.wasm
Module parse failed: magic header not detected
File was processed with these loaders:
* ../../node_modules/raw-loader/dist/cjs.js
You may need an additional loader to handle the result of these loaders.
Run Code Online (Sandbox Code Playgroud)
现在我们终于将工作线程捆绑到一个 *.js 文件中!然而,当加载它时,我们最终遇到了这个错误:
Uncaught ReferenceError: document is not defined
Run Code Online (Sandbox Code Playgroud)
指向这段 webpack 生成的代码:
// in webpack.config.js
module: {
defaultRules: [
{
type: 'javascript/auto',
resolve: {},
},
{
test: /\.json$/i,
type: 'json',
},
],
rules: [
// ...
{
test: /\.wasm$/,
loader: 'raw-loader',
},
],
},
Run Code Online (Sandbox Code Playgroud)
由于某种原因,webpack 尝试支持动态加载内容(?)。wasm-pack我们可以将问题隔离到使用 CLI 参数时作为 javascript 绑定的一部分生成的这段代码--target=web:
Uncaught ReferenceError: document is not defined
Run Code Online (Sandbox Code Playgroud)
显然,必须生成 URL 的可能性使得 webpack 所依赖的 URLdocument在工作范围内加载工作脚本时不可用。取消注释该new URL()部分会使document引用从 webpack 输出中消失。
不知道从这里去哪里。编写我自己的 wasm-loader?我为此工作了一段时间,对 wasm 文件进行 base64 编码并将其内联为字符串 - 但随后我必须大幅更改消费者代码以异步手动加载 wasm。这意味着我不能wasm-bindgen再使用绑定,因为它们依赖于URL上面显示的部分(使用时--target=web)或 webpack 5 的捆绑逻辑(使用时--target=bundler),我无法从我自己的简单 wasm-loader 尝试中获得支持。本质上,这意味着我必须提供自己的 JS 绑定,这很不方便。
一定有更好的方法——对吧?
cargo build --target=wasm32/unknown/unknownwasm-bindgen --out-dir=dist --target=web --omit-default-module-path my-wasm-package.wasm.import init, { /* other stuff */ } from 'my-wasm-package';
import wasmData from 'my-wasm-package/my-wasm-package.wasm';
const wasmPromise = init(wasmData);
Run Code Online (Sandbox Code Playgroud)
// ...
module.exports = {
// ...
module: {
rules: [
{
test: /\.ts$/,
loader: 'ts-loader',
options: {
configFile: 'tsconfig.json',
},
},
{
test: /\.wasm$/,
type: "asset/inline",
},
],
},
};
Run Code Online (Sandbox Code Playgroud)
我观察到的核心问题是由wasm-bindgen包含URL关键字生成的 JS 绑定 - 它以期望定义对象的webpack方式进行初始化。document该对象在工作集范围内未定义,因此webpack即使我们从未进入包含URL.
如果我们不使用wasm-pack一次性构建 wasm 和绑定,我们可以传递额外的参数wasm-bindgen- 主要是从绑定中--omit-default-module-path删除带有 的部分的参数。URL现在初始化时webpack不会引用,我们可以使用绑定而无需修改。document
从这里开始就很简单了:我们将 wasm 捆绑为 b64 编码资产,并将其传递给init()JS 绑定附带的函数。
| 归档时间: |
|
| 查看次数: |
11498 次 |
| 最近记录: |