Hacker News new | ask | show | jobs
by gjsman-1000 1602 days ago
Personally, to me, whenever I read these stories about how Amazon is doing this novel use of WebAssembly, or how Uber is doing ludicrous engineering effort to keep their React-based app under 300MB for the App Store, I can't help but think:

"Man, that's an awful lot of work to avoid writing a native app."

13 comments

The challenge would be that Prime Video is distributed on many client devices. Here’s a list of a few TV OSes: https://en.m.wikipedia.org/wiki/List_of_smart_TV_platforms. How would you manage a different native app for each of them?

Caveat: previously worked at Prime Video though not in this area, still at Amazon

I could be incorrect, but last time I did some reverse-engineering, Netflix had a Qt application that used native C++ bindings to knock out huge sections of that list.

That Qt application was only lightly modified for each platform, IIRC, and it appeared all over the place from those cheap Linux-based Blu-ray players to Smart TV clients. Anywhere that was embedded, generally Linux-based, and unlikely to get frequent updates.

As for some of the larger players like Roku or Android, those ones are more obvious where to hire. Java developers and BrightScript developers.

It all kind of undermines your original comment tho that they're trying to avoid native. It seems more likely that they're goal is to reach as many devices as they can and be able to do updates frequently. In the first paragraph of the linked article the guy says the trade-off is between "updatability and performance".
I am really sick of fast-churn and forced updates. Guys. Settle. Write a native app or three. It’ll be ok.
As someone who is writing a cross platform app, I'd love to, but I can't.

There are too many different stacks with their own languages (which means different library ecosystems), no good FFI/IPC options that work across stacks, massive test matrix for every little piece of the code etc. All of this, when the native differences that supposedly should make each platform unique are so few, and virtually all UI and application logic is identical. Our platform lords have basically not standardized a single thing.

> Our platform lords have basically not standardized a single thing.

And in addition, you have bugs in official native SDKs and then you end up writing your own text rendering engine, because some OS-level API didn't work properly.

I think it's important not to conflate churn with fast updates. In it's essence the ability to deliver updates quickly (in this case by downloading a blob of wasm+js each time the app is started) is a great thing imo, as you eliminate a huge chunk of problems around delivering updates and clients on old versions. For 99% of users this is a huge win.

You can obviously abuse this by redesigning the UI every 6 weeks but let's not throw the baby out with the bath water.

I'm of the strong opinion that there simply does not exist, as you say, 'a huge chunk of problems around delivering updates and clients on old versions.' It's certainly not a win for users, but for lazy developers. Good software engineers are much more than fast-churn developers. In fact, they are different people.
if they did that then only the most popular platforms would ever be support, happen to use a niche product, or a older product, well your SOL.
Uber is a bad example because they need to have support for literally every payment method on the planet. And all of that needs to be preloaded ahead of time just in case the user decides they're going to fly to Mumbai tomorrow. Their app absolutely needs to be bloated or it won't work at all.

Likewise, Amazon needs to run on all sorts of different smart TV platforms, not just iOS and Android. All of those apps need to be consistent to each other, rather than to their host platforms. That's almost the textbook case for using a cross-platform framework.

> Their app absolutely needs to be bloated or it won't work at all.

It really doesn’t. I remember this being brought up back when the Uber engineer crying about how their compiler couldn’t match their scale was making the rounds, and in the end the numbers just did not add up to support the app size they have right now.

> All of those apps need to be consistent to each other, rather than to their host platforms.

Why? Platform-specific apps, for the most part, should feel at home on their platforms. Not doing this is how you get YouTube for Apple TV and similarly bad apps.

> Uber is a bad example because they need to have support for literally every payment method on the planet.

How is the breadth of their payment back-end and excuse for a bloated client?

>And all of that needs to be preloaded ahead of time just in case the user decides they're going to fly to Mumbai tomorrow.

This is Interesting. So essentially Uber is a "Global" App by default?

Yes, that's why it works everywhere* with local specifics ( e.g. proposing tuk-tuks where available, or bike rentals where Uber have the service or a partner, etc.) directly without new downloads or anything.

* of course where Uber are on the local market, i doubt it works in North Korea

Writing a native app for every conceivable platform someone might want to watch Prime Video on seems an awful lot of work
"But why, though?" I keep asking myself, from a "how many darn buttons and doodads does it really need to have?" perspective. I suspect the issue is that people write entirely too much dang code to solve what is, after all, a fairly simple UI problem [1]. I mean, seriously. The Alto had less than a megabyte of RAM and managed to invent the GUI--menus, mouse, all. How have we managed to make this harder in 40 years?

[1]...until Branding(tm) enters the chat.

Because it's not just buttons and doodads, it's all the error handling and loading indicators and UI edge cases that are needed to make it seamless and good. Title too long? Does it get truncated or shrunk? Does the UI reverse itself for RTL languages? Does the focus ring move in a sensible order?

This is front end engineering. It's a whole profession, and when it's done poorly, folks think your software is garbage. Forty years ago half of the software was in English and required a specific screen resolution. Of COURSE it's going to be harder.

Frontend engineering is a thing because of the accidental complexity of a massive software stack that's evolved by accretion and gone through fad after fad after fad. I'm not looking down on frontend engineers, but I don't believe right-to-left languages or focus order inevitably leads to hundreds of thousands of lines of code or 50+ MB binaries.
Where do you think all that code lives, then? The support for dark mode, the ability to look at the pixel data of an image so that you can display text with the right color on top of it to have high enough contrast, the subtle animation when you tab between elements in a scrollable grid, the annotations for accessibility, the code that makes drag and drop work like you expect... As much as you don't think it is "hundreds of thousands of lines of code", it really is.

I started a business online five years ago. I used as little JS as possible: the first version was probably 500 lines total. Today, it's approaching a quarter million, and it's all just me. Why? Because I want forms to show helpful errors when you type the wrong thing, and my pages to show appropriate visual cues at the right time in the right places, and for the page to look right when dark mode kicks in on your laptop or you resize your window, and for decimals to be formatted correctly for folks in Europe. Or for the power users who expect things to be fast, so navigating forward and back loads and caches data correctly. Or for folks with high-dpi displays (or as it were, folks who zoom in) who don't want pixelated icons.

And has it paid off? Yeah. As an example, my service hosts a surprising majority of blind podcasters, including the American Council for the Blind. I didn't get here with a spring in my step and a strong belief in semantic HTML, I got here by investing in all the fiddly edge cases so no matter what size your screen is, the browser you use, the language you speak, the currency you want to get paid with, your ability to use a mouse, your screen reader or level of vision, you still have a great experience. As much as you'd like to call it a fad or accidental complexity, it's really just your inexperience with actually building good user interfaces in the 21st century.

Hey, I share your passion for human interfaces - huge kudos to you. I built the main interface for the redesigned Amazon Photos iOS app and went through a lot of the things you mentioned - totally agree that it pays off. If you ever want to chat over coffee my email is johnanthony.dev@gmail.com
> don't believe right-to-left languages or focus order inevitably leads to hundreds of thousands of lines of code or 50+ MB binaries

It does. It literally does. Try writing your own operating system, or font parser, or graphics engine. The work our shitty React apps sit on top of is unimaginably complex. It would take centuries for one single person to grasp what is going on in an iOS "Hello World" app.

It's not simple, at all. Especially not for a video streaming service! I mean, my God, just being able to understand the codecs and licensing issues would take you months, let alone writing decoders that run natively on every platform. Let alone dealing with monitors and color schemes and HDMI and Chromecast streaming and window resizing and bandwidth limits and buffering and....

It's not simple.

EDIT: For reference, vim, a Hacker News favorite and widely considered one of the most popular TUIs ever built, is currently sitting at about 1.2 million lines of code. All it does is edit text files. Imagine if it had to play video.

> For reference, vim

Vim is an incredibly useful tool but I've seen frequent complaints about its codebase. Competitors with significantly higher code quality exist (ex Kakoune).

> > don't believe ... inevitably leads to

> It does. It literally does. Try writing your own operating system, or font parser, or graphics engine.

There are working examples of such and the code appears to be significantly simpler than the status quo. I'm far from an expert here but to the best of my understanding feature creep combined with maintaining backwards compatibility is to blame for a significant amount of current complexity.

