Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use in browsers? #305

Open
michaelfranzl opened this issue Sep 18, 2022 · 10 comments
Open

How to use in browsers? #305

michaelfranzl opened this issue Sep 18, 2022 · 10 comments

Comments

@michaelfranzl
Copy link

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,

import { init, WASI } from '@wasmer/wasi';
await init()

gives the following error:

Library.esm.min.js:25 Uncaught (in promise) ReferenceError: Buffer is not defined
    at Z (Library.esm.min.js:25:15897)

This comes from

const buffer = Buffer.from(data, encoding) as MimeBuffer;
Indeed there is no Buffer global in browsers.

How to use @wasmer/wasi in the browser? If Buffer is supposed to be polyfilled, could you add this to the README and refer to a library which fulfills the required API? Thanks.

@Jack-Edwards
Copy link

I was probably about to encounter the same problem. I'd like to use this library in the browser as well.

@corwin-of-amber
Copy link
Contributor

corwin-of-amber commented Sep 19, 2022

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).

@michaelfranzl
Copy link
Author

@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

@corwin-of-amber
Copy link
Contributor

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.

@cdecompilador
Copy link

I'd also like to use the library on the browser, also note that in parcel doesn't work out of the box sadly

@guregu
Copy link

guregu commented Oct 6, 2022

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)]

@Cloudef
Copy link

Cloudef commented Nov 23, 2022

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 wasmerio/wasmer#2568 the app calls exit()
It's dumb but this workaround works

var exitCode = 1;
try { exitCode = wasi.start(); } catch (e) {}

makenowjust added a commit to makenowjust/wasmer-js that referenced this issue Mar 5, 2023
The global `Buffer` is used for loading base64 encoded string.
However, this **implicit** and **global** dependency makes some
confusions and problems (wasmerio#294, wasmerio#305, and ruby/ruby.wasm#182).

The use of `Buffer` here is limited, so we can easily replace this
by using `atob` function. This simplifies user's build settings
and reduces the file size since there is no need to include Buffer.
@frog-o
Copy link

frog-o commented Mar 25, 2023

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.

@zees-dev
Copy link

zees-dev commented Aug 22, 2023

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()]
});

@vmx
Copy link

vmx commented Sep 14, 2023

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();
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants