54 comments

[ 2.5 ms ] story [ 115 ms ] thread
It looks like the browser crashes on every screen change on Safari 15 on macOS...
Same on iOS.

It’s been a while since I’ve seen a documentation site with a loader that goes multiple seconds.

I didn't think Safari supported PWAs, or is that a new feature in 15?

Personally I'm still not a fan of PWA. I don't see what they give me as a user, other than a worse experience than a native application would have.

No App Store, no install, no walled garden, no 30%.
As a user I like the App Store, all my software and purchases are all in on place.

Installs aren’t really an issue, and less so if you like the app store. I can see the point about wall gardens, but you can still just install non-app store programs on all operating systems. Regarding the 30% I not convienced that saving are directly passed on to the end users.

Edit: It just occurred to me that you might be think about software on phones. I don’t exactly care about mobile, but yes, then your argument makes more sense.

Yes, I was thinking mobile when I wrote that. :)
PWA isn't a singular feature (well, beyond ServiceWorker, which is pretty essential), it's a group of loosely connected features exposing more native functionality to the web, and making the web app experience more native-like.

The ServiceWorker API has been supported by iOS Safari for years: https://caniuse.com/mdn-api_serviceworker. When people complain about lack of PWA support on iOS Safari, usually the #1 complaint is lack of Web Push: https://caniuse.com/push-api.

In this specific case, the site is working fine on iOS Safari 14, and Safari 15 TP on macOS Big Sur. I'm not sure if there are problems specific to Safari 15 on not-yet-released iOS 15 or macOS Monterey, I don't have an installation of either.

> When people complain about lack of PWA support on iOS Safari, usually the #1 complaint is lack of Web Push

Good, web push is horrible and 99.9% of use cases are malicious. Take a look at your grandma's Android phone and she probably has 12 Chrome notifications saying she won a free iPad because she went on a site that asked to send notifications, and users are so used to user-hostile UX's that force you to agree to everything to use the site, they just hit "allow" so they can get to the content.

I'm not surprised Apple doesn't want that on the iPhone.

One problem with golang's wasm target is that the generated binary is huge. For instance, I checked app.wasm of this documentation site and the four examples listed at https://go-app.dev/built-with:

0. This site: 14.9MB, 3.4MB gzipped;

1. 13.5MB, 3.2MB gzipped;

2. 15.4MB, 3.2MB gzipped;

3. 4.7MB, 1.2MB gzipped (this is an extremely bare bones demo);

4. 25.0MB, 5.4MB gzipped.

You can save a bit more with brotli, but not much more. I built an app with golang wasm last year, but ended up rewriting everything in good old TS since I couldn't justify the ~15MB raw, ~2.7MB brotli'ed payload.

I guess you can make some huge savings if tinygo has enough capabilities to cover all your needs. Not sure if it's possible with this library, but if it is, they certainly haven't explored it, hence the 3.4MB gzipped wasm for a documentation site.

The “good” news in my experience is that they don’t seem to usually get much larger than 15mb, I’m guessing it’s the wall you hit once most of the standard library is already included. It’s certainly not enviable, but I have absolutely seen sites with an equal volume of JS, so it’s not unheard of.
One thing for old-school performance comparers to remember here is that WASM is very significantly cheaper than JavaScript to parse and compile.

On an arbitrary fairly weak phone, 15MB of WASM might take two seconds to compile, but it can do that while downloading, so that in practice your network link will probably be the limiting factor. So the transfer size is typically the figure to care about and the uncompressed size actually doesn’t matter all that much.

15MB of JavaScript on that same device might take ten seconds or even more to compile, and it largely can’t even start until it’s finished downloading it. Consequently, you need to care about both the transfer size and the uncompressed size, in different ways.

(My figures are super dodgy as I can’t find any recent concrete figures, but they should be in vaguely the right ballpark.)

This is all about comparing just the cost to the CPU; data transfer costs money too and takes time, and several megabytes transferred is inconvenient to many for reasons of cost or time, and decidedly wasteful.

Multiple megabytes even of WASM is still madness and folly for simple stuff like this, severely restricting its potential usefulness. Thank you for deciding not to ship something like that yourself.

That applies if youre shipping a giant 15 meg blob of js (not saying some sites dont do this), a lot of the size also comes from css and other assets which still apply with shipping a wasm blob. I'm gonna guess that v8 can parse a 1-2 meg js file just as fast if not faster than the time it takes to download a 15 meg wasm blob or a 4 meg blob + decompress + parse outputted from golang. Like your last line says, shipping 15 megs of any kind of code makes no sense to me
When considering performance, some people presume that WASM is much the same as JavaScript; I’m just reminding them that this is not the case: WASM has better loading characteristics than JavaScript so that its cost per byte is much more like that of images than of JavaScript.
As mumphster pointed out in a sibling, 15MB of wasm vs 15MB of javascript is an unfair comparison. For instance, my aforementioned app is a few hundred KB of uncompressed js when rewritten, not 15MB.

Also, in my experience, a 15MB wasm blob has shit caching characteristics; it gets evicted all the time. An immutable few hundred KB js blob, on the other hand, can remain cached for much longer. Sure, you can use a service worker and its Cache API to make caching large blobs more predictable, but then shipping new code / cache invalidation becomes more annoying.

Genuine question. What's the underlying issue behind this concern? When I'm reading your numbers, my first reaction is that 5-15MB these days is peanuts. What use cases am I missing?
In web contexts, we usually shoot for sub 1MB (ideally ~250kb for static sites). The main reason is usually just optimizing for mobile experiences. People expect to wait a while to download a 200MB app, but if you have to wait 5s for a webpage you’re very likely to click away.

Of course it’s partially a function of your target audience. Notion and Retool (for example) are able to ship massive multi megabyte bundles because they’re productivity apps targeted mostly towards people with desktops and high speed internet connections. If HN were to ship a 15MB bundle it’d be virtually unusable on mobile for a lot of people (myself included, and I live in Seattle!).

I agree. I'm all for static, low-size websites and that is something I always strive for. But, the internet speed keeps improving. 5MB app won't take 5s to load these days. 1 megabit-per-second connection needs 8 seconds to load 1MB. Most internet providers offer 300Mbit/s minimum ($39/month). But even with 50Mbit/s channel, it'll only take 0.8s to load 5MB.
It very well might depending on the audience and the percentile you target. 90th percentile times show that those larger speeds are not consistent, often showing a bifurcated distribution where the tail is experiencing loss / latency that compounds the more request and the larger they are.

Of course if the development benefits for your team outweigh it, it makes sense to do it. Just mean to say advertised cellphone connection speeds are not a reliable benchmark to hit.

When I moved away from Alaska a couple of years ago, the fastest speed available to me was 768k. sites with several mb were virtually unusable, and so many of the would refresh or ajax recklessly as though bandwidth were huge and infinite. much of the modern web was completely unusable.
The Website Obesity Crisis was prescient:

> If present trends continue, there is the real chance that articles warning about page bloat could exceed 5 megabytes in size by 2020.

> The problem with picking any particular size as a threshold is that it encourages us to define deviancy down. Today’s egregiously bloated site becomes tomorrow’s typical page, and next year’s elegantly slim design.

https://idlewords.com/talks/website_obesity.htm

I work in Latin America and with the kind of low end phones and flakey mobile connections that a lot of people use here, 5-15MB is a pretty big issue. E.g. what I have seen from metrics is phones spending seconds just parsing/compiling those huge javascript bundles loading websites that don't do much more than turning json into html.

A lot of modern web is a nightmare to use if you have a ~$50 android phone and are lucky if you have a decent 3G connection.

You seem to be forgetting all the people in the world that are not on fast network connections.

Genuine question: how did you manage to forget something so huge?

I'm originally from Ukraine. My mom's internet connection there is 100Mbit/s and she pays $9 per month ¯\_(ツ)_/¯
ok, so sounds like ukraine is in the subset of the world with fast internet, or at least your mum's town. But I don't see how that answers the question -- what about rural south america, rural africa?
I mean, pretty much every tech serves a percentile of population. It can not please everyone.
Yes. You were asking what use cases you were missing. The answer was people on slow networks.
I'm on crowded public wifi right now and the site spent 4-5 seconds on the loading screen.
Does anyone know how wasm binary sizes produced from other language toolchains compares? (For example Rust)
Depends on the language, and tool chain used to generate the wasm.

Most LLVM generated binaries, including Rust by default from memory, turn out pretty small.

Really wish Go had some kind of parameter that let it take extra time compiling "production" builds, such that it would significantly optimise their resulting size.

> but ended up rewriting everything in good old TS since I couldn't justify the ~15MB raw, ~2.7MB brotli'ed payload.

What were the size improvements?

