The best platform for developing apps in 2019 is not one of the major frameworks but – the platform. The “platform” is the collection of native technologies available on browsers. And they have finally reached the point of disrupting the established frameworks.
That’s not to say, that you will see a significant rise in Apps being developed without Angular/React/Vue (or some more obscure framework) in 2019. That will take some more time. The platform tech is there, but for it to pick up momentum more is required.
First the web developer community needs to figure out patterns of how to best employ the technology. I think the current approaches are misguided by a very misleading history. Let’s have a look at that, shall we?
Some History – you may skip this section if you don’t care
1989 Tim Berners Lee (then a Tim, now a Sir Tim) had an idea on how to link texts. His work was technically outstanding in its vision and flexibility. But the convoluted history of web development started with him. For example he made up some ad hoc standard tags which were later partly revoked. Then came the browser wars where every browser vendor made up standards as they best saw fit to hurt the competition. After Microsoft leveraged its desktop monopoly to kill the competition, the dark age of web development ensued. Microsoft miscalculated the potential of the internet, ridiculing it before the dot-com boom and thus send out its dark lord IE to terrorize web developers into not fulfilling the web’s promise.
By then, web development was a terrible business. IE was by far the number one, but there were others, too, that needed to work. And IE was a notoriously incompatible buggy piece of shit. Along came jQuery. That library is a nice collection of syntactic sugar to get things done faster. But most importantly it was a compatibility layer that allowed developers to actually get something done for a change, instead of working around IEs many bugs and incompatibilities.
And the (web development) world was never the same. At the same time a couple of other frameworks sprung up, but none gained comparable traction. And thus jQuery became the de facto lingua franca of web development. Until.
Google finally had enough. As a company living on and of the web, they were terminally fed up with Microsoft’s malevolence or incompetence and with the Mozilla project’s failure to deliver great performance. And so Google developed its own browser, Chrome, which took over the world, almost sinking Firefox which had just stolen the crown from IE.
After Microsoft, too, lost the – in truth neverending – browser wars, they finally saw the light, and made IE somewhat compatible. Around that time long time proposal HTML5 became standard, too, and jQuery was still a cool utility, but its compatibility killer selling point lost traction. It was also a toolkit designed for breathing some life into web pages, with an animation here and some cool color changes there. It was never made to build complex web applications which started showing up around that time.
So jQuery became kind of obsolete with regards to the big picture. Today many big sites use jQuery, but if you want to build an app you look somewhere else. jQuery did achieve one thing, though: it raised a whole generation of web developers in utter awareness of the indisputable fact, that you need a layer of abstraction between you and the browser if you want to develop for the web.
Along came Angular, the next supreme ruler of web development. Angular did two things: it established a structure to web projects, that wasn’t there before. If you develop a complex application with several developers, structure is a key concern you need to get right. Web developers, being on average web designers who learned some coding at some point, tend to be somewhat lacking on such things. That may well be the prime factor of Angular’s success.
Now Angular allows you to say: “Okay, this is a title, I’ll tell you later what’s going in there, but if it’s green, I want it gone.” Web developers love that stuff. It gives us a lot of power. And what do web designers who learned some coding do with a lot of power? Use it. But forgive them, for they know not what they do.
That’s not arrogance, but humility. I’ve been coding (starting with rough boy C) for some 20 years, and I certainly don’t know what I do, when I write “Okay, this is a title, I’ll tell you later what’s going in there, but if it’s green, I want it gone”. The thing is, each of these frameworks is the size of a small (Vue) or sizable (Angular) book. When I write that sentence, they create a partial, virtual HTML document, and later tow a plough through it with a Ferrari. When you look into what’s happening, your head starts spinning immediately – that was already somewhat true with jQuery, and it did not exactly get better from there.
The End of History
If that is the case, you’ll have to wait another couple of years, before you get rid of vendor lock-in and thrive on the platform. Because each such framework comes with its specific idiom of gluing the imperative world to the declarative. And getting a canonical, browser supported way of uttering such things, would take a very long time. If it’s going to happen at all, that is. The End of History may not be nigh, after all.
So this rand-ish article has narrowed down to the interaction of imperative and declarative. That’s just one aspect of application development, though the one that web developers spend most time on. I mentioned Angular’s killer selling point: project structure. You need that. But you do not need a web framework for it.
This is one of the things that the web development community needs to figure out: What is the canonical structure of a project? There will be more than one answer to this, but things are starting to become somewhat evident: When you have a big project, you probably better manage application state separate from rendering. Redux may not be the final word on this, but the overall architecture it imposes is very likely here to stay. When you have a small project, you may get away with two-way-binding.
Do we need a build chain? If not, we still need a canonical way of telling the server, what to push with a page over http/2. Build tools are already independent entities, though each framework embraces one in particular. Same goes for package management.
There are many more such questions. And hopefully, in the future each project will have a different combination of answers instead of being locked into one of a few framework worlds with one set of answers for each world.
Yet, there is one more thing, that’s becoming pretty evident, more so than any other: you organize your views into a composition of components. A tiny component may be a label, a simple button, an input. And the next level component, e.g. a form, may be a composition of the former three. This is one thing, that all relevant frameworks, most irrelevant ones, and the platform agree upon, for once. Which brings us back to the question of how imperative and declarative interact in components.
If you are dead certain, that throwing the two into a kettle a giving it a good stir, you may pick a tiny render helper like lit-html, stencil … it has to be seen, what gets out on top in a few years. Well, maybe you stick with Angular/React/Vue, for now. Yet I’m here to tell you, that while mixing object oriented, functional and procedural is perfectly fine, mixing declarative and imperative may not be.
Declarative and imperative languages are both tools who’s greatness is hard to overstate. Imperative gave us the whole IT world we have today, and declarative build the web on top of it besides other things. But mixing them is something I’m starting to grow sceptical of. I did it for several years, and I get growing doubts about it.
The reason for this change in attitude is that a title is something different parts of the code may be interested in. And if you mix declaration and binding to imperative code, parts of the latter start stepping on each other’s toes. The mixing of worlds violates a paramount principle of computer science: the separation of concerns.
Why does everybody get away with this violation these days? Because components. Components separate the whole code along a certain axis. Each component owns its template and can rest assured, that nobody else will mess with it.
So all good? I guess, if you’re willing to constrain yourself to a very limited way of doing things, it is. Good that is. Indeed, this limitation probably is another killer selling point of Angular and what came after. I alluded to the web designer who learned some coding at some point.
Web developers are likely the largest subgroup of developers on the planet, these days. And the quality of web developers has a very wide range with lots of people wiggling through and pretty few highly skilled software designers.
In such an environment, limiting the options is a great plus. You give your developer a map, draw a red line and tell him: “Follow this route, at the end you’ll find my app”. This leaves less room for failure than telling him: find my app, the sky is your limit. And it leaves behind bloated crappily performing web apps with little reusable code – the plethora of reusable stuff is usually done by the skilled folks (often outside of projects), and hardly intelligible to the average developer. It leaves no room for greatness to happen.
And the major frameworks have become very complex intimidating beasts. Everybody is desperately looking for reasonably decent Angular/React/Vue developers. We layered a ton of complexity on top of the frustratingly complex web platform, we created a plethora of dialects of doing things on the web, segmenting the already insufficient developer base into several buckets.
Ultimately it would be nice to have good developers instead of pampering bad developers into barely getting the job done. We don’t exactly simplify the quest of becoming good at web development by segmenting the domain.
The Art of Programming
The art of programming lies in a couple of domains: split a complex problem into a couple of simple solutions. Make these solutions reusable. Make them elegant and efficient. Mixing template and code (I get tired of (decl. & imp. 🙂 ) falls short in a few of these points.
It is very hard to write efficient code, if you don’t know, what exactly it is you are telling the browser to do. As I pointed out above, it is nigh impossible to figure that out, if you use some such virtual DOM framework, that takes a dynamic template to render your view. When you thus step into a performance trap, that is very hard to spot, because all the performance is lost in the framework and not your code, where it would be trivial to find with a profiler. Reusing templates is also hardly possible, when you mix it with your code, and re-using code is equally hard vice versa for the same reasons.
Of the list I put up as my ad hoc definition of the art of programming, that leaves you to split your problem into a somewhat redundant set of simple and elegant solutions, re-usable only at the level of components – if at all. Reusability and efficiency suffer. Elegance is constrained to a very limited subset of the possible beauty. What looks simple and elegant in small demos leads to cruft and inefficiency in big projects, because optimization is hard when you don’t know what’s happening and each component has a hard time sharing with others.
What puts me off most, though, is that I do not really understand, what I’m doing, when I’m using such systems. It appears simple and intuitive, when you look at it, and the mapping from dynamic template to result is indeed pretty simple and intuitive. But knowing what goes on between is all but.
I encountered several occasions, where I needed to optimize something, and each time that was the point, where I had to leave the framework behind and resort to “the old way” of doing things. So if I have to know the standard way anyway in order to do my job, why use the other way in the first place? Because I can do more with less effort? I though that. But I found to my surprise that I was wrong.
The Platform to the Rescue!
I implemented a smallish (1.5K lines of code) private project and wanted to see how far I get with just using platform technology. I didn’t get that far and tried the least invasive thing I could think of, a small templating library (lit-html). When I was finished I was happy, but not completely. The performance was less than I hoped and I didn’t like lit-html imposing its custom syntax of mixing code and template. So I started my own drop in stuff, and since I had that nagging doubt of dynamic templates and was too lazy to tackle that kind of problem, I separated the worlds.
A mere 200 lines of imperatives later, I had all I needed to get me going. Performance went up considerably and footprint went down to unprecedented levels. My whole app had some 50k, or so including (SVG) graphics. And I even needed a tiny little bit less code in my app instead of more as I had expected. I then refactored the library code to be truly uniform and reusable. On that I wrote a performance demo (dbmonster) that ranks among the top of all such demos (there are plenty of those, including all major frameworks … which are all 30% behind the top). And that at a below 10K footprint, a 100 lines of code plus templates. If you care, have a look at the project: https://github.com/schrotie/shadow-query
The point here is not that tiny library, though. The point is: in order to write platform only apps now, that have great structure, well readable code, and outstanding performance, you don’t need frameworks. You just need a tiny set of helpers – no good standard is emerging, yet, for this. You may want to free yourself of the idea of dynamic templates, though. And you better know what you’re doing 🙂