I am trying to add some web-assembly to my project. On the beginning I created a simple method to check is my webpack works well and can I use my .wasm
modules. So I created somthing like this:
#[wasm_bindgen]
pub fn return_char() -> char {
return 'a';
}
And then I used this inside constructor of my web-component (just to check is everything works fine):
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = template;
console.log(return_char());
}
This worked as expected I saw 'a'
in my web-app console:
Then when I saw that everything works fine I created struct with implementation:
#[wasm_bindgen]
pub struct Test {
value: char
}
#[wasm_bindgen]
impl Test {
pub fn new() -> Test {
let value: char = 'a';
Test {
value
}
}
pub fn value(&self) -> char {
self.value
}
pub fn change_value(&mut self) {
self.value = 'b';
}
}
Then I add created instance of Test
inside the same web-component class constructor and call methods of this Test
impl. I thought that I should see 'a'
and 'b'
in my console
constructor() {
super();
this.attachShadow({ mode: 'open' });
this.shadowRoot.innerHTML = template;
const test: Test = Test.new();
console.log(test.value());
test.change_value();
console.log(test.value());
}
But this didn't happen and I saw only this error:
Uncaught (in promise) ReferenceError: Cannot access '__wbindgen_throw' before initialization at Module.__wbindgen_throw (calculator_engine_bg.js:5)
I do not know why I am getting this error and how can I fix this. Maybe there is a problem with my webpack.config.js
?
const path = require('path');
const HTMLWebpackPlugin = require('html-webpack-plugin');
module.exports = {
mode: 'development',
devtool: 'eval-source-map',
entry: './src/index.ts',
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
experiments: {
asyncWebAssembly: true
},
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
include: [path.resolve(__dirname, 'src')],
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
devServer: {
contentBase: path.join(__dirname, 'dist'),
},
plugins: [
new HTMLWebpackPlugin({
template: path.resolve(__dirname, 'src/index.html'),
filename: 'index.html',
}),
],
};
GitHub repository with minimal code needed to reproduce: webpack-web-assembly-rust-impl-bug
webpack version: 5.0.0-beta.26
So as sokra mentioned in his answer under issue which I created. I should use experiments.syncWebAssembly
instead of experiments.asyncWebAssembly
. If I use this experiments.syncWebAssembly
I have to add additional file which will asynchronously load index.ts
file.
webpack.config.js
module.exports = {
mode: 'development',
devtool: 'eval-source-map',
entry: './src/bootstrap.ts', // !! <- change path to bootstrap.ts
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
experiments: {
syncWebAssembly: true // !! <- use syncWebAssembly instead of asyncWebAssembly
},
module: {
rules: [
{
test: /\.ts$/,
use: 'ts-loader',
include: [path.resolve(__dirname, 'src')],
},
],
},
resolve: {
extensions: ['.ts', '.js'],
},
devServer: {
contentBase: path.join(__dirname, 'dist'),
},
plugins: [
new HTMLWebpackPlugin({
template: path.resolve(__dirname, 'src/index.html'),
filename: 'index.html',
}),
],
};
bootstrap.ts
import('./index').catch(e => console.error('Error importing `index.js`:', e))
Full solution you can find here:: webpack-web-assembly-rust-impl-bug