And as if the words "COO" and "jquery ui" in the same sentence weren't enough to raise eyebrows, what came next was probably one of the most mind bending software engineering episodes I'd ever witness. It turned out he was trying to put together a web UI for displaying a number of reports from some computationally intensive data warehouse query crunching. We're talking visualization of tables and tables full of data. Conventional wisdom would dictate that implementing this the traditional way would involve query optimizations, various layers of caching, separation of concerns, a framework to manage all the complexity, etc, etc, etc. His approach? Just do the naive queries (slow as they were), print directly to HTML old school PHP style, then save the HTML file to disk.
He was a bubbly happy type of guy and you could see the child-like joy on his face when he showed me how lightning fast the thing would load from navigating from one page to another because it was effectively looking at a static website once the pages had been generated once. I distinctly recall feeling a mix of confused feelings at seeing the guy break every rule in the "programming best practices" book and the undeniably good performance results from the sheer dumb simplicity of the solution.
I mean he basically cached the results for viewing later. As cringy as it seems, it was probably the optimal solution.
personally, I would have probably built out a materialized view and added memcache to generate json to make it easier to refactor additional output formats over time but that's just me. It still wouldn't have loaded as fast as sending a pre-generated html file.
> COO invents cache invalidation
I can bang out a basic landing page site in a few hours that will be extremely performant while pulling in zero libraries. But I would never want to maintain that over any extended period of time or added complexity.
In my experience, KISS results in the easiest solution to maintain. Then I get a litany of complaints from devs that "this isn't programming" or "this is a dead end to my career" and then they leave. Which paradoxically makes it more difficult to maintain, as I have no maintainers lol.
Not saying that latter is the case here, but I've ran into devs maintaining some monstrosity and then complaining about others pushing for off-the-shelf solutions not realizing that nobody wants to spend time learning some bespoke system they created that's not actually as great as they think it is.
Not going to bash younger devs in general but the fact is that getting the job done without thinking of their future career... is usually not high in their list of priorities.
You can only anticipate so much up front. You're always going to have to rewrite things after enough growth, so make it easy to add complexity later.
(one of their caching solutions -- which works very well, actually -- is to just cache the slow PHP output of many sites and serve the HTML directly)
Ideally, folks would use a thinner stack with _less_ JS, as that's rewarded across all the metrics. But in recent years, many teams build a "site" by building a SPA. As they're entrenched in that dubious decision, the only path to making it performant is adding SSR complexity. ¯\_(ツ)_/¯ Perhaps its the apparent conflict between UX and DX that leads to tooling complexity?
And to nitpick: Core Web Vitals debuted with 3 metrics, one of them being FID. The focus on runtime/JS performance has been there from the start. Regardless, I hard agree on your last paragraph.
+ PMs wanting to run dozens of AB tests at once in every single page
In theory improved DX leads to improved UX. In practice, subpar/lazy tooling needs to be worked around to get better DX.
I’ve added a lot of JS weight to migrate legacy apps to React always improving time to interactive and responsive error handling/messaging. Vanilla JS and even Jquery just don’t have the DX that allows them to scale in a corporate context (specifically because of under experienced engineers and poor “due dates”).
IMO it’s a lack of initiative from browser developers to move the web forward faster (obvious given the funding comes roughly exclusively from the developers of iOS and Android). I understand the inertia of legacy browsers, but it should not take decades to eliminate the need for these DX polyfills (eg like Jquery took to become redundant, and how long it’s taking React/Vue/Svelte style components).
How are you supposed to "less JS" your way out of that?
I thought the 'if the level of interactivity basically amounts to a form' of top-level comment sums it up nicely. Many are SPAs for the sake of it, similarly to packaging a website as an 'app' but not doing anything native, offline, or that really warrants it being its own app at all other than getting homescreen space on iOS.
(Totally off-topic: I can't believe Apple still doesn't let you organise that however you want. It's sort of a small thing, but also so in your face, by far the most immediate turn-off to me of iOS.)
How do you compare "fast" between "my journal entry today" and "Photoshop on the web" using one set of metrics...?
Indeed, I’ve seen higher NPS scores when it’s slower… the user feels like they are paying for more.
One essay on this topic… https://medium.com/young-coder/the-future-web-will-canvas-re...
I spent much of the last few years working on such hybrid apps (DOM mixed with graphics techs, with clientside UI and state combined with server-side with and persistence, etc.).
The DOM has never meaningfully slowed down for me, even with CPU throttling or testing on old laptops. Canvas has, especially in some builds of Firefox. Certainly for rendering graphics canvas or WebGL are better choices, but it's not a performance magic bullet for all apps.
More often than not, the performance bottlenecks are just some bug of ours (a poorly implemented search algorithm) or an unoptimized query somewhere.
No modern web app needs to be just one thing or another. Even if you're operating almost entirely in canvas (like a map) there's still a ton of Javascript (open layers, leaflet, mapbox-gl-js, etc.) that you need, along with being able to use the DOM where it makes sense (reusing buttons, alerts, etc.)
Canvas is also really hard to make responsive. CSS evolved alongside the devices and has first class units for all that. Canvas doesn't have those easy abstractions and having to virtualize your UI without CSS-like helpers (much less things like flexbox or Bootstrap) makes it hard to make standard UIs too. HTML still has its uses for now, though arguably React and other abstractions make it much less important.
Games and maps are just an extreme version of that, but other examples where clientside DOM apps with heavy JS can still be faster (compared to old school server-side HTML) and easier to work with (compared to canvas) are email, e-commerce, ebooks, dashboards, chat, forums, video tubes, search and filtering, galleries, documentation, project management, etc.
A big problem with this is that html is extraordinarily limited as a widget framework. You only have a handful of widgets available, and many of them offer very little (if any) customizability from CSS.
For example, say you wanted a checkbox, but you wanted to use a custom shape (Edit: shape - color is more easily controlled today) instead of the browser default. Well, tough luck. From HTML you'll have to put the checkbox inside a label, add an empty span next to it, and from CSS make the checkbox invisible and then get creative with drawing some boxes that look like a checkbox [0] (or, more realistically, load some custom graphics). So, if you're doing all of this effort anyway, why go through the effort of using the HTML input checkbox at all?
I always find it fascinating just how barebones and bad HTML+CSS is as a GUI framework. I really don't understand why people insist it's in any way superior to using a JS toolkit for anything requiring more than the simplest interaction (say, more than a newspaper article).
[0] https://www.w3schools.com/howto/howto_css_custom_checkbox.as...
What the fuck? Just use the actual goddamn checkbox. You can set colors with CSS, but also, it will work in exactly the same way as all the other checkboxes on the user's system. It will respond to keyboard and other input shortcuts the same way as all the other checkboxes they use. It will work with any accessibility devices the user has in the same way as all the other checkboxes they use.
Don't reinvent standard controls just because they're not "customizable" enough. Function is more important than form, and the standard control has a lot more function than you're probably aware of. Also, the user already knows how the one on their system works, because they've already used one hundreds of times.
And the same goes even more so for controls which are more complex than the checkbox. Which is, uh... checks notes... all of them.
Just stop.
Especially for web apps, writing them so that they look good on every browser with default styling for every element is... Difficult.
Not to mention, users often use the same app from different browsers (laptop, phone, tablet), and are much more easily confused by the different styles of each device and browser than if the app itself is consistent, but different from other apps.
Edit to add: I'm very curious if you can find some major sites that do actually use the default checkbox controls - Google doesn't, YouTube doesn't, Apple doesn't, Wikipedia doesn't, Mozilla doesn't (though I did find a default radio button on their donate page), Microsoft doesn't. Even HN uses plenty of default controls, but still you'll see some custom controls, such as the upvote/downvote buttons.
We came damn close to every OS operating like this in the late 90s. Sadly the future arrived.
Don't reinvent well known controls. Stop doing it. You can give it a border color and an accent color (check out the new accent-color CSS property) and for the rest you leave it alone.
Try to extend this idea to a game menu and see how much sense it really makes to you: would anyone really want default browser checkboxes in an otherwise medieval styled game UI, for example?
Also, if you truly believe that all checkboxes in all apps should look exactly the same (per browser/OS, and except for color), then why not extend this to other aspects of design? Why even allow different sites to use different fonts? That is much harder to adjust to than a different roundness on checkbox corners.
HTML has a lot of virtually useless controls due to their limited styling. And yeah, sometimes you want custom-looking checkboxes, because you just fucking do and design matters. Also, on some browsers, checkboxes don't even have the lauded accessibility you're thinking about -- I recall a time where zooming in in Chrome wouldn't change the size of checkboxes!
Those aren't even the most egregious examples, to be honest.
In which case, people with accessibility needs won't be using that browser. And that's the whole point. The user can pick whichever browser works best for them, and implements the standard controls in the way they want. (Or, in the way that sucks the least, out of the browsers available to them.) And if they decide to get a better browser (different engine, or even just a major upgrade to the current one) suddenly all their websites work better. More importantly, they all work better in exactly the same way, so they only have to get used to any differences once, rather than for each and every website.
If you go and write your own version of a standard control which implements it that way you want, you take that away from the user.
HTML allows you to specify the semantics of the controls you want, and have the user-agent bother with the details about how it works. That's going to be more lightweight, more performant, and more user-friendly for more people than any alternative you bodge together yourself.
I have a bunch of legacy custom controls I deal with regularly because things like color pickers were not cool enough in 2009. The down side is that in 2022 they regularly break and require dev time to fix so some report that gets run once a year works correctly.
Hopefully, in someone else's timeline. But the user/customer is complaining to you, not to Google
Because HTML is the only way to do a checkbox?... Even if you use JavaScript, at the end of the day you'll have to generate HTML for it to render... so then why go through the effort of using JavaScript for a checkbox at all?
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.
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.
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.
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)
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.
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.
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.
Having worked on one of the most bloated SPAs at Google and doing an SRE rotation to optimize exactly these metrics, I couldn’t agree more on the hypothesis that this is where complexity, jank and fragility arises.
This is why our startup set out to build the best-in-class frontend for cloud computing and making a bet on SSR. I’m from a JavaScript background and personally think hate for the language is undue. V8 is also a marvel of engineering. We elected Go for our application language. It’s faster for our purposes but with SSR the domain language isn’t as important. We could use Haskell if it was fit for the problem domain. We empathize with how ideas such as “user-perceived latency” came about but SSR is a much simpler model and our philosophy is that “simpler is faster is faster”.
I thought if you're using server side rendering you'd be serving HTML directly from your application.
Render the entire page in one go, rather than have the server render small chunks at a time and have the client patch the DOM. I.e. not having to think about below the fold, adding event handlers to pre-empt and preload. In practice, you’ll need to sprinkle in JavaScript interactivity, but the point is keep this to a bare minimum. See Craigslist or HackerNews.
Let me guess. Google Ads?
We have a very slow eshop, worst than any competitor, yet the priority is always new features that will make the life of users even worse.
It's a bit like your car. It takes you from place to place and could drive much faster than speed-limits or traffic-jams allow. But getting from place to place is not all you want. You want to pay extra for the coolest looking fastest wheels you can afford.
When you work with an app or app-development tool that looks cool your self-image improves. You are a cool dude because you work with a cool-looking application. Seriously, it does have an effect on me.
Another theoretical advantage is that you can get better colocation of content, style and functionality.
Basic JS is pretty annoying to write. It reminds me of using goto for control flow. It’s a lot cleaner to be able to put functionality alongside the document structure.
Of course, you can use HTML + CSS + JS but you can also use Assembly for all code. But the end solution here is not Frontend frameworks.
I think it’s time browsers give us a better abstraction to HTML + CSS + JS. Webassembly and friends are nice, but I think the 3 fundamentally need to be replaced together in a performant way such that the simple case of no client side code is well optimised. Frontend frameworks are just a symptom of the problem which is that Web devs have to use the only abstraction creation mechanism available to get nicer development properties.
Agreed. As I've been developing a service (https://prose.sh) with no javascript and only go templates, the biggest downside is autocomplete.
I agree with you, but there’s some sort of complexity agreement in corporate environments, because people aren’t willing to accept that you don’t need a large build process, or any at all these days, maybe outside of a build pass for JSX.
Good. An interview is as much you assessing your potential employer as your potential employer assessing you.
If you do this and have a sufficiently complex application... you will end up where the modern frameworks are. They exist for a reason.
Hydration is... an automated system to do this? Am I missing something
What if it doesn’t? I mean by requirements from various departments/analysts and user’s common sense.
I'm slowly coming around to the idea that PageSpeed (or Lighthouse, or Core Web Vitals, or whatever Google has invented this week) is what drives a lot of the complexity in web app dev. People refuse to throw out what they've learned, so every time there's a new metric to chase in case you lose SERPS ranking for being slow! devs heap another layer of complexity on to the Webpack bonfire.
Hydration is an example of this. People chased 'first contentful paint' and 'cumulative layout shift' timings because that's what Google told everyone they needed to optimize for. That meant reducing the amount of upfront work done in JS, pushing some barebones HTML and CSS to the client for those sweet, sweet metrics, and then running a massive bundle of deferred JS to make it do anything. Google is pulling that rug with Time to Interactive, First Input Delay and (coming soon) Interaction to Next Paint, so now devs are trying to write the same website but have the server strip out the code they wrote (eg Remix.run).
Everyone wants a fast website. No one wants a heap of fragile complex build tooling. The answer to the first problem is to stop trying to solve the second problem with MORE TECH. Go back to fundamentals. Just make something that works with with HTML and CSS alone, and enhance it with JS. You don't need to be clever about it, especially if the level of interactivity on your website amounts to basically a form.