Web dev and insanity
Recently I got assigned web dev work and came to a conclusion: either I am insane or everyone who uses any Javascript framework (e.g. React) or component library (e.g. MUI or Bootstrap) is.12
There are a lot of otherwise really smart people who swear by React. And using two completely different languages and frameworks to write a website and an API that the website calls. And using component libraries that to me just seem completely useless.
I suppose I ought to include a disclaimer: it is almost certainly not the case that React is always a bad idea. In fact sometimes it may be the best idea. My point here is that often (but not necessarily always) it does turn out to be a bad idea.
React
Let’s start with React. Why on earth am I writing
className
instead of class
? Why should I write
<Link>
instead of <a>
? So on and
so forth. There are technical reasons for this. I know what they are,
thank you very much. But if we are going to depart from standards and
muddle up the 1-to-1 relation between “what I write” and “what is
rendered”, there better be really big benefits to doing so.
Using <Link>
as an example, does making your
website a single-page client-side-rendered application actually help
anyone?
No! You are not making the next Google Docs. Most websites with a backend are some selectively rendered text, a few images, and a bunch of HTML forms. Websites with significant client interactivity are a different story and not one I know anything about. But if your website is literally just a blog (which doesn’t behave any differently for different clients, by the way), you really should not be writing it in React. It’s just complexity for no reason most of the time. Oh and by the way, this isn’t just “React is unnecessary most of the time”, it’s “Javascript is unnecessary most of the time”. React is much more complicated than plain Javascript, and so the bar for its inclusion ought to be much higher.
Component libraries
Component libraries are also hard to justify most of the time. Let’s take one of the more popular libraries, React Bootstrap (to be clear, Bootstrap CSS itself seems fine), and look at the first component they have: the Accordion. Here is the HTML code that gets generated.
<h3 class="anchor anchorWithStickyNavbar_LWe7" id="basic-example">
Basic Example<a href="#basic-example"
class="hash-link"
aria-label="Direct link to Basic Example"
title="Direct link to Basic Example">
</a>
</h3>
<div class="playgroundContainer_TGbA">
<div class="playgroundHeader_qwyd">Result</div>
<div class="playgroundPreview_bb8I">
<div>
<div class="bs-example">
<div class="accordion">
<div class="accordion-item">
<h2 class="accordion-header">
<button type="button" aria-expanded="true" class="accordion-button">
Accordion Item #1</button>
</h2>
<div class="accordion-collapse collapse show" style="">
<div class="accordion-body">
Body text #1</div>
</div>
</div>
<div class="accordion-item">
<h2 class="accordion-header">
<button type="button" aria-expanded="false" class="accordion-button collapsed">
Accordion Item #2</button>
</h2>
<div class="accordion-collapse collapse">
<div class="accordion-body">
Body text #2</div>
</div>
</div>
</div>
</div>
</div>
</div>
Yikes. Why is the title of a collapsible item an
<h2>
? This is not good from an accessibility
standpoint. This collapsible item is organized under the
<h3>
with the title of “Basic Examples” for Pete’s
sake. So clearly, it and its title should semantically be a part of the
<h3>
header. But the HTML code indicates otherwise.
And any programmatic tool which relies on the semantics of the
HTML (which by the way, includes accessibility software) is not
going to work well if you generate semantically incorrect HTML. And no
amount of aria tags will make up for the fact that your HTML is
terrible.
Also, a button? It’s not the worst thing you can do, I guess. At
least aria-expanded=true
is properly set. But you can do so
much better for a dropdown.
Dropdown code
<details>
<summary>
Dropdown code</summary>
<div>
Pretend there is some code here.</div>
</details>
Given how simple this is, why would you ever write this code?
import Accordion from 'react-bootstrap/Accordion';
function BasicExample() {
return (<Accordion defaultActiveKey="0">
<Accordion.Item eventKey="0">
<Accordion.Header>Accordion Item #1</Accordion.Header>
<Accordion.Body>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.</Accordion.Body>
</Accordion.Item>
<Accordion.Item eventKey="1">
<Accordion.Header>Accordion Item #2</Accordion.Header>
<Accordion.Body>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
minim veniam, quis nostrud exercitation ullamco laboris nisi ut
aliquip ex ea commodo consequat. Duis aute irure dolor in
reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.</Accordion.Body>
</Accordion.Item>
</Accordion>
);
}
export default BasicExample;
The <details>
tag is more accessible and easier to
style to boot. There is literally no downside.3
And the worst thing is that frameworks like React Bootstrap pass
automated tests like Google’s Lighthouse with flying colors. But look
for a couple of seconds and you can already see issues. (I don’t know if
Accordion titles are always <h2>
elements,
but I suspect the answer is yes. Regardless, it’s not the greatest sign
if the title is a header on their official website.) And React Bootstrap
is doing quite well for itself, actually. Just look at MUI’s
accessibility issues on GitHub.
But this isn’t supposed to be an expose about accessibility.4 The main point here is that using a
custom “Accordion” component is moronic if <details>
is already available to you at no cost. Accessibility just happens to be
one of the big reasons it is stupid.
A potpurri of unnecessary uses
There are a lot of reasons people have to use React, component libraries, and other similar things. Let’s run through them:
- “It is more accessible.” Making all of your code (including your rendered HTML) more complicated and error-prone is not accessible.
- “It resizes well on different devices like phones.” Only if you apply different styles based on screen width, which is much simpler to do with plain CSS and media queries.
- “It makes my website look nicer.” No. Everything is reproducible with plain HTML and CSS. It all compiles down into (semantically poor) HTML and CSS. And using plain HTML and CSS ends up being simpler. It is hard to grok dozens of 2,000 line minified Bootstrap CSS files whose default values are a mystery to all of mankind. It is much easier to understand a small CSS file
- “It is necessary to connect my frontend to my backend and create a full-stack website.” Factually false. There are simpler and more robust ways to do this. Rust frameworks like Actix-web, Rocket, etc are much more robust . And it is simpler because there are less layers in the client-to-server connection: browser-website-server as opposed to browser-website-api-server. And only having one middleman is important because it allows you to guarantee consistent datatypes to represent your SQL tables (or whatever your database uses).
Now I am not going to go as far as to claim React is totally useless. This is very likely untrue. But it is the case that a lot of the reasons people think React is useful are total hogwash, at least for their specific use cases.
What do you do?
So how should you write a website, particularly a full-stack website? Two years ago5 I teased an answer to this question:
I hope this post was helpful! A post on full-stack websites will be coming soon :)
Two years later and I will tease it a bit more. I am planning to write a total of three entries, one of which is already done:
- I will start with an abstract, simplified explanation of the principles of client-server communication. We will start with username-password authentication, then dive into cookies, and finally we will discuss why encryption is necessary.
- We will add more detail to the abstract client-server model. The client is usually just the browser; the server can be divided into the API and the database. Furthermore, there are many other types of clients that work. For instance, you could use the terminal to interface with a CLI, which sends a request to a programmatic API that queries the database. The important point is, anything on the server can interact however it wants with anything else on the server, and with a few exceptions, the same is true for the client.
- We end off the series by looking at web frameworks, discussing what a “tech stack” is, and some of my recommendations for what tools to use for creating a website.6
I plan to write the first two entries fairly soon. The last entry will be written eventually, likely when I have finished Glee.
Those who have followed this blog know what I think the answer is :)↩︎
There are some oases of sanity out there.↩︎
Technically a simple dropdown doesn’t match the function of an accordion, since accordions enforce that only one item is open at once. Putting aside how terrible of a feature this would be in most cases, it is quite easy to implement with just HTML and CSS.↩︎
I am not the right person to write about this, and I’m sure people who create components are trying their very hardest to make components accessible.↩︎
How time flies!↩︎
You can probably guess what they are. Avoid React, make the website (one of) your APIs (though this does not preclude you from creating a REST API that, say, a CLI could interface with). Write your backend and frontend in the same language, ideally in the same project so that your backend types agree with your frontend types. (For example, you can use a Rust framework like Axum to both query the database when appropriate and generate HTML.)↩︎