Tom MacWright: Second-guessing the modern web
The emerging norm for web development is to build a React single-page application, with server rendering. The two key elements of this architecture are something like:
- The main UI is built & updated in JavaScript using React or something similar.
- The backend is an API that that application makes requests against.
This idea has really swept the internet. It started with a few major popular websites and has crept into corners like marketing sites and blogs.
It's hard to quote just one bit but there's a lot in here. React (and many single-page application architectures) is a good fit for managing a certain level of complexity as long as you don't ask of it more than it can deliver.
For simple things, you can often get it done with simpler solutions. Take has no visible JavaScript if you're just visiting the site as it is. That's not a dogmatic decision – if I need to bring in JavaScript for compelling functionality I will, but there's no need for that at present. I'm writing this into a post editor right on the front page, with Markdown rendered live as I type, and the JavaScript and CSS to support it is being conditionally included when I'm visiting the site.
I love the basic idea behind React, which is to solve the inevitable problem anyone who tried to "just hook together" functionality using jQuery ran into, which is drift and divergence in UI logic. Doing iterative things to bodge something into just the right state from all over the place, and getting things done right up until the point where you start cursing your own love for expediency.
But React comes with the associated mess every JavaScript framework comes with. It's not the language as such (even though it has perhaps the worst standard library design sighted by reliable witnesses), it's that you have to use ten tonnes of slow-moving, complex infrastructure to build a pipeline for module loading and code splitting and minification and source maps, not to mention cross-compiling down to the revision of the language people can actually run. And it's the kind of thing that you don't do exactly the same on all projects, and the whole world moves enough that you can't really just crib a version from another project, because if there isn't a new language feature or technique you want to use, there's damn sure a new version of the bundler which promises to fix some inherent corner case you keep running into.
To their credit, the React team has made create-react-app
which is a command line tool to generate, wrap and maintain a known good configuration of one such solution, but to configure it you have to "eject" from the ecosystem, and at that point you're in the same place you were. Angular also comes with a command line tool for related but not identical reasons, and it's emblematic of the problem and the culture. Pulling down a stack of paper that would reach your ceiling a few times over is not seen as an issue.
Even if snapping your finger and getting everything tooling-related working was possible, which I'm sure it is at Facebook where React is developed, the next round of problems arise, which is that having flipped the world on its head, you now have to find, develop, document and cohere a new set of solutions to all related problems, like, oh, fetching data and handling the evolution of state, which are inherent problems in all projects where React solves anything.
Dan Abramov of the React team and creator of Redux (which I also like) describes the issue from Tom's post as straddling the server-client divide and requiring a holistic solution, which may be true, but pretty much locks everyone into running JavaScript on the server (or the React team into providing server-side parts for all major server-side frameworks), and preferably committing yourself to ancillary technologies like GraphQL. One of my big problems with React is much bigger with GraphQL – that normal use cases like "authenticating", "mutating data" or "understanding how the hell you implement something that if unconstrained can basically cause you to need to generate arbitrary queries on your server" are tackled only incidentally and hand-wavily, and can never be thorough enough, seeing as how GraphQL is a specification instead of a library.
There are many things that can be done with JavaScript that make so-called single-page applications worth thinking about. And it's easy to see everyone who questions the state-of-the-art as either grumps or web haters. But Tom's post shines a light on the spectrum of solutions and serves as a good reminder that simple solutions can be the most appropriate and that React has a long way to go before all parts of using it are as attractively coined as the core, which was rooted in an actual problem, observation and mitigation that brings many of us in to begin with.
I believe in the web as a platform that is uniquely suited for many things, but also as a stack of technologies whose characteristics and limitations should be understood and respected to achieve the best result. Focusing on scaffolding and tooling and reworking revolutionary internals in order for brief code samples to become more powerful risks missing that the extra effort to support this process is a significant cognitive and operational load for everyone who uses the framework, and plants the expectation for newcomers that it's okay for 5000 things to go on behind your back, which is poisonous to learning and an impediment to problem solving.