-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
proposal: cmd/go: option to bundle wasm output with wasm_exec.js #72055
Comments
Related Issues
Related Code Changes Related Documentation (Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.) |
is this appropriate / efficient for the js ecosystem? |
I believe it is, yes. You're right that wasm_exec.js doesn't change very often so it's not very likely that Go v1.N wasm_exec.js will break when trying to run a Go v1.N+1 binary. But if, say, https://go-review.googlesource.com/c/go/+/555417 were to be merged that would immediately cause existing Go v1.24.0 wasm_exec.js to not work with any newer Go v1.24+1 Go-built .wasm files. The current manual management of the sibling wasm_exec.js increases the complexity and general this feels hacky and unofficial feeling which can be detrimental to the 0-60 getting started first-timers. To provide an example from another ecosystem: wasm-bindgen from Rust does a similar thing to GOOS=js GOARCH=wasm -- it runs & binds to JavaScript through a JS-provided suite of functions -- and wasm-bindgen does automatically generate accompanying .js code in your output directory (albeit separate .js and .wasm file with an extra .d.ts). Point being though that wasm-bindgen does generate the JS glue code instead of saying "ok I did most of it; now go find the right glue code yourself before you can run it". That "ok I did most of it; now go find the right glue code yourself" is what I would like the option to skip via a Obviously, yes, the current workflow works but I think that this would be strictly an optional improvement that would emphasize and reinforce the idea that the generated .wasm and the accompanying wasm_exec.js are intertwined in lockstep with each other and are very much not guaranteed to work with other non-lockstep versions of eachother |
Noting that there's some similarity here with a previous request to add cmd/go support for multi-architecture macOS binaries (issue #40698). In both cases, it's something that can also be done by an external tool, such as https://github.com/randall77/makefat for the former request, where there are fewer constraints (cmd/go has a 6-month release cycle, high bar for breaking compatibility, etc.). |
This is similar yes. Similar: Both of these are "post-process the compiled output pls" requests. They can both be accomplished outside of the |
I think this comes down to a) how integrated the wasm_exec.js is with the Go toolchain/output itself and whether that warrants baking it in to the output and b) whether or not it's good DX to bake it in. I am willing to try and contribute code to make this a thing if this is deemed an acceptable proposal. (whatever form it takes; -ldflags, env var, a sibling file, whatever) |
CC @golang/js |
Base64-encoding WASM incurs a ~33% size penalty. Also, I'm not quite sure if this will affect the user's ability to use DevTools to diagnose the generated wasm file? It might be more likely to add a sibling file when using the |
This doesn't affect the 1.24.x versions, they've been separated into separate branches for development, and code on the mainline is always pointing to the next major version. |
Proposal Details
Similar to how there's
-ldflags "-H windowsgui"
for Windows I think there should be something like-ldflags "-H jsmodule"
(output ES module which uses top-level await) and/or-ldflags "-H jsscript"
(output classic global script which just does .run() and doesn't await it). Or it could be some completely different option. I don't know where this feature request makes the most sense.Why do this? So that users have the option to get the correct wasm_exec.js bundled with the output instead of needing to remember to tell any downstream user of
myapp.wasm
"hey! this was built against Go v1.24.0 so remember to use Go v1.24.0's wasm_exec.js and NOT Go v1.23.0's wasm_exec.js" or similar that you might already have in your codebase.This might make Go WASM more "reproducible" (is that the right word?) because now the JS can optionally be part of the included output and thus doesn't have to be specified out-of-band as "I used this wasm_exec.js (paste code)" when filing bug reports or whatever.
Here's an idea for a template. I have no idea if it works -- this is just illustrative.
Remember, currently js/wasm only outputs main command executables and not libraries so you can assume that it should always be run as a top-level item and not imported as a library. ex:
node a.out
orsomePrepWork(); import "./a.out"
but notimport { f } from "./a.out"; restOfCode()
THIS SHOULD NOT CHANGE THE DEFAULT BEHAVIOUR I understand that changing the default output of
GOOS=js GOARCH=wasm go build
is a bad idea. Instead, I'm proposing an optional mode that outputs JS wrapping the wasmThe -H flag as part of https://pkg.go.dev/cmd/link seems like a good fit but idk I'm not a compiler dev lol
so I thought "hey maybe
-H jsmodule
fits the-H <goos><type>
of "windowsgui" where goos=js and type=module".Alternatives
The text was updated successfully, but these errors were encountered: