The case for vanilla front-end development
pushdata.io
pushdata.io
This is the thing that baffles me about the SPA/framework trend, regardless of connection speed. The whole pitch for React/Vue/etc. is that they're supposed to make for more responsive interfaces. And yet, whenever I actually use an app written in React/Vue/etc., I find myself marveling at how slow it feels. Even on a desktop PC with a fast connection, I spend so much time staring at progress bars and loading spinners as all the various bits and bobs of the interface get pulled down and rendered. I don't know whether pages that are rendered server-side are empirically faster, but they sure feel faster, because after a brief (usually < 1s) wait the whole page just, you know, appears, fully rendered and ready to go.
As another developer who's old enough to remember the CENTER tag, I'm open to the idea that this is just incipient old-fogeydom on my part. But whenever I hear people start talking about how much more responsive SPAs are, it sounds a lot like the old gag: "who are you going to believe, me or your lying eyes?"
With (e.g.) Vue, because you write so little code comparatively, it leaves you very little to do if the 'magic' that's making stuff happen under the hood is very slow.
I work with a largely native Javascript SPA (main dependency is d3) and find that Javascript can be pretty damn fast if you need it to be.
A lot of that is likely because of the way most REST APIs are laid out.
Suppose you're looking at a page that displays an invoice for an accounting system. With a traditional non-SPA app, you'd do a bunch of SQL queries and build a page from an HTML template.
With a REST API, you're doing one HTTP call per entity, at least, and then subsequent HTTP calls for aggregate entities.
When I've made SPAs before, I've often eschewed REST and just made a single Ajax call for "everything I need to display X to the user," not just out of efficiency, but also out of laziness -- it's easy to build. As long as you internally use your API only and don't publish keys for third parties, it's easy to maintain too.
There are some solutions to address the whole problem on a grander scale (GraphQL comes to mind), but overall, that's the cause of slow SPAs in my experience.
For one, the most major http client library (Axios) doesn't have support for that kind of pipelining.
But also, you don't necessarily know what to pipeline until you get the first request through. Most web apps will make a REST request, look at the contents of the response, then make another REST request. Maybe you could keep the socket open through that, or you could even use websockets to bypass HTTP altogether and use jsonrpc, but still, you don't know what you need to fetch in the second round until you finish the first one, so either way you're looking at a waterfall of requests, one after another. Pipelining them would scarcely help.
What would help is having one API request that basically says, "here's who I am and here's the page the user wants. Give me everything for it." Then you're moving the controller back to the server, and leaving only the view on the client.
I do agree that waterfall-style requests are more prominent with a REST structure, and that something like GraphQL could solve that - but GraphQL seems largely incompatible with how many develop web apps today; smaller components that request their own data. I'm also unsure how compatible a dynamic query language like GraphQL is with denormalized databases like Cassandra or ScyllaDB where you can't model your data before you've established what queries your site/app will perform. I've yet to see a codebase where the REST waterfall problem is a huge problem though.
Note that I too dislike how slow websites are these days, and much prefer to both build and use an entirely server-side rendered one. None of the SPAs that I know of has been a success in terms of performance; Facebook, Google Mail, Reddit's redesign, Youtube, Twitch - most of them are dreadfully slow and sluggish.
I'm suspicious about this data. This sounds way too much like the same misguided thinking that makes people ignore performance, because obviously your app is so special it'll be the only thing user will have open on their computer. I can buy this expectation for work SaaS, in front of which you sit for 8 hours straight. Most of those used by genpop? Opened briefly and rarely.
This means whoever wrote the app wrote it slow. React rendering performance is fantastic but that doesn't stop devs from abusing AJAX.
I've been saying this for years and always get heavy push-back by the framework proponents. I've also encouraged them to look at history. Ten years ago, it was ALL about Backbone. Then Angular came around and it was ALL about Angular. Then React came around and it's currently ALL about that. But, wait! Now Vue is starting to gain some traction. In 3-5 years it'll be ALL about Vue.
My point is this: if the frameworks are so great and all-encompassing (I've literally heard, "you can build anything with [FRAMEWORK]. You don't need anything else!"), why doesn't one of them stand out so solidly that nobody would think to create another one? Why do we, like toddlers grown tall, keep rushing to the next latest and greatest shiny object that catches our eyes?
I submit that that last 10% is the reason why OP got more done faster with Vanilla than he could with React.
That's always a lie. Take a logarithm of the number of subdirectories in node_modules, and subtract the logarithm of subdir count of node_modules for framework's hello world, to get an estimate of how much other stuff you're using.
This never ceases to puzzle me. I thought yuppie framework jockeys love to travel. Don't they ever find themselves at some remote locale, try to check in on things, and realize that their site runs like pure ass outside of costal North America? Do they just not care?
Simplicity really can be a class issue. Lots of developers seem to write code with their own demographic in mind, rather than the real people who have to put up with their bullshit.
I agree, though I'd qualify it because I'm sure they're testing the site, but it's on a fat pipe with low latency that easily hides any performance issues. It doesn't seem limited to web development though - game development seems to have the same issue, where it's clear devs are playing and testing on overpowered rigs with little regard for low-end systems.
It's not the same thing but it's a pet peeve for me when people make comments like "How could a developer skip X or not do Y?!?" Well not all of use can pick 100% what we work on and are sometimes forced to cut corners. We aren't happy about it but we are more happy with taking home a paycheck that being right 100% of the time. My go-to is "Is this this hill I want to die on?" when this stuff comes up.
Speaking of which, having worked a bit in corporate setting, I have my own extra point of hatred here too: I saw perfectly good, if crappy looking, server-side, plain HTML intranet apps replaced with most recent JavaScript framework shitfest, making my life extra miserable as I suddenly had to deal with some apps I was forced to use stealing computing resources from the very job I had to do.
If you build websites, come spend some time in rural Idaho - it'll change how you develop!
The observations were:
- ~6MB JS file produced by `npm run build` compared to ~400KB page weight for all items in my vanilla app
- Page load times from that Greek WiFi was ~4 secs for the vanilla app and ~50 secs for the React app, which told me the throughput was on the order of 1 Mbit/s. The React app didn't load many things (about 3 resources, if I remember correctly) while my app had more to do. This means network or server delay will have mainly affected load time of my app.
Of course, this whole performance/page weight thing wasn't the main point of the article (for those who happened to read it), nor did it very much affect my decision to go vanilla. I am surprised it became such a big issue here, but I've stated that I too think it was due to inexperienced developers. I guess my mistake was thinking that my lack of front-end experience would make it a viable comparison - I'm probably a lot more performance-conscious than most, and especially compared to someone who is just learning to program.
Something to consider:
1. If the server render is slow, everyone notices.
2. If the client download is slow, only people on slow connections notice and only then if it's not cached.
So in other words, your CUSTOMER on a fast connection might notice #1, but probably won't notice #2.
I'm not defending unoptimized code exactly -- I'm just pointing out that if the person paying the bills doesn't notice a problem, it's far less likely to get fixed.
Date and time manipulation, reactive programming, data binding, etc. Those are bread and butter stuff that the standard library should solve but doesn't.
I'm amazed sometimes of how complicated and heavy some people, especially new developers, make things.
While I usually pull in JQuery for small applications, sometimes all you need is.. well, nothing, just the core language(s).
Node - Check
React - Check
Angular - Check
NPM - Check
"See how much you've learned in just two weeks! You'll easily get a job with that!"
And so on.
Rather than learning how some of this stuff actually works, many new developers are falsely led down a path where they think they can't create cool useful stuff without relying on a massive number of libraries and build processes.
See the whole leftpad disaster for example (Yes, I know, they fixed it, but it happened to begin with).
No seasoned or even moderately experienced developer should be using a package for something as simple as padding something. If I saw leftpad during a code review I'd send it back to the dev to fix.
Right now I'm creating a website using pretty basic tools, no frontend builds, and a backend using FPC, Postgresql for DB and done, no mass of libraries, no cascade of dependencies.. Just good performance, simple builds (Single FPC compile to executable), and easy for anyone to wrap their head around the entire process.
It makes perfect sense for the bootcamps to exist to fill that niche, it's just horribly unfortunate for both the companies hiring people with less skill than they think, and the new developers being led down bad paths.
Another part of the problem is that job ads only show part of the image.
If you can show that you're a good developer with a solid track record, those HR checklists largely become null and void.
Just look at how many job ads include "Must have Bachelors in CS", which most of us know is complete bull.
If you have a stateful application (or even just a single stateful part on a static site), React will simplify life a lot.
Figure out your requirements and develop based on those. That's pretty much it. There can also be external requirements (e.g. we want to be able to hire easily, so opting for a well-known framework is better) and those should be taken into account as well.
react + react-dom is 33.4Kb gzipped. That's not completely trivial obviously, and if your app isn't doing much DOM work it's probably unnecessary, but nor is it the reason why any app would take 50s to download on a 1Mbit/s connection. The problem was clearly something else.
I have nothing against people who choose to hate on frameworks, but if your maths is that far off it really undermines your argument.
I didn't use a framework until 2016. I use React now and love it, and yet I still find myself using all of my knowledge of the DOM when writing React, to ensure that it behaves smoothly.
I personally think there are simply a higher number of devs who can code fine in React/Vue/Angular/whatever but don't fully understand the intricacies of the DOM. So the result is that these SPAs often feel slower. But it isn't the fault of the frameworks necessarily.
But still, that's a completely fair point.
highchart.js 75 KB
boost.js 11 KB
exporting.js 5 KB
checkout.js 26 KB
pushdata.js 57 KB !!
analytics.js 17 KB
and there's hundreds more KB of png images downloaded as well
This is when an idea that having everything loaded from 7 different CDNs for a page to show anything at all falls on its head.
My uncached domain resolve times are in the range 1-10 seconds. So in an unhappy scenario, when things chain up, because a page needs one resource to decide that another resource from another domain needs to be loaded, and so on, I can easily wait 10-30s on a web page to load. Combine that with an idiotic FOUC prevention, that many website's designers fall for - and it means starring at a white space for the entire time, until some stupid web font loads, despite the actual text content having been already loaded for the most of the time.
So if the wifi is combined with a high latency DNS, it's certainly possible. Not everything is about raw throughput.
I've seen websites that are driven by vanilla JS that use 30MB images for backgrounds. I don't claim that's a reason to use a JS framework.
I had to read that three times to convince myself that the author was not stricly equating "having a dev team of more than 1" with "being lazy and ignorant".
Anyway. If I'm never going to see and maintain your code, sure, go ahead and write it the way you want.
It will be. I work on an application that still uses JS libraries from 5-10 years ago, simply because refactoring to use a new library is usually unnecessary (or even counterproductive). There will always be a need to keep applications like that running.
There are some exception where a SPA is certainly justified, but for the most part a static site with some dynamic parts in JS is so much easier to produce and maintain. Also a lot faster to load.
It's easy to still use Webpack/Babel/etc with Jekyll. Here is a starter kit I made some time ago for some coworkers. It's for Vue but the same idea can be used for React, etc.
I'm all hands up for vanilla JS development, but I really don't think this drastic load/render time difference is caused by React but rather by the poor coding.
React is tiny, and you can see performance degradation like that only if you don't use it right, don't understand the life-cycle or over-engineer
Me? I like frameworks, I use them daily at work, I'm familiar with them, and I'm comfortable with the tradeoffs. I think in a multiple-developer environment you need to standardize things and a framework is ONE approach to that. I think it's the best approach in a shared environment but I'm not going to be so cocky as to tell you what the best approach is for you.
I mean reading about your experience with modals made me cringe a little (at how long it took) but hey, you didn't have to lean Angular/React/etc so you probably came out ahead so who am I to judge? Focus on what makes your business successful, for you that is clearly NOT the web UI (not meant as a dig) so don't waste your time using the New Hotness (tm). Instead work on making your API servers rock solid and adding features.
A User is NEVER going to come to you and say "I'd use your product but you used vanilla JS so I went somewhere else" they will say "your site doesn't work in X browser", "Your site is ugly/inconsistent" (I don't think this about your site), "Your API is slow", "I need to be able to filter my time series on X but you only allow for Y". NONE of these problems are fixed with a framework alone and fixing them with a framework brings it's own set of issues.
You do what works for you and clearly this seems to work. Keep it up!
PS: I'll have to keep Pushdata in mind for future side projects, looks pretty cool, this is the first I've heard of it.
The thing is, I see so many reach for the big guns and over-engineer their new, tiny app that they're developing themselves, with a friend or perhaps a small team. And I see overuse of components in general - the tendency to just pull in a new dependency via npm for something completely ridiculuous. This post was not about big, in-house enterprise systems development.
And in fact, thinking about my experience from that financial company mentioned earlier, I would greatly have preferred a standardized, external framework before the in-house developed macro/library mess that worked but was pretty much undocumented and whose inner workings were known to a very small number of people.
Because it is much more reassuring having a community back you up in case you get into the edge cases. DIY? Good luck, you are on your own. Not to mention you have to scaffold all the things that are already taken of by the framework.
It's also a matter of maintainability. If you can successfully predict that the project will always be small, then fast, bespoke code might be great. But it's usually not the case. Prototypes almost always turn permanent.
And once you're reasonably familiar with a framework it would make sense to use it even for a prototype. Unless you're actually interested in trying out "VanillaJS" or an alternative framework you would just use the tools you already know and get on with the problem you're trying to solve :-)
Instead of having a sea of divs and a trillion class tags on everything, you can use the proper tags for your document, e.g. 'article', 'aside', 'nav', 'section'. Then in your CSS just style it on those parts, so 'main > article > section {grid-column:2;}' with CSS Grid as the layout engine.
You can use classes for things like links you want to make into buttons and elements you want to toggle hidden, but otherwise the class-less way where your CSS mimics your document is much easier to maintain. If it breaks then it just means you have something wrong with your document, e.g. placed that form in an 'article' rather than the 'section' inside it where it should be.
CSS variables are also awesome, you can have your media queries just set the variables and the CSS rules just use variables, e.g. 'font-size: var(--font-size)' with what that font size is on different devices done in media queries rather than a whole bale of extra CSS.
Vanilla JS also goes with this pattern where you only care about evergreen browsers. You can use divs for containing non document things, e.g. some 'I am not a robot' iframe, but, with the mind-bending CSS grid there is no need for having everything in twenty containing divs.
Ah but, my site is complicated. Well it shouldn't be. If you have it complicated you are doing it wrong.
Also worth banishing are pixels. I took a while to banish them but now I am on ems and viewer units there is no going back.
For presentational niceties try and use pseudo elements with inline SVG stored in CSS variables. In this way the icons can be all in the stylesheet rather than extra downloads. Again, with icons, you are getting it wrong if they are complicated. If you can't draw an icon with simple 'rect' and 'circle' primitives then it isn't going to work as an icon.
Vanilla HTML5 is definitely to be downvoted by some, but you can give up the class and div HTML with silly margins, paddings, floats and hacks and do it all massively cleanly with CSS grid and the new tags. Don't even have a 'reset.css', go vanilla all the way.
The author published his project (a 2048 game clone) here: https://github.com/Swiip/vanilla-modern-js
A kind of variation on Greenspun's Tenth Rule might be in order:
"Any sufficiently complicated web application contains an ad-hoc, informally specified, slow, bug-ridden version of half of React".