Consider that if you rewrite a low level API with the benefit of hindsight, everything that uses that API has to be updated. Often multiple distinct APIs will be involved though, not just one. Look at the difficulty the Linux ecosystem has had gaining full support for Wayland, which necessitated the likes of PipeWire and a number of other new ways of doing things, and has been "nearly ready" for production for how many years now?

> It would take centuries for one single person to grasp what is going on in an iOS "Hello World" app.

Not really. Several years, maybe.

Alternatively, it could be that building high quality cross-platform front-ends that look and behave consistently across those different platforms is actually complex and the tools to solve those problems reflect that complexity. In my view, this is pretty common knowledge... just consider, every example of native software is horrible outside of one or two platforms, and most native software project/products don't even support more than two platforms.
This comes off incredibly naive of FE engineering.

Buttons and Doodads? sigh.

A significant factor as to why Apple has succeeded the past 2 decades is due to the design of their products - from the sleek aluminum bodies of their hardware to the UI/UX of their operating systems.

Unless you want your UI to look like something out of 1995, you're going to have to make it look good.

Making it look good will require a decent amount of code.

From animation libraries like Framer Motion, or data visualizations using d3, or even After Effects renders from Lottie.

That isn't even mentioning the amount of state that is required to be stored so that proper renders could occur - If your user has logged in, if your user has typed something into an input field, how many times you should retry a request if it fails, what functions to run due to a websocket response, and myriads of other things that FE engineers have to deal with.

Please reconsider your thoughts.

I feel the conversation will just cycle if we try to push people to the poles of opinion and insult them. Accidental complexity is an enormous, pervasive problem across all software stacks. The ratio of lines of code to pixels on the screen is pretty bonkers. Since you mention Apple, if you look at the ratio of lines of code per pixel, it's really hard to understand how an OS weighs in at 10GB, even for Apple which is brazen about deprecating and only catering to their own hardware and products. That speaks to a universal bloat problem that shows no signs of slowing down. I mean we could dive down into the details and keep coming up with special pleading for every little functionality, but it won't be a productive conversation, really, and the big picture will be completely lost.

> Please reconsider your thoughts.

Just leave that part out next time. Anyone can write this at the end of any comment and it only injects a bad vibe into the whole conversation.

I, for one, would love if UIs looked like it's 1995 again. Imagine the crispness, everything is fast, responsive and written in sensible languages. A simpler, and better time.
> all the error handling and loading indicators and UI edge cases that are needed to make it seamless and good

You mean the single instance of “owo we are very sorry” that shows up for any error, including the case where you might just have the gall to use the app on a non-perfect connection? The lack of a loading indicator? The poor and non-seamless experience because somebody wanted to ship Branding™?

But I still think prime video, Netflix, Apple TV, etc are still garbage. They are woefully inconsistent, laggy, etc despite it “being it’s own profession”.

I think the fact that it is its own profession is part of the problem. Every company feels the need to reinvent the wheel.

I feel like you could make tons of money proving everyone wrong.
A company that makes an awful lot of money can afford to not make an awful app on major platforms.

A native app on Windows, macOS, iOS and Android (TV), and some other solution for other platforms, isn't an unreasonable ask in this context.

If you're already very successful, why would you spend a lot more money to produce a buggier product that will generate a lot more customer support requests and cost a lot more money in engineering effort to maintain forever going forward? It just makes no business sense. This reasoning is even less justifiable in the context of WASM which is quite performant.
Because Apple has proven that people will actually pay for reinventing something but better and more polished. And you call it a buggier product, but if you have a dedicated team working on a native app for platform X, that team can become the expert on platform X, work around and fix all its caveats, and beat the competition on everything forever.

I mean granted, for a lot of companies, having a substandard or suboptimal app simply does not matter to their bottom line, because the product trumps the implementation details in the end; people are willing to put up with e.g. a bloated web app because it gives them access to a good chat service (think slack, discord). People were willing to put up with Twitter's fail whale outages whenever Justin Bieber tweeted because they had something good (network effect?).

> Because Apple has proven that people will actually pay for reinventing something but better and more polished

The massive popularity of React Native on the iOS platform suggests there's more to the story. Discord, Slack, Spotify etc might also beg to differ; all electron apps, all the most dominant players in their respective markets. Consider all the massive gaming successes on the Unity platform?

The deference to native purity is an engineering conceit not something that users actually care about except in rare cases.

I'm not following.

This assumes that, generally, native apps are more buggy. Why? This is contestable at best, or getting it the wrong way around at the worst. Perhaps at the hands of inexperienced developers it's right. But experienced developers coding in native APIs will probably produce an app with fewer bugs.

And we are talking about a billion dollar company. It can afford a handful of really good native developers for each platform. It can attract talented developers who can write cross-platform native code.

Cross-platform toolkits introduce their own class of bugs, which might require patches upstream to resolve, or annoying local forks.

As for the economics of it all, I'll leave that to the other sub-comment which deals with that with an excellent analogy to Apple. People will pay for quality.

> This assumes that, generally, native apps are more buggy.

They are, not because "native" code is inherently buggier but because the amount of code that needs to be written is multiplied by every platform you have to support to replicate the same experience per platform; more code = more bugs, and you have to handle all the nasty edge cases that are specific to each platform: a major increase in bugs is assured.

> And we are talking about a billion dollar company.

The size of the company doesn't matter, it makes no sense to massively increase the cost, complexity and staff size needed to support an existing product that's already massively successful.

> Cross-platform toolkits introduce their own class of bugs, which might require patches upstream to resolve, or annoying local forks.

This is true of literally any external source code you import into your project. However, if you re-invent the wheel you have to pay to fix it rather than having it fixed upstream for free.

And when comes the payoff for writing all those native apps?
It takes an awful lot more money to ask engineers to do boring things like, “reciprocate this behaviour from iOS to Android “
Once I broached this subject with a developer at a start-up that developed totally separate native apps for iOS and Android. I queried him about the use of native apps, and he made the point that you do whatever it takes to keep your users happy.

This was a startup. Not a billion dollar company. When your app is used by millions, it's a worthwhile investment.

It's also hardly boring to achieve the same end result on multiple platforms by using appropriate native code for each. Particularly when it produces satisfyingly fluid and responsive end results. Perhaps an engineer that considers it boring is in the wrong field. A UI developer should get satisfaction from developing UIs, not as it being a stepping stone to get into systems development. I can't think of anything more boring in app development than developing an app which operates in a mediocre way.

A carefully planned native app for each platform can still share parts of the same codebase, you're not necessarily reinventing the wheel each time.

“This was a startup.” And? They have the latitude to make big risks. Larger companies can’t eat that risk as easily.

“it's a worthwhile investment.” Obviously not, or you’d see it more.

No. You just build one abstraction and then use a code generator to build a client for different targets. So as long as you have good developers with an interest in code generation and that will stick around for a few years to maintain the generators, then it works out fine. Resist the temptation to create a new DSL or programming language. Pick a language with a strict compiler, good typing system and good reflection capabilities and you are good to go. Ideally you code your app/abstraction once and then then everything else gets generated automatically by some build pipeline.
Isn't the abstraction essentially their wasm and js libraries? And they just use a vm instead of code generator.
In their case, most likely yes. I honestly don't know and how don't know how many of their targets can be blanketed this way. The scenario I describe will not work for 8000 device types as you will end up with 8000 codegen libraries. Or that is, with my current implementation you will end up with that amount, as each target gets it's own little generator.

I recently swapped out a big chunk of my codegen code and let my code call the flutter cli, so then I generate a flutter project which in turn can generate a few clients (like web, desktop, android etc). I'm currently optimizing the way I keep state between generations: certain parts can/should be overwritten but other parts need to be kept in tact. Trickier than it sounds.

I highly recommend people to try building their own generators, scaffolding & tools. Very enriching!

In the pre-streaming era, every platform had a native player and content library app that worked fine.

If streaming services desire to replace local playback, they’ll also have to replace the convenience that provided.

In this world where the only real differences between streaming services are their apps and their catalogues, you’d think everyone would be doing everything in their power to acquire every advantage on those fronts.

My own strategy would be to keep the generic electron version and then make a native app for the top 5 most popular TV models but that’s just me.

Native apps are harder to update: https://news.ycombinator.com/item?id=30110265
For web & phones, I'm inclined to agree; a native app outperforms a web or hybrid app any day of the week. I do believe Facebook and Google are companies who ran into limitations though, binary size, number of classes / identifiers, build times, for which using web technology was a solution.

But for TVs, ehh. There's a lot more fragmentation on the TV market. And if things were slightly different, we'd have a lot more fragmentation on the mobile market as well. Actually there are plenty of mobile alternatives, but developers don't really want to support all operating systems - and these cross-platform tools often have substandard support for mobile operating systems that aren't iOS or Android.

I disagree with this perspective.

From a startup pov, going with native apps will require multiple teams (Usually just Android + iOS, but occasionally Windows as well)

React Native will only require one team, or just one engineer depending on the size of the project

Better yet, If your front end developer is fluent in React(web), then that developer is already fluent in React Native.

I completely disagree on the "awful lot of work", when you could literally get your FE developer to work on your "native" apps.

Sure, where performance must be squeezed, it's probably optimal to go native, but that bar is set a lot lower than where it actually should be.

If React Native is good enough for Discord, it's good for 3 quarters of all apps out there.

Former Dev that did Web -> Ionic -> RN -> Native iOS over the course of 6 years speaking here.

- Web devs typically don’t have strong instincts for mobile apps, they require more mentorship & onboarding time.

- Animation and interactivity is strongly limited in RN - You’re always so many levels removed from the actual APIs being used. For example, using UIKit and CoreAnimation are absolutely amazing and super lightweight on CPU/GPU in comparison. UICollectionView is a modern miracle that offers so much more control than FlatList.

- JS/Babel/node_modules is hell, no I won’t elaborate.

- Multi-threading, priority/concurrent queues etc for maintaining good all-around perf while doing intense operations is very strong with native platforms. RN just has sophisticated band-aids.

Honestly it mostly depends on the type of work the app will be doing, the dev resources available to you, and the level of quality you want to attain. I strive to create the best of the best user experience, and native is the best way to attain that.

The app I work on still uses RN for some features, but the results historically have been disappointing on average.

Happy coding!

> Web -> Ionic -> RN -> Native iOS

Although that list directly relates to the number of people you reach per line of code.

Web (all devices) -> Ionic (most devices) -> RN (Android + iOS) -> Native iOS (iOS only and probably only more recent devices).

People do cross-platform development, because it runs on so many platforms with almost no additional code. And for sure, you might not get the full experience of every platform this way, but maybe it's still good enough for users to solve their problems?!

> Web devs typically don’t have strong instincts for mobile apps, they require more mentorship & onboarding time.

I don't agree entirely. I do understand that there are differences in concerns regarding web and mobile, but the similarities overrun that of the differences, ESPECIALLY if they're working with react + rn.

mentorship + onboarding time aren't words I would choose if a developer wanted to move from React to React Native - you make it sounds like a dev is joining a new company.

> Animation and interactivity is strongly limited in RN - You’re always so many levels removed from the actual APIs being used. For example, using UIKit and CoreAnimation are absolutely amazing and super lightweight on CPU/GPU in comparison. UICollectionView is a modern miracle that offers so much more control than FlatList.

Again performance is not something I will ever disagree with, the only part I disagree with is where people typically put that bar of "we need native because of performance" - It's a lot higher than most people think.

Furthermore, your example of Flatlist in animations is confusing. A better example would probably be React Spring. Granted, RN animation is levels above, obviously, but it doesn't mean RN can't implement the same style of animations as native can

https://twitter.com/VilacaRodolfo/status/1178351034051284993

> JS/Babel/node_modules is hell, no I won’t elaborate.

ok

> Multi-threading, priority/concurrent queues etc for maintaining good all-around perf while doing intense operations is very strong with native platforms. RN just has sophisticated band-aids.

not arguing performance. that is always a given.

Again, I will reiterate.

If React Native is good enough for Discord, it's good enough for 3 quarters of mobile apps out there.

Happy coding!

HTML+JS+CSS is a very refined toolset for building UI that provides you with a content to consume. Sometimes, especially when the content is text, video and images, it’s actually easier to build high quality experience that works very well on all the platforms because it provides interaction modes out of the box that are the same everywhere.

