Ask HN: Why the web lately is all about JavaScript?
I read https://news.ycombinator.com/item?id=31341083 recently and feel quite frustrated because now everyone is rendering html using javascript. I'm on twitter reading web stuff, when they talk about "SSR" (server-sided rendering), 99% of the time it means javascript based server. Why these trying-to-be-innovation lately aren't not working with backend languages like python, ruby, elixir, go, rust etc?
I have an SPA app that is quite sophisticated whose WHOLE app size is ~110kB minified, and when I look at react-dom on https://bundlephobia.com/package/react-dom@18.1.0 it's 130kB minified which sounds CREAZY to me compared to my whole app (no, it's not a todo app, it's an editor app)
Is it just me that interpret this situation as "suck", or this is the future?
141 comments
[ 1.6 ms ] story [ 129 ms ] thread- https://htms.org - https://unpoly.com - https://hotwired.dev
Reading over the Hotwired homepage, I honestly thought it was a funny parody like http://vanilla-js.com Turns out it's an actual framework!
That said there is a movement for a more flexible style, e.g. https://htmx.org/
That and those writing JS on the frontend are, among all the devs out there, those the more likely to be working on SSR pages.
And there always was some sort of a separation in the industry: I remember when in some enterprisey places there was the strange role of "webdesigner" or some other (often incorrect) term that was half-designer half-programmer that only took care of HTML/CSS. Javascript was used very sparsely. There were several frameworks whose whole spiel was to allow people not to write HTML/CSS/JS.
Anyone doing both the backend and the HTML/CSS part was considered a bit of a unicorn, even back then. For a lot of self-taught people doing "everything" was the norm, but in the industry it wasn't.
Then came Bootstrap etc and sorta equalised everything. Then came Angular and React and we needed a name for people doing the HTML/CSS/JS work.
When rendering on the server became a focus again, the responsibility of writing the markup once again fell on people able to do HTML/CSS. Which means frontend developers. Which means JS.
My solution for that is to liberate UI programming out of a single language, using WASM as the abstraction layer. For more information https://github.com/joelewis/kwasm
React is a decent framework conceptually and more importantly it has become a defacto standard for UI development in JS. On top of that the sheer amount of React support in terms of components, tooling and learning resources is immense.
NextJS says “use what you already know and use on the backend (React), and not only that we will make it seemless to use the exact same code to render an initial paint for time to render/seo as you do for live updates, and we will chuck in static site generation for free”.
Tailwind is another thing that seems really really odd, until you use it and then it seems brilliant. In a nutshell it is css classes like “m-1” for a small margin.
It would be awful for a handcrafted static site, but it works great with React because it plays well with componentizing code. If skeptical read their site where they address the obvious reasons for being skeptical.
the reason why i have 3 tabs open using 3gb of ram.
Frameworks that generate HTML on the server side have been around a long time, but are mostly not considered in this category. I would say though there are a decent number of modern ones in the "static site generator" category that exist in many languages.
It makes sense to me that in the current iteration of web tech that the client code and the server code be mostly in JavaScript since it allows for a single code base between the front and backend. There is definitely hope for other languages in this space though as WebAssembly gains more traction.
As for the bundle size of an app, it's not too surprising that a bespoke app would be smaller than a modest framework. Choosing a framework will always be a trade-off of size, complexity and whatever features the framework offers.
I think wether you see it as "suck" depends on how much you love or hate JavaScript and how tolerant you are to using modestly large frameworks. Mostly, I see the modern crop of JS frameworks as a breath of fresh air compared to what precedes them, though the complexity of what is imported when running an `npm install` is enough to give me pause and a wish for something more minimal.
I don't hate javascript as I write it too, but I also write many other languages. And I also think more of the web generally.
If we take a step back from the most well-known client-server system (the World Wide Web) and look at other examples, we’ll find that client and server are often developed together, in a single language and similar architecture.
Frameworks and libraries provide generalised solutions to some common problems. In react and react-dom's case it's defining a ui in a declarative and more or less performant(wihtout making the dev think too much about it) way. The downside is; it includes lots of things your app doesn't need but other apps do.
The alternative is to roll your own but if your solution did all the things that the X framework did; then you'd end up with a similar size/complexity. You can build the features only needed by your app; but then I can't imagine the amount of engineering hours wasted for every apps custom framework.
And nowadays ~110kb is not that big of an application really. It might be really complex in terms of concepts and what it does but current day apps are a lot bigger than that in terms of size. So the size of frameworks doesn't make that much of a difference in most cases. For example the app I'm working on in my job has a total bundle size of ~15mb minified excluding any third party code. This is just the code written and being actively used by us. We don't serve it all at once and load as needed but still.
The gist is; there are options and there are tradeoffs.
Silicon valley adopted JS probably because of ease of access to cheap developers. Pity there is not a serious competitor from another Valley because i think they could beat them with superior performance in just about anything.
There are hundreds of thousands of developers now who only know javascript. They have no perception of the parts of javascript that are badly designed because they don't know any other language. They think that computers taking 500ms to render a webpage is just how slow computers are because that's how it is with javascript. They think desktop applications that use 400MB of memory on startup are normal.
People no longer weigh up the pros and cons of javascript and decide it is the best option for a certain project. Javascript is all they know, and it shapes their entire view of programming.
The same can be true of frameworks, databases and other tools.
JavaScript has got some rough spots, but it’s a fine language these days, with a nice multi paradigm support.
[1] jamesshore.com or letscodejavascript.com — they both run on the same servers.
The thing that led me to using the SSA style initially was that it seemed easy to write a backend and then bolt on a frontend. But there isn't actually a good transport layer for that, and the API for your web app and the API for API users usually end up being quite different. I think that GraphQL is intending to be the transport layer that just works (and since it's a graph you can query, theoretically means you don't have to write an API for your web app, teach your web app how to incrementally request things, cache things, invalidate that cache, etc.). I have found that ... it's not that great. The Go libraries for a server are terrible. There are no debugging tools. You send gigabytes of JSON for no reason.
My personal favorite API is gRPC-Web, but I guess browsers never added the hooks necessary for bidi streaming, and the "tree shaken" protos + gRPC-Web runtime are HUGE, so I've decided it's not worth being excited about anymore. I typically stick grpc-gateway in front of my gRPC services and get normal RESTful JSON. And then I'm at square one where there isn't any magic in React to make that particularly useful.
Anyway, yeah... just printing out HTML. Not that bad. Use fly.io and put the server close to your user and they won't even notice that it's slightly higher latency than caching everything in your SPA. And it sure is easy to debug when something goes wrong.
[1] https://alpinejs.dev/
[2] https://hexdocs.pm/phoenix_live_view/Phoenix.LiveView.JS.htm...
When you control server interactions on the client side, you can do things like optimistic editing, where the UI assumes the action will succeed and then does it in the background, and then handles the exceptional case where something goes wrong, most likely by returning you to a form; or things like queuing actions up when there’s no internet connection, and performing them when you get a connection again.
I want to emphasise again the importance of latency. I live in Australia. Most of the web is much slower in Australia than it is in the USA, not because of bandwidth, but because of latency.
The LiveView approach is convenient, but it’s technically not a good solution for most applications. It’s excellent for things like chat systems where being bound to synchronous operation and requiring a network connection to do things isn’t an issue, but I honestly don’t think it’s the best solution (technically, again; socially it may be) for much else.
95% of projects, I'd pick productivity over working offline, especially these days when being truly offline is more and more rare.
And lastly, even in JS, offline support is a pain in the arse, not a given. You have to design your entire app around it, it's not something you can add 2 days before shipping.
Have you experienced this type of thin client when you have half a second’s latency, or a connection that keeps dropping out, or moderately high packet loss? I don’t think I’ve actually encountered a full thin client in the wild, but from my experiences with other poorly-done (very common) network-bound web apps in such circumstances, I can report that things are considerably worse than one would expect—that half a second’s latency inexplicably leads to things taking several seconds instead of fifty milliseconds a lot of the time (though I will admit that a pure thin client is less likely to find this so); and that very brief dropout manages to lock the page up for ten or thirty seconds until it manages to (or decides to) reconnect, or just breaks your page completely so that you have to restart and lose progress.
I have worked on apps that work offline or partially-offline, but the problems of the thin client approach are so much more than that—which is why I didn’t use the word “offline” in my earlier comment. Prefetching. Caching accessed entities so that you can revisit them without talking to the server. The bfcache, once you’re talking about simple pages rather than apps. And various more things, some of which I spoke of in my other comment here.
The thin client approach is a nice idea. It can be suitable for tightly controlled deployments. It can be suitable for a very restricted set of apps. It can be a pragmatic choice sometimes. It will tend to be better than a badly-done client-side-rendered app. But I am convinced that it is not very often the best choice, taking into account both user and business considerations; and that for consumer systems, it’s rarely a good choice.
Obviously, there are ways to write the same page and end up with a smaller bundle size, but size is only one dimension. Javascript SSR offers (arguably) less development time and less maintenance (as there's simply less code since you handle both the same way) at the expense of other things, such as bundle size etc. As with any other tradeoff, you can't only look at one parameter and say a thing is good or bad, you need to look at the whole package and figure out whether it makes sense in the given context or not.
What's your testing story like in your hand rolled app? Do you have test for your atoms, molecules and organisms?
How well does your tooling support your code? Popping into a framework means you get to benefit from all the productivity tools that have been built around that framework. Rolling your own anything always means forgoing many conveniences to the developer and possibly the user.
The vast majority of people who use the internet don't know what JavaScript is, and especially in the US, most have no reason to really care about bundle size. No company is going to optimize for the very small group of people who browse with JavaScript turned off. Instead companies want to optimize for speed of development, testability, stability, ease of onboarding, etc.
And wouldn't it be hard to deal with all of them (starting with the quite common eyesight problems, though I guess browser zoom is mostly JavaScript-compatible, and red/green color blindness) without ensuring that the core website functionality works without JavaScript ?
It's enough for them to know that https://twitter.com/POTUS loads in half a minute, while https://nitter.net/POTUS loads almost instantly. Despite both being the exact same content!
Honestly I use Twitter occasionally enough that I've never even considered going to Nitter.
Financially that reasoning makes sense but economically it’s stupid because you will end up with the same shitty uncompetitive product as everyone else. The developer counter argument is to just raise salaries, but over that past 2 years salaries have exploded and yet businesses have doubled down on this idea of prioritizing candidate selection and no training.
To your point about code quality I agree. I have an OS frontend written in JavaScript that fully loads (completes page render with state restoration) in under 200ms according to Chrome’s performance tool. The code is about 340kb unminified. You won’t that with React.
If you work at a company where the software you write isn't what generates revenue, you're going to have a bad time.
There are plenty of companies where developers are the profit centre.
Which has always been my answer to over aggressive management strategies for "replaceable devs": If your product is fundamentally software, it will be as replaceable and disposable as your developers; Show some commitment instead and you will get it in return from worthwhile devs.
Employees perception of growth: it's easy to feel like you are learning more when it's something brand new because of how easy any topic is at the beginning, and you inevitably get more new things when moving; whereas pushing your existing abilities and strengths into incrementally more advanced areas is harder won and requires more fortitude. Also focus on short term financial gains over long term career growth: Although jumping ship has a tendency to force a re-align of financial reward with ability, it also resets your progress reducing your experience on long term project and denying yourself to opportunity to learn from the long term consequences of your decisions, which in turn can affect your long term prospects and financial rewards. (I am suspicious of candidates with a employment history of a series of short stints for this reason, because they did not have to live with the results of their output).
It's subjective, sometimes it's truly not worth staying, sometimes it is... but I suspect many people confuse short term gains with reasons to move, when their current job may in-fact be of more mutual benefit long term.
What’s the distinction you’re making here? To me it looks like you’re contradicting yourself, but I’m happy to admit I might be ignorant.
It’s a teaching tool in itself. You can essentially hire a janitor and make them an architect when everything just makes sense already and guides them in the right direction.
Of course eventually poor products are unusable, but I wonder if position on the barely-usable-to-snappy generates much revenue differentiation.
Like you have drupal with bunch of modules, it's slow as hell so you put redis caching. It's faster but not as fast, so you add varnish on top, so you don't even have to touch the php code unless you make a change.
But then you've never solved the problem, you just hide it two layers deep.
And same with javascript - 85% of sites are visit would work perfectly fine without any javascript. Loading would've been instant, and you don't even need ajax if you can spit html document fast enough - the browser makes it seamless anyways. But no, instead, we do animations and slow down the time to interaction because it's fine sitting on 1Gbit connection waiting for your slow backend part that's not cacheable.
JS isn't bad, it just feels like people think it can solve anything while not seeing issues it adds.
I've been building a webapp with Python/Django and HTMX, it works like a charm.
[0] - https://htmx.org
So to rise up a few steps on the Google results page, people turned to serving empty pages with a small JavaScript (which finished loading fast - so bonus points from Google) which then starts pulling in the actual content.
Dear Big-G: Thanks a lot for your hard work, you've really done something.
Most web apps dont have pretenses of being simple. They want to use tools that have room for growth, that have deep capabilities.
And they want to use the really good tools & libraries & technologies that will be used on more complex efforts. Specializing in being lightweight, narrowing the scope of your skills & capabilities is less attractive than getting good at something that works & ideally will also be fast in all cases.
I think it's good to reflect nack to 2014, when React was coming out, & think of what rapid development looked like. Hand manipulating dom trees, course grained re-rendering by setting el.innerHTML,... React and the virtual dom were a huge huge performance win. Some up-front load price, but an amazing boon to rapid rapid developmemt, grossly reducing the scope of concerns one had to think about in webdev, & massively speeding up rendering/updates at the same time.
React isnt the smallest but holy shit it propelled us into a massively massively faster world. Where development is just so stinking much faster/easier, where there are so mamy less bugs & memory leaks. Thanks react.
So why focus on a niche, special purpose skill set? Why go back to hard mode? Is a 30kB preact bundle actually any kind of problem? Is a 100kB react bundle really a problem?
> Loading would've been instant, and you don't even need ajax if you can spit html document fast enough - the browser makes it seamless anyways. But no, instead, we do animations and slow down the time to interaction
Because it's javascript we can often run the same code on the backend, & store & cache our documents or if it's light weight enough just render it (with already started/initialized workers). Hence: server side rendering (ssr).
SSR is very prevalent, actively supported out of the box in newer JS libraries/frameworks like Next. React has had support for "hydrating" a SSR page on the front end for a while, but required some investmemt & didnt just work out of the box.
Im very mixed here, about performance in general. On the one hand I want us chasing technical excellence, being fast. But I also see two things, one, that waiting for a second isnt the worst. Second, a huge amount of the slowness is ads and trackers, is shitty other people prpolems that businesses just accept, and developers at a company dont get much say in. Why would we spend iterations dropping load times from 2s to 0.4s when the damned trackers are still gonna make the site take 5s to load anyways?
React never made development faster.. easier to manage complex state but not faster development.
React hides all that away. The virtual-dom just works. Event handlers all get faithfully reconnected. You never end up accidentally having multiple copies of content or having deleted too much content. As opposed to the DOM's native retained mode rendering, React gives a much simpler immediate mode rendering.
And it's often faster. It's easy to do too much work, to end up replacing more than you need to when you are hand-working the DOM. React's diffing algorithm is quite effective at doing just what updates actually needed be done, where-as before I as tech lead would have to go re-walk through my teammates code & tune & optimize it, fix some of the gross inefficiencies.
Working the DOM used to be a complex & subtle art. A lot of simple stuff you could just do & it was ok. The API was never delightful, even with jQuery. But there was so much latent knowledge, so many particulars, so many hazards. It, in my view, made even simple things much faster to develop.
There is no hard fast & easy rule to tell how problematic managing the DOM yourself will be. It's not about state size. It's about how much work you're going to have to do to maintain the dom, & the risk of one interaction jamming up something else. Knowing you can safely work the dom requires a blend of careful analysis & general intuition, to feel out where different concerns might collide, and you can be wrong. And adding just one more feature down the road can cause significant nightmares, blow up these assumptions. For someone else who comes along to do some work & who doesn't understand every assumption you've made about interactions, the risk compounds.
Moving from a retained mode DOM-manipulating view of the page to a immediate mode v-dom backed view such as react can save a huge amount of trouble. That just deciding & justifying your decision that only a small tool is required is complex that I'm more in favor of using React everywhere than I was before you posted: this oversimplification & overreduction emphasizes to me how particular & careful you have to be about justifying picking a less-safe tool. Simply tallying up the state you need is far beside the point. The DOM's risk has always been more about compound interactions. If you have completely isolated things on the page that only need a couple fixed features, and you never plan to grow the capabilities, maybe conventional DOM swizzling is ok. I still find it hard to recommend.
No, that's completely false.
Most web "apps" are just text and images, and would better be thought of as documents, which after all is what the web is for. Re-inventing that out of massive piles of JS is strictly worse than what we already had, and in fact still have if only we would choose to use it.
Yeah, sure, there are definitely real app-y things on the web, and here on HN we're biased towards those as mental reference points because they're cutting edge and exciting. But those things are emphatically NOT "most" of what the web is.
There is a trend in OSS SW development to "continously improve " programs. This means that the program stays mostly the same but it gets over time a "gui improvement" which brings almost nothing new but a lot of libraries and bloat. Two programs that stroke me were Xaos ( which got a QT dependency) and Xsnow. Maybe jwz was right that every program evolves until it can send email.
I'm not saying SPAs should always be used because in most cases they shouldn't, but a well optimised SPA should in theory be quicker and provide UX improvements to the user.
130kB minified is nothing unless you make an app for people in Africa or very remote parts of the world. It is cached and is loads instantly on most connections. Check the network speeds of your users, it’s very likely more than fast enough to load a 130kB file once.
https://en.m.wikipedia.org/wiki/List_of_countries_by_Interne...
2 MB minified, compressed, ball of js is nothing. I've even seen companies accidentally put their debug builds in production (>15MB js ball) with without noticing or getting complaints.
I'm much more sensitive to page weight than most, and every sizable dev shop should have someone who is. But even I realize that current business reality is it didn't matter nearly as much as sensitive tech people think.
I will for example "excessively" test how many images in what resolution I can get away with. Is my json to big? Can I use a custom font? Do I need to start the "infinite" scrolling fiasco? In what order are things loaded? Are we requesting a html document that when parsed has us request a js file? Is its execution delayed by the dom state? Then it parses out html? And then that html requests media that loads lazy?
If I would find myself there the 130 kb (and its overhead) would persistently bother me. When I get to it it will get ripped out and replaced with inline vanilla js.
It's not just that I want my application to be snappy and appear instantly. I also want to see instant results when testing it. There is no build time. It doesn't exist.
>react-dom is 130kB
the goal of these tools is not building performant applications. the goal is enabling barely skilled laborers to churn out disposable shit as quickly and cheaply as possible
>I'm on twitter reading web stuff
do yourself a favor and don't.
And if one really needs a slimmer version of React, there's always Preact [1] which is 3k-4k gzipped and has pretty much the same API.
Of course, in real life the 130k of React is far from a problem. The React code is (more often than not) dwarfed by the application code itself.
[1] http://preactjs.com
If you search for SSR, you will not find PHP, Django, ASP.
I’m working on a new project that is using F#/Giraffe, with the Giraffe view engine. It’s using htmx to update content without a full page reload. I love it. It’s been the most fun I’ve had developing a web app in quite a while.
My reaction to this ridiculous situation:
Use Preact instead of React -- I'm planning to switch to Svelte next -- and using minimal dependencies and writing my own minimalist implementations where feasible. I need to get better at this.
Use code-splitting and lazy loading to keep gzipped download under 100k for all content per "page".
Avoid web fonts, images, tracking, 3rd party crap, cookies, advertising, etc etc etc. I'm lucky enough to be in a position where nobody is telling me to put this stuff in.
Tree-shake, minify, compress (brotli if possible). Sure, it takes processing power to decompress at the other end, but my suspicion is overall compression wins. Happy to be proven wrong.
User-test everything on a throttled connection at 3G speeds. Or "poor 3G" or whatever the browser dev tools have. This is subjective, of course, but gives me a good sense of user experience.
It's not a perfect recipe, but downloading megs of crap for a web page is totally unacceptable.
(Obviously all the above side-steps the "no JS" perspective.)
Solid is currently more oriented towards fully interactive SPA use cases, but they do have partial hydration (or something like it) on the roadmap.
Also in a conference / the train / the beach / driving / any crowded place / in space
No. This is cached if the devs aren't incompetent, the lion's share of information transfer is video streaming, not large JS files.
Your point about video streaming being a far larger amount of data is of course fully valid. But I was replying to a thread about JavaScript.
I am calling these applications Hypermedia Driven Applications or Hypermedia Oriented Libraries:
https://htmx.org/essays/hypermedia-driven-applications/
libs like unpoly, hotwire or my own htmx are all hypermedia oriented, recentering HTML and hypermedia as the core application architecture for your app
some other related essays:
https://htmx.org/essays/spa-alternative/
https://htmx.org/essays/a-response-to-rich-harris/
the really nice thing about the hypermedia approach is that it takes pressure off adopting JS/TS on the backend, since you no longer have a massive front end codebase already in JS/TS and it can be hard to justify having two different languages, models, etc. With hypermedia, you don't have this situation. I jokingly call this "stack" the HOWL stack: Hypermedia On Whatever you'd Like.