Hacker News new | past | comments | ask | show | jobs | submit login

And what do you do for more complex, stateful apps? I don't think it's fair to dismiss this problem as "just use HTML and CSS and a sprinkling of vanilla JS". What happens when you need to build anything more complex than a basic form? A dashboard, or web map, or Figma, or Slack, or Gmail, or Gsheets... everything from state to AJAX (and other async) to persistence to URL routing, etc. becomes insanely complex.

I feel like "don't use tooling/frameworks" is the web dev version of "you don't need Java or .NET or WPF or WinForms, just use assembly and gfx drivers and draw pixels on the screen". HTML and ECMAscript evolve very slowly relative to the needs of software businesses, and it would take 30x (if not 300x) as long to write complex apps in those alone. Having a "build and bundle" step is just the webdev version of compiling developer-friendly code (React and frameworks) into the "lowest common denominator" code of browser-parseable HTML + JS.

It's not about "cleverness", but being able to do your job in a reasonable amount of time and effort, vs going back to a 90s-style internet where every page is basically a dumb terminal and all the actual interactivity has to happen on the backend.

I think is a better option is to know your target audience, their expected device and connection speed (metro desktop? rural mobile?) and not to worry about over-optimization. Nobody cares if your website loads in a second if it's so hard to use that it takes THEM more time to do what they need. Better to take 5 seconds to load, and then be actually usable as an app.

FWIW I don't think web apps are getting slower because developers are getting worse, but because the newer frameworks are enabling new use cases that weren't before possible. Photo editing? You used to have to download and install Photoshop, which can take minutes or days depending on your network and connection. Now you can run Photopea in a browser window in a few seconds and do most of the same things.

As for core web vitals? It's not a bad thing to use a performance arms race to get websites to be faster. It forces frameworks to evolve their delivery, caching, loading, hydration mechanisms. But that doesn't have to mean "give up on frameworks and complex apps". It can also just mean keep up with their latest performance improvements, and/or hope that ECMAscript evolves faster, that things like Web Components or PWAs etc. become more commonplace.




The examples you give are a 100% fit for the SPA model. Nobody would build Google Docs or a game from server-side HTML.

That's not the discussion. The discussion is everything except that. The typical example being a CRUD app. A bunch of cards, filters on the left, search box on top, logged in user. It usually isn't much more than that. Which means its low state and lowly interactive.


The problem is that there are a few cases in every CRUD app where it is undeniable that the best user experience would come from client-side rendering. Stuff like password criteria validation, filtering or sorting a column on a table, upvoting or downvoting a post, and other application specific behaviors shouldn’t require a page reload.

What we tried in the jQuery-era was augmenting mostly-server-side apps with components that handled these behaviors. But it wasn’t a good dev experience and it wasn’t a good user experience.

So a lot of teams choose to build entirely in JS nowadays since it leads to a simpler experience to have everything in a React SPA than some things in <dynamic form language of choice> and some things in jQuery.

I’m not saying this is perfect, I think we still have a long ways to go. But I’m optimistic about the current wave of JS tools (Hotwire, Astro, Fresh), and I think “just go back to server side frameworks” isn’t solving any problems.


But not everything is a black or white good/bad fit for an SPA, and you don't always know upfront...

Building a list of blog entries? Sure, it doesn't need to be an SPA. Add a tag filter? Still doesn't. Then you eventually need more complex filters (by author, dates, whatever), plus a text filter, plus thumbnails, plus maybe a gallery view of the photos, and maybe you want all of that with realtime clientside filtering... hmm. You can rip out that part of the static HTML and make it a drop-in widget.

But what if you need to tie that into the logged-in state of the user to determine what they can see? Or you want to integrate comments and facilitate real-time discussions?

Having a split backend/frontend rendering system like that makes it pretty hard to reason about (it's how a lot of PHP sites were built, for example, with serverside HTML and a sprinkling of clientside JS, but coordinating the two gets tough with ugly hacks like using `window` or `data` props to pass variables to the client).

Ecommerce? You can build it entirely backend, entirely frontend, or some hybrid of the two. Look at a random Shopify example: https://nomz.com/ (suggested by their website, not sure if real) and a Next.js example (https://demo.vercel.store/product/quarter-zip). Try browsing around and looking at different products. The Next version is pretty much instantaneous while the Shopify version is slow and requires a full page load for any navigation.

Another example from a decade or so ago was the "real" desktop Gmail vs the light/mobile (and maybe WAP?) versions of Gmail (maybe still available at m.gmail.com). They both did the same basic things, but the desktop version was a lot faster, featureful, and usable once you let it load for 5-10 seconds at first. The light version shows you the inbox really quickly but then subsequent actions (navigating to a message, replying, etc.) are actually slower than the SPA version.

Even for just a moderately complex site, an SPA model can be slower upfront as it downloads a bunch of JS but then faster after that, speeding up all the subsequent interactions (with JSON content loads instead of full HTML pages, auto-detected image sizes, smart prefetches based on state, etc.).

AND it doesn't require a rewrite once your site gets "complex" enough. You can start with a simple SPA that may be overkill at first, but keep growing it organically and adding complexity without dramatically increasing the bundle size (with proper tree shaking, etc.) since the bulk of it was the framework.

With traditional serverside HTML sent to the client, yes a simple individual page may be smaller, but you quickly lose that benefit as you keep sending the header, footer, etc. on every page load, while still needing some sort of JS management system for the interactive parts.

For all but the very simplest site, that means you sacrifice a lot of the developer experience for a minor increase in performance. The user also loses out if you start thinking in terms of "how do I add interactivity to my dumb HTML" instead of "what's the best UI for this".

Safer (and usually better) to just start from an SPA unless you absolutely know upfront your site is going to stay really simple. It's a lot easier to optimize an SPA for better performance than to rewrite a hybrid backend/frontend rendering stack and migrate architectures, etc. (i.e., Jamstack over LEMP/Drupal/Wordpress/Rails)


And what do you do for more complex, stateful apps?

To quote Albert Einstein, "Make everything as simple as possible, but not simpler."

This applies as much to your JavaScript bundler configuration as it does to the origins of the universe. It's not surprising really, because if I say "an instantaneous explosion that causes the entire universe to be filled with matter" you don't know if I'm talking about the Big Bang or Webpack.


> Having a "build and bundle" step is just the webdev version of compiling developer-friendly code (React and frameworks) into the "lowest common denominator" code of browser-parseable HTML + JS.

One problem is that for all the building and bundling webdevs do, only a few very recent frameworks (Svelte and SolidJS) can even manage to compile into something that even approximates "plain vanilla", progressively-enhanced JS on the client. And use of these is still the exception rather than the rule.


Maybe it's because I'm from GenX and from that era but I still don't get why JS frameworks jump through all these hoops just to avoid server-side programming. Why do all these round trip stuff when you could just render it server-side to begin with?


In large part because HTML was not designed as a "streamable" format. The main benefit of AJAX is that it lets you send information back and forth without needing a whole page refresh.

You don't have to load anything to send a request to the server. But when the server sends a response back, HTML by itself can't do anything with it. Interaction isn't really a part of the language. So Javascript needs to act as the client, and take the information to apply some sort of DOM transformation to the HTML so that the user can actually see the response and further interact with it.

Javascript is what allows HTML to be interactive in real time at the component level. There's a lot more of that these days than in the past.

The frameworks still do the same thing, at a higher level of abstraction and with better debugging and less verbosity and manual labor. They make it much quicker to create and maintain complex compositions of stateful components... if that is meaningless, your page probably doesn't need a framework, but a lot of complex sites today are exactly that (compositions of stateful components)

It's possible that may change in the future, like with the Web Components spec. But for now, once Flash was deprecated, JS is the only tool really available to web devs for this sort of usage. It's not that it's the best choice for an interactive web, it's just what history left us with... flawed, slow, clunky, but popular enough as to be worth the costs.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: