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

Make go-app compatible with GopherJS #830

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

nevkontakte
Copy link

...or, more precisely, not actively incompatible with GopherJS.

At a high level, this PR does two changes:

  • Use GOOS=js as a predicate for the client-side execution, instead of GOARCH=wasm. GopherJS builds the code with GOOS=js GOARCH=ecmascript, so with this change go-app will correctly detect which side is the client when compiled with GopherJS.
  • Factor out logic related to wasm-specific resources into a Driver, and allow users to provide an alternative implementation. It does not add any explicit support or mention of GopherJS, but it is now fairly trivial for the user to make it work with GopherJS.

The general idea here is that while go-app doesn't officially support GopherJS, the latter supports syscall/js package pretty well, so the only practical issue is that Go WebAssembly requires some special code to load and start up, whereas GopherJS-compiled scripts can be simply included via a <script> tag. This change effectively makes the wasm-specific part of the initialization optional, and also take care of not attempting to cache them in the service worker.

https://github.com/nevkontakte/go-app-on-gopherjs contains a Go Workspace, which demos use of go-app with GopherJS using this patch. The only caveat is that Go 1.18.x is required for GopherJS to work.

Fixes #819

`GOOS` usually indicates the availability of certain OS APIs, whereas
`GOARCH` targets a specific bytecode architecture. For go-app purposes,
it's important that the `syscall/js` package is available, but it's less
interesting whether the code is compiled into wasm or something else.

By using `GOOS=js` constraint go-app becomes more open for use with
alternative client-side toolchains, such as GopherJS, which also
supports the `syscall/js` package.

I also fixed a small bug in the `log.go` file, where `goarch ==
"window"` could never be true. I believe the intent was to check for
`runtime.GOOS == "windows"`.
The new `Driver` type can be used to customize how go-app environment is
set up on the client side. It is responsible for pre-rendering and
registering scripts and styles that are necessary to load and start
app's business logic.

By default, a Go WebAssembly driver is assumed, which maintains the
original behavior with showing a loader progress bar and starting up a
Go wasm binary.

Users can customize the loading process and the scripts necessary for it
by providing their own Driver implementations - at their own peril.

One notable change is that app.js has been split into two parts:

 - The code responsible for managing service worker remains in app.js
   and is included regardless of the driver used.
 - The code responsible for setting up wasm was moved to driver-wasm.js
   and is used by the `goWasmDriver` implementation.
@oderwat
Copy link
Sponsor Contributor

oderwat commented May 6, 2023

I can confirm that our current most important App is compiling without any problems when I use this branch through a 'go.work' directive.

Copy link
Owner

@maxence-charriere maxence-charriere left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks a bit like what I was thinking to do but I'd like the driver part a bit different. Could we split this in 2 and target the v9.7.0 branch?

  • The precompile part (I want to get this as it is)
  • The Driver part (might keep it as it is or take inspiration)

Thanks for this PR.

@nevkontakte
Copy link
Author

Sorry for the delay, I've been busy with other projects. I'll try to get to it this weekend.

@suntong
Copy link

suntong commented Aug 13, 2023

I for one hope this will get into the official code for two reasons,

  • this would allow us to migrate our web app step by step while go-app based code grow bigger and bigger in percentage until it finally takes over all then we can switch to wasm, but before that, I don't know any way for my go-app code to co-existing with our existing framework.
  • Seems to me that there is no hope for pre-compressed wasm in any near future (see go-app can be served from Gitlab Pages, how about pre-compressed wasm? #866), yet I still have a hope that gopherjs based solution can support pre-compressed. IE I don't mind at all my build time take a bit longer, as long as my server doesn't need to compress a 16M big file each time a request is made. Would that be possible @nevkontakte?

@oderwat
Copy link
Sponsor Contributor

oderwat commented Aug 13, 2023

@suntong you can call all your JS code from WASM, no need to GopherJS for that. The pre-compressed files problem IMHO is a GitHub pages problem and can't be solved by other vendors. You need to be able to send a Content-Encoding: gzip for pre-compressed data (and for loading % reporting the original length header). So you can do that with any "real" web server already. It just needs more fiddling at build time than having transparent compression running.

@suntong
Copy link

suntong commented Aug 14, 2023

@suntong you can call all your JS code from WASM, no need to GopherJS for that.

I thought so at first until I tried it with an example here. You can see @oderwat that in its test folder, the Javascript invoked fine from html page.

However, the same content, when rendered with go-app, the Javascript was not able to be invoked.

If you can make the example triggering JS code from WASM works, it'll be very appreciated. thx.
If you indeed able to, please follow up at #859 instead.

The pre-compressed files problem IMHO is a GitHub pages problem and can't be solved by other vendors. You need to be able to send a Content-Encoding: gzip for pre-compressed data . .. It just needs more fiddling at build time than having transparent compression running.

Yep, quite agree.

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

Successfully merging this pull request may close these issues.

Support building go-app with GopherJS (no wasm)
4 participants