Is it possible to use wasm-bindgen with webpack 5?
Asked Answered
L

2

12

I followed the Hello World Guide for wasm-bindgen (I am using wasm-bindgen = "0.2.72").

Unfortunately the npm packages mentioned in the guide are not really up to date. Because I would like to have a clean starting point, I tried to upgrade them.

This is the package.json mentioned in the guide:

{
  "scripts": {
    "build": "webpack",
    "serve": "webpack-dev-server"
  },
  "devDependencies": {
    "@wasm-tool/wasm-pack-plugin": "1.0.1",
    "text-encoding": "^0.7.0",
    "html-webpack-plugin": "^3.2.0",
    "webpack": "^4.29.4",
    "webpack-cli": "^3.1.1",
    "webpack-dev-server": "^3.1.0"
  }
}

I removed text-encoding (because I do not care about not supporting the non Chromium based version of Edge) and upgraded @wasm-tool/wasm-pack-plugin without Issues:

Working package.json:

{
  "scripts": {
    "build": "webpack",
    "serve": "webpack-dev-server"
  },
  "devDependencies": {
    "@wasm-tool/wasm-pack-plugin": "^1.3.3",
    "html-webpack-plugin": "^3.2.0",
    "webpack": "^4.29.4",
    "webpack-cli": "^3.1.1",
    "webpack-dev-server": "^3.1.0"
  }
}

Working webpack.config.js:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");

module.exports = {
    entry: './index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'index.js',
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: 'index.html'
        }),
        new WasmPackPlugin({
            crateDirectory: path.resolve(__dirname, ".")
        })
    ],
    mode: 'development'
};

The next thing I did was upgrading the html-webpack-plugin and webpack itself.

The package.json of the version with the error:

{
  "scripts": {
    "build": "webpack",
    "serve": "webpack-dev-server"
  },
  "devDependencies": {
    "@wasm-tool/wasm-pack-plugin": "^1.3.3",
    "html-webpack-plugin": "^5.3.1",
    "webpack": "^5.27.1",
    "webpack-cli": "^3.1.1",
    "webpack-dev-server": "^3.1.0"
  }
}

Because I upgraded webpack to version 5.27.1 I also had to change the webpack.config.js like this:

const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const WasmPackPlugin = require("@wasm-tool/wasm-pack-plugin");

module.exports = {
    entry: './index.js',
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'index.js',
    },
    plugins: [
        new HtmlWebpackPlugin({
            template: 'index.html'
        }),
        new WasmPackPlugin({
            crateDirectory: path.resolve(__dirname, ".")
        })
    ],
    experiments: {
        asyncWebAssembly: true
    },
    mode: 'development'
};

Now when I run npm run serve the build completes without errors, but when I open the webpage no alert is shown anymore. In the browser console the following error is now logged:

TypeError: _index_bg_wasm__WEBPACK_IMPORTED_MODULE_0__ is undefined
    greet webpack:///./pkg/index_bg.js?:113
    <anonymous> webpack:///./index.js?:4
    promise callback* webpack:///./index.js?:4
    js http://localhost:8080/index.js:18
    __webpack_require__ http://localhost:8080/index.js:366
    <anonymous> http://localhost:8080/index.js:709
    <anonymous> http://localhost:8080/index.js:712

What do I have to do, to get rid of this Issue, so that I can use wasm-bindgen with webpack ^5.27.1?

I am thankful for any hints whatsoever.

Additional Observation

Interestingly I found, that even with the not working version, it is possible to remove m => m.greet('World!') from index.js and instead call the wasm function from pkg/index.js like this

import * as wasm from "./index_bg.wasm";
export * from "./index_bg.js";

wasm.greet("World");

When I do this, I get no more errors in the console and an alert showing "Hello, !" (missing the "World") is shown, so I think the .wasm should still be fine...

Update

I was able to get everything working again by using:

experiments: {
    syncWebAssembly: true
},

however this is deprecated, so it would be great if there was a way to still use asyncWebAssembly.

Ludly answered 21/3, 2021 at 16:5 Comment(1)
Interesting, I think I ran into this before, so this would be a nice opportunity to find out what's causing it. I've created an issue in the meantime.Helvetia
C
0

I was able to get it working by loading my application in the following way.

My webpack entry config looks like this:

    entry: {
      wasm: ['./src/bootstrap.js'],
      vendor: ['react', 'react-dom'],
    },

The bootstrap file looks like this:

import('./index.tsx').catch(e =>
  console.error('Error importing `index.getStringX`:', e),
);

Further down in my React application I load the wasm package installed with npm like so:

import * as wasm from 'myRustWebAssemblyPackedPackage';

That's all I do. I don't use any plugins in Webpack.

Corbel answered 22/3, 2021 at 23:39 Comment(4)
The problem is, this won't recompile my Rust wasm package, when I apply changes to my rust code. This is the main reason I use Webpack with the wasm-pack plugin, because it provides the live-reload capability.Ludly
@Ludly I know this may not be ideal but if you use my approach and then install cargo-watch and run cargo watch -i .gitignore -i "pkg/*" -s "wasm-pack build" in tandem with your webpack watch, then cargo will call the wasm-pack build command updating the pkg directory which webpack is watching on and rebuild.Corbel
I am accepting this as a workaround for now. Hopefully this will be resolved in the wasm-pack plugin.Ludly
had to add "console.log('wasm='+wasm);" after ipmort, otherwise webpack was repoting '(webassembly) [orphan] and thing wasn't loadedSiege
M
1

Yes, it is officially supported now, as committed in Aug 10, 2021 to the main branch. Note, that as of Dec 2022, if you are cloning from wasm-bindgen GitHub, you need to copy examples out of wasm-bindgen root, see related issue. Don't forget to npm i before proceeding with npm run serve

Maunsell answered 22/12, 2022 at 10:54 Comment(0)
C
0

I was able to get it working by loading my application in the following way.

My webpack entry config looks like this:

    entry: {
      wasm: ['./src/bootstrap.js'],
      vendor: ['react', 'react-dom'],
    },

The bootstrap file looks like this:

import('./index.tsx').catch(e =>
  console.error('Error importing `index.getStringX`:', e),
);

Further down in my React application I load the wasm package installed with npm like so:

import * as wasm from 'myRustWebAssemblyPackedPackage';

That's all I do. I don't use any plugins in Webpack.

Corbel answered 22/3, 2021 at 23:39 Comment(4)
The problem is, this won't recompile my Rust wasm package, when I apply changes to my rust code. This is the main reason I use Webpack with the wasm-pack plugin, because it provides the live-reload capability.Ludly
@Ludly I know this may not be ideal but if you use my approach and then install cargo-watch and run cargo watch -i .gitignore -i "pkg/*" -s "wasm-pack build" in tandem with your webpack watch, then cargo will call the wasm-pack build command updating the pkg directory which webpack is watching on and rebuild.Corbel
I am accepting this as a workaround for now. Hopefully this will be resolved in the wasm-pack plugin.Ludly
had to add "console.log('wasm='+wasm);" after ipmort, otherwise webpack was repoting '(webassembly) [orphan] and thing wasn't loadedSiege

© 2022 - 2024 — McMap. All rights reserved.