前面在《解决 Rust WebAssembly 启动 Web 程序报错》 一文中讲到,将 Webpack
升级到 5.54.0+
。其实问题并未彻底解决,还潜藏另一个问题。当我们像原先那样,通过导出 memory
来访问 WebAssembly
线性内存:
import { memory } from "wasm-game-of-life/wasm_game_of_life_bg";
在 npm run start
时会报警,结果是程序无法正常运行:
export 'memory' (imported as 'memory') was not found in 'wasm-game-of-life/wasm_game_of_life_bg'
(possible exports: Universe, __wbg_error_f851667af71bcfc6,
__wbg_new_abda76e883ba8a5f, __wbg_set_wasm, __wbg_stack_658279fe44541cf6,
__wbindgen_object_drop_ref, __wbindgen_throw)
在 github 上 wasm-bindgen
、wasm-pack
和 webpack
的 Issues 中搜了一通。发现都有报告类似问题,不知为何过了两三年仍处于 Open 状态。不过评论中也有提出可供参考的解决办法。
总结了评论中的方法,我自己做了这样的修改:
首先,在 www
目录中创建一个源文件 memory.js
,用以从 wasm
文件中导出 memory
,内容如下:
// 从 `wasm` 文件中导出 `memory`
export { memory } from "wasm-game-of-life/wasm_game_of_life_bg.wasm";
然后,在我们需要访问 memory
的源文件中导入:
// 导入 `memory`
import { memory } from './memory';
...
// 访问线性内存中的宇宙细胞数据
const cellsPtr = universe.cells();
const size = Math.ceil((width * height) / 8);
const cells = new Uint8Array(memory.buffer, cellsPtr, size);
再次 npm run start
,正常运行!
对了,别忘记我们之前升级 Webpack 5
时,修改了 webpack.config.js
:
const CopyWebpackPlugin = require("copy-webpack-plugin");
const path = require('path');
module.exports = {
entry: "./bootstrap.js",
output: {
path: path.resolve(__dirname, "dist"),
filename: "bootstrap.js",
},
mode: "development",
plugins: [
new CopyWebpackPlugin({
patterns: [
{ from: "index.html" },
]
})
],
// 支持 WebAssembly 打包
experiments: {
asyncWebAssembly: true,
syncWebAssembly: true
},
};