When I've tried it out for wasm game development, the biggest issue I had was frequent GC pauses (was a few every second) causing frame drops. TinyGo gets at this issue. I've used C++ since then, focusing on a small subset that keeps things flexible and compiling fast. Been hacking on a Go -> C++ compiler lately that produces that subset.
The focus on PWAs probably helps a little bit since there's the expectation of more local cache hits
Wasm is good for a lot of things, but this isn't one of them. Go is notorious for generating enormous wasm binaries, and, sure enough, the wasm blob for this page weighs in at 14MB.

I don't know how somebody keeps a straight face clainming their 14 meg page is SEO-friendly.

So much for assembly language being the most compact and efficient form of software... (Yes, of course I know it's assembly for a VM, but still, there's NO excuse for this kind of outrageous bloat!)
It is compact and efficient. Problem is that there's a lot of it, because these payloads also have to include large chunks of Go's standard library. Apparently fmt and http are particularly large packages that will each add 1-2MB to your was binary.
The runtime alone is also roughly 700kb, or at least was as of 2017 when this SO answer was written

https://stackoverflow.com/a/46159048

Not sure if anything's changed since then

With go 1.17, a minimal program doing absolutely nothing when built with

  GOOS=js GOARCH=wasm go build -ldflags='-s -w'
comes in at 1.2M raw, 362K gzipped, 276K brotli'ed (default compression levels).

  func (h *hello) Render() app.UI {
   return app.H1().Text("Hello World!")
  }
Using a template would have been easier and more clear.
Checkout hyperapp - same design, but pure javascript.
I agree that it feels unnecessary and uncomfortable. There might be a reason why he chose this vs plain text or template, not sure.
Hi, go-app’s creator here.

I did it in previous version and since there is no code check/lint on HTML templates within strings, debugging HTML was a pain in the ass.

More clear is a matter of taste and you can do pretty clear code with this syntax.

Horrible html syntax. No thanks.
Yikes, that's really nasty, you're right. Not sure why frameworks like this tend to reinvent the wheel. This isn't the first to create a new DSL for writing HTML. The most efficient way to write HTML is to use HTML, or an in-html template like Handlebars or embedded elixir. No need for a senseless abstraction layer on top of an already existing markup language.
I saw this a longer while ago on reddit and wasn't convinced, because I asked questions but felt ridiculed in the answer. The question was about component reusability and inheritance. Also what about real time changes to contents when the values in the data store change (see ngrx, redux, vuex) aka reactivity. However good that I found it here because I wanted to take a closer look at it and play with it and doubt that I'd be able to find the post on reddit again. Also as much as I dislike Rust, it's closer to typescript in philosophy than Go and might actually be a good fit for the frontend wasm. I'm ignorant however and idk if the binary size is also a problem for Rust like it is for Go.
Hey folks, just find this post, I’m go-app’s creator. Looks like a bunch of the discussion is about the wasm size. When its gzip it is not that big. People are talking about 15MB, none of my projects reached that size, and they are usually pretty liked by my users.

For the syntax, it is a matter of tastes but things that people like about it is that its full Go and everything is discoverable from your editor with auto completion.

At the end what’s matter is that it’s good enough to build beautiful UI only by using Go and it’s ecosystem.

I've been building wasm powered apps (compiled from Go) for almost a year.

Main issues:

- the size of your build: you need to check what packages you import and possible trim them down

- resource usage and performance(due the lack of DOM).

- bugs/implementation: the browser may stop working/freeze after a while. There were some issues with the scheduler, I'm not sure if it's still the case. If you develop an UI for an embedded device this is a big issue.

It may work for Desktop apps (electron based) or some enterprise apps so it has its niche but you definitely can "feel" the difference between a wasm implementation and a pure JS implementation. As a client you will prefer the JS version. As a developer you will love the Go version

All that being said it's great to be able to use Go in browser and as the devices are getting faster along with the network I guess it will work just fine once 5G becomes mainstream.

Hint: If you process HTML, always use the DOM/JS interface. Any processing of HTML (i.e. via x/net/html) in Go will make your app VERY slow.

(comment deleted)
3.5mb for a documentation site. This is several orders of magnitude worse than the JS framework plague.

At least have a demo that warrants a package that large.

Click your mouse three times and say 'progressive web app' and you'll be taken to a bloated website in two seconds.
I enjoy Go but I don't see it playing nicely with wasm anytime soon. It's runtime is big, it has a garbage collector, and getting the complexity and nuance of goroutines to work in the browser with webworkers seems like a scary challenge.