Native apps shine when you do something novel, something that’s beyond text, images and video consumption or you leverage platform specific functions.

IMHO, sticking to Web technologies is a better option for things like Netflix or Amazon Prime but not good for Uber and alike.

You can render OpenGL with C++ and compile it to Wasm but alsk have it build and run natively (Emscripten or your own bindings or whatever). So this can be a way to do both, while keeping the reach of web. Depends on what kind of application you're building and whether this makes sense for that, for sure.
Between electron, webassembly, and other technologies, I don't think the line between web app and native app is as clear as it used to be, especially relative lift and performance. In the end, the only difference may be "one is launched in a browser and one is launched from the start menu"
It is very clear: are ALL controls which could be standard (provided by native OS toolkit) really standard (and respect system theming, customization, etc) and are ALL keyboard shortucts and other behaviors of OS standard toolkit supported? I don't care are code is native (as in compiled ahead of time / just in time / interpreted), but I'm care for behaviors and it consistency, both across one app and whole system.

I'm forced to use Slack at $job, and it is awful, for example. Some text fields looks as text fields and are used as text fields, but don't respect "Shift+End/Home/Arrows" keyboard commands. Other does. It is annoying as hell. It is Electron.

Even more «native» toolkits, like GTK and QT are have small discrepancies. Simple example: my Windows has English MUI (interface language) but Russian locale (time and date format, etc). In POSIX terms it is something like LC_MESSAGES=en_GB & LC_ALL=ru_RU (according to POSIX more specific categories have priority over LC_ALL). 95% of both QT-based and GTK-based software with translation to Russian speak Russian to me (and if I'm lucky has setting somewhere to enforce English). They think that «(system language)» is Russian. But it is not! It is not very «native», IMHO. Ok, GTK-based software is typicality build via cygwin/mingw, so it is really not very native and is «hacked» to run on Windows, but most of QT-based software IS build for Windows, as Windows is fully supported, tier 1 platform for QT. But still.

If I start to write down all small nitpicks about cross-platform software, which shows that it it not native, I could find many in any cross-platform software. Corner cases in keyboard shortcuts, non-copyable messageboxes, strange tab behaviors, non-standard open/save/print dialogs, etc, etc, etc. If you use platform for 25+ years (yes, Windows changed a lot from 3.11 for Workgroups which was my first version, but these changes were small ones, step-by-step, and A LOT of things in UX didn't change still!), you have a shitton of muscle memory and all these nitpicks throw you off.

Yes, I know, that there is no "native" toolkit for Linux. IMHO, it is a big problem, much bigger, that all problems of X11 which Wayland want to solve.

I agree, the controls and OS integration are what makes the most difference in the whole debate. But: Why aren't there native controls in the browser? Why do they suck?

> Even more «native» toolkits, like GTK and QT are have small discrepancies.

And then there is truly native stuff and you still have discrepancies like bugs that make you write your own UI kits, recently witnessed here:

https://nova.app/

> Here's a little editor story for fun. During beta we found some bugs in Apple's text layout engine that we just could not fix. Our solution? Writing our own text layout manager… from scratch.

That is a great example for Panic's dedication and at the same time a sane argument for doing cross-platform development, if you can't even trust the truly native libraries.

It’s all about deployability.
I love native apps. But on the scale of Amazon (and having to compete with Netflix), slightest bit of friction, in this case downloading and installing an app, accepting permissions, etc takes a minute or two. It would be absolutely catastrophic to their competitiveness. You need to think more broadly on scale.
If you read the original article, the use of WebAssembly is mainly across a broad array of device types where it will be packaged into an app. That app will require installation, accepting permissions, and all of that just like a native app.

The point is moot except for anyone watching Prime Video in the web browser.

The WebAssembly component gets pulled on app startup. That means you make a bug fix, deploy a new build to an S3 bucket and every single user is running the fix inside of ~24 hours.
I hope native apps die. Most companies won't put in the level of effort into their engineering that the Chrome/Firefox teams do - specifically, they're not going to take security as seriously.
Agreed! Why write a native app when you can just use Babel to transpile to Google Sheets formulas? Sure it doesn’t support threading but modern devices are so fast nowadays it doesn’t even matter.
That… escalated quickly