mozilla / source-map

Consume and generate source maps.
Other
3.56k stars 358 forks source link

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

Open rauschma opened 5 years ago

rauschma commented 5 years ago

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

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 commented 5 years ago

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 commented 5 years ago

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

loganfsmyth commented 5 years ago

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 commented 5 years ago

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 commented 4 years ago

it's somewhat coincidence but https://github.com/mozilla/source-map/pull/369 takes same approach for b64 encoded binary, and makes isomorphic module publishing easier.

adjenks commented 4 years ago

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 commented 4 years ago

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

gruns commented 1 year ago

@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