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

Create a bundle for browsers that includes the Wasm code? #408

Open
rauschma opened this issue Oct 9, 2019 · 8 comments
Open

Create a bundle for browsers that includes the Wasm code? #408

rauschma opened this issue Oct 9, 2019 · 8 comments
Labels
feat New feature

Comments

@rauschma
Copy link

rauschma commented Oct 9, 2019

Suggestion: source-map would be easier to use if it completely hid the fact that it internally uses Wasm.

  • For browsers, you can do that by distributing a bundle, as shown below.
  • For Node.js, this should be even simpler.

webpack.config.js:

const path = require('path');

module.exports = {
  // ···
  module: {
    rules: [
      {
        test: /\.wasm$/,
        type: 'javascript/auto',
        loader: 'arraybuffer-loader', // installed via npm
      },    
    ],
  },
};

Setup code (when used outside the library):

import arrayBuffer from 'source-map/lib/mappings.wasm';
SourceMapConsumer.initialize({
  'lib/mappings.wasm': arrayBuffer,
});

AFAICT, .initialize() is not in the .d.ts file. Maybe add it?

@loganfsmyth
Copy link
Contributor

Hey there!

source-map would be easier to use if it completely hid the fact that it internally uses Wasm

I 100% agree with you there.

Before I potentially go the wrong direction, would the module also be "completely hide" the bundle's existance? When you say "For browsers" and "For Node.js", is what you have in mind

  1. two separate entrypoints, e.g. require("source-map") and require("source-map/browser")
  2. one entrypoint with
    main: "lib/index.js",
    browser: "browser-bundle.js"
    
    so that require("source-map") would load one or the other based on context, and the bundle would be an implementation detail?

@rauschma
Copy link
Author

rauschma commented Oct 9, 2019

Ah, good point! Tricky to get this right. Ideas:

  • Separate entry points may make things simpler, because you don’t have to dynamically check for the current environment(?) Another possibility:
    • source-map: same as now – for people using Node.js and bundlers other than webpack
    • source-map/webpack: uses arraybuffer-loader
  • It may make sense to do (then the entry in module.exports.module.rules may not be necessary):
    import arrayBuffer from 'arraybuffer-loader!!source-map/lib/mappings.wasm';
    

@loganfsmyth
Copy link
Contributor

I think for me, since this is published on npm primarily, it should be targeted at users consuming the library via the most common tooling first. To me, that means that it would ideally work in Node and Webpack without users needing to know that the library is in use, which would preclude needing to install arraybuffer-loader. That seems extra important for file extensions like .wasm that have potentially conflicting definitions of what it means to import them.

That all makes me lean toward the default being a base64-encoded WASM included in the npm package by default to avoid the loader.

We could certainly try to expose ways to configure it manually, but I think that gets complicated quickly, especially once it is used as a subdependency instead of a direct dep.

@rauschma
Copy link
Author

rauschma commented Oct 10, 2019

Base64, stored in a CommonJS module? Sounds good! The more transparent, the better, IMO. If it can be overridden, then it doesn’t matter if that’s a little slower. Must people will just appreciate that it’s easier to use. Bonus: it’s easier to migrate to something else in the future (to a first-class Wasm module, away from Wasm, etc.).

@kwonoj
Copy link

kwonoj commented Dec 10, 2019

it's somewhat coincidence but #369 takes same approach for b64 encoded binary, and makes isomorphic module publishing easier.

@adjenks
Copy link

adjenks commented Jul 28, 2020

Could encode it more densely with ascii85:
https://en.wikipedia.org/wiki/Ascii85
https://www.npmjs.com/package/base85

Or z85:
https://rfc.zeromq.org/spec/32/
https://www.npmjs.com/package/z85

@puzrin
Copy link

puzrin commented Sep 2, 2020

From my experience, if 25% size increase is not deadly critical, loading "small" wasm from base64 string is optimal (simple & fast enough).

@jkrems jkrems added the feat New feature label Apr 18, 2021
@gruns
Copy link

gruns commented Jul 24, 2023

@rauschma i just accidentally, independently reinvented your

                test: /\.wasm$/,
                type: 'javascript/auto',
                use: [
                    {
                        loader: 'arraybuffer-loader',
                    },
                ],

technique to bundle and include mappings.wasm into a bundled .js output file. but i then hit the roadblock where the latest npm version, v0.7.4, does not support providing an ArrayBuffer to SourceMapConsumer.Initialize(), while the latest trunk does. then i Googled and found this issue

so, in short: as a first step to support people -- like myself and @rauschma -- bundling mappings.wasm in output .js bundles, please push trunk to npm as a new version, e.g. v0.7.5. the last release, v0.7.4, was published 4 Jun 2022, over a year ago

then, thereafter, i too wholly support bundling mappings.wasm into source-map itself, hiding its internals that wasm is involved at all. that's an implementation detail. but that's more effort than just publishing trunk to npm, so starting with the latter immediately is best 🙂

zooming out, I'm curious: why is mappings.wasm wasm instead of js to begin with? speed? compiled from other, native code?

cc @loganfsmyth

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

No branches or pull requests

7 participants