Open michaelfranzl opened 1 year ago
I was probably about to encounter the same problem. I'd like to use this library in the browser as well.
Hi! Currently the Wasmer-JS libraries rely on a bundler for browser integration. Webpack and Rollup work well. Notice #290 and the comments below about defining wasmer_wasi_js_bg.wasm
as external; it is actually not needed as its content is inlined in Library.esm.min.js
(as a data URL).
@corwin-of-amber When you say that it "relies on a bundler", do you mean that a bundler has to be configured to polyfill Buffer
? Like from rollup-plugin-polyfill-node
or @esbuild-plugins/node-modules-polyfill
?
In contrast, in v0.12.0, Buffer
was included in wasmer-js/wasi (imported from buffer-es6
and injected as a dependency): https://github.com/wasmerio/wasmer-js/blob/v0.12.0/packages/wasi/src/index.ts#L11
Yes, exactly. I am pasting the contents of webpack.config.js
from a hello-world project that I did to learn how to use it; if you find it useful then perhaps I can make a PR to add it to the WasmerJS docs.
const path = require('path');
const webpack = require('webpack');
module.exports = {
name: 'hello',
entry: './hello.js',
mode: 'development',
target: 'webworker',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'hello.js'
},
module: {
rules: [
{
test: /\.wasm$/,
type: 'asset/resource'
}
]
},
externals: {
'wasmer_wasi_js_bg.wasm': true
},
resolve: {
fallback: {buffer: require.resolve('buffer/')}
},
plugins: [new webpack.ProvidePlugin({
process: 'process/browser.js',
Buffer: ['buffer', 'Buffer']
})]
}
It is true that previous versions were bundled with Buffer. IMO this is now old-style; having your dependencies bundled hinders inter-operability esp. if types from the bundled package are part of the API. It makes passing the "right" objects quite tricky. Forcing the user to provide their own polyfills is certainly more cumbersome and goes against the OOP encapsulation concepts, but pragmatically is much more flexible.
I'd also like to use the library on the browser, also note that in parcel doesn't work out of the box sadly
Here is an esbuild configuration I am using successfully in the browser: https://github.com/guregu/trealla-js/blob/9dfaf8b886033ea339cd36d005b2555091c56efa/make.cjs#L17-L19
The important bit:
const stdLibBrowser = require('node-stdlib-browser');
(async () => {
await esbuild.build({
entryPoints: ['index.js'],
// ...
inject: [require.resolve('node-stdlib-browser/helpers/esbuild/shim')],
define: {
Buffer: 'Buffer'
},
plugins: [plugin(stdLibBrowser)]
After polyfilling buffer I'm getting
Uncaught (in promise) Error: Failed to instantiate WASI: RuntimeError: JsValue(TypeError: import object field 'env' is not an Object
EDIT: After compiling in all the functions that weren't in wasi-libc ... would be nice if you could provide env through JS too in case you want to implement the functions there, now I get this:
Error while running start function: RuntimeError: JsValue(Object({"ptr":1122200}))
Works in wasmtime though :/
EDIT2: prob this issue https://github.com/wasmerio/wasmer/issues/2568 the app calls exit() It's dumb but this workaround works
var exitCode = 1;
try { exitCode = wasi.start(); } catch (e) {}
One thing I hate( so far) is everything i can find requires vite Wich indirectly uses node. One of the cool things about wasm(if i not mistaken) looks like wasm should not need a bundler or anything other than a web browser ;i am reading wasm are binary(all though it could be text). I would like to use wapm without node i am surprised they have no instructions un using it with unpkg or skypack and no install IMHO it should need wasmer.
If you're using vite
you can use this plugin to polyfill for node: https://github.com/sodatea/vite-plugin-node-stdlib-browser
// vite.config.ts
import { defineConfig } from 'vite';
import nodePolyfills from 'vite-plugin-node-stdlib-browser'
export default defineConfig({
server: {
port: 8080,
},
plugins: [nodePolyfills()]
});
After polyfilling buffer I'm getting
Uncaught (in promise) Error: Failed to instantiate WASI: RuntimeError: JsValue(TypeError: import object field 'env' is not an Object
I had the same error. My problems were the imports. I've used:
const imports = {
myfun: () => {
console.log("my function")
}
}
But when I looked at the WAT output (thanks to https://uptointerpretation.com/posts/webassembly-woes/, pointing to https://stackoverflow.com/questions/54598317/rust-wasm-module-not-found-error-cant-resolve-env-in, where the answer suggests running wasm2wat
), I saw that myfun
is imported under env
.
So the correct import is:
const imports = {
env: {
myfun: () => {
console.log("my function")
}
}
}
I've been using this from Rust, the extern there is just:
extern "C" {
fn myfun();
}
The README of v1.0.2 states that browsers are supported. However, neither the README nor the example directory contain usage examples for the browser. Using the best guess in the browser,
gives the following error:
This comes from https://github.com/wasmerio/wasmer-js/blob/8f3f221a5431eff5c5370f48d9189eba3547f451/lib.ts#L62 Indeed there is no
Buffer
global in browsers.How to use
@wasmer/wasi
in the browser? IfBuffer
is supposed to be polyfilled, could you add this to the README and refer to a library which fulfills the required API? Thanks.