Modern Front-End Frameworks should be less of a “frame” and more of a “work”

Disclosure: I am the author of slim.js — a web component standards based library for building components and applications based on these standards and APIs, so I may get a bit evangelistic here.

Credit: Pixabay.com

TL;DR #1

Most popular frameworks deal with browser gaps (rendering stuff and handling UI). Because of this we are doomed to endlessly port UI components from framework X to framework Y (fancy-calendar -> ng-fancy-calendar -> ng2-fancy-calendar -> react-fancy-calendar)…

A long time ago in a galaxy far, far away… there were Java, Flex & Silverlight

We created (what used to be called) “Rich Internet Applications” and “publish” them in the web and consume them with browsers. These technologies gave us the classic Model-View-View-Model and Model-View-Controller patterns which every desktop applications developer had (i.e. Windows API) — into the web. You could have buttons and drop-downs and titles and menus and images. And it was cross-compatible and looked the same on every computer.

To my perspective, the biggest difference from HTML & javascript is that everything was (or had) a class. A button was a class. The drop-down was a class — even layouts and grids were classes. And there was black magic (a framework) running behind all this which knew how to render this into graphical user interface.

Imagine a world where you could:

  • Declare how your display list is being built using XML (or XML-like) structure: with parents, nodes and attributes.
  • Write implementations (“code-behind”) for containers which encapsulates ready-made elements (i.e. buttons, labels) and apply business logic of how they behave and deal with incoming data and even user behavior!
  • Extend existing components or write your own custom components from scratch.
  • Seep and stream data “down” your display tree.
  • Capture streaming events going “up” on your display tree.
  • Write code which is pure business logic and had no visual footprint on the application. Things like services, models…

Wait! Aren’t we already doing this?

A modern web developer today is already familiar with all these techniques, as these exist in popular frameworks like ReactJS (+ it’s ecosystem) or Angular. The modern developer also understands WHY these frameworks exist: browsers are incapable of doing it by themselves. Well, they’re capable of doing some of this magic, but not with “structure”.

Before Angular (1.x) came along we did some hacks and jQuery tricks (and used big UI libraries) in attempts to bring the experience every .NET, Java or Flex developer had into the world of HTML. Enterprise-class applications were built with these tools and there wasn’t much of a demand for doing it using HTML and javascript.

Smartphones stormed us: Java/Flash/Silverlight died and suddenly… there was a void.

Though solutions like GWT and Dart attempted to bring “the developer experience” into the crippled chaos of browserland, they were not accepted by the community. Within one year all websites looked the same and everybody hated Java and Flash and said it is bad technology and it is full of security breaches and memory leaks and it is the Satan.

Luckily, us developers, had the community to the rescue. It provided awesome tools like grunt and gulp to bundle up you project and great styling tools like sass and fantastic libraries like Angular (and backbone and bower and browserify and I can’t mention it all). And the web developers were happy again. So much has happened in just few years.


The web components standard

Quickly we (almost completely) forgot how to do simple things. We now easily deliver a 250 kilobytes “Hello world” app. We structure model, data stores, services and multiple views for a simple registration form. We are now riding dragons like bosses.

Meanwhile, big things happened with browsers. They matured.

TL;DR #2

Since most of frameworks must deal with rendering and handling the UI as well as providing stuff like patterns and structure, they provide different implementations and approaches. Because of that we are doomed to endlessly port UI components from framework X to framework Y all the time. Everyone that have used some fancy calendar built with jQuery and had to search within millions of ports like mentioned above “ng2-fancy-calendar”… You know what I’m getting at. Every badge and every drop-down needs to be rebuilt ten times so it can work in ten different frameworks and components which aren’t interopable.

Big companies invest tons of money and man hours to integrate a framework into their products. Porting is expensive.

Those companies, then, spend a lot of time and money porting components and building whole UI libraries which works with their selected framework. So they start working, and when they are about 75% there, a new framework suddenly arise. Now the dev team wants to migrate and the company has to choose between migrating all their work and rebuilding everything again (and make dev team happy) or lose their developers to the trends. This is a big problem which costs big money. As a software consultant (at Tikal knowledge) I have many times seen companies get stuck with two years “old” frameworks and cannot hire developers — nobody wants to work with it anymore. Two years old! It is a serious problem for software companies as it is also a problem for us developers. Do we really want our job to be focused on rebuilding everything over and over again for different stacks? We need to stop being imprisoned by libraries and tools! But how?

Go vanilla?

I’m not going to preach for vanilla. There is a reason and a place for frameworks and big organizations need frameworks and developers need frameworks. But here’s a fun fact: today, all evergreen browsers provides most of what frameworks are doing.

It is about time that frameworks would provide a frame to work with and stop making us work for the frame. The next generations of frameworks should focus on something else.

I would like to bluntly make a rough comparison:

  • webpack “require/import” vs. HTML Imports!
  • React.Component / Angular Directive vs. Custom Elements!
  • CSS Modules vs. Shadow DOM!
  • Bundling vs. HTTP/2!

We have all the alternatives in the “bare metal” of browsers and severs: everything that needed a work-around became a standard. All the libraries can stop doing this for us. Thank you for what you did, we appreciate it, now is the time for us to move on.

I’m not saying we should throw away webpack — I’m just saying that we should use it as a tool and not as a solution for technology gaps. We may consider rethinking how we use React/Vue: Custom elements provides what is known as “state and props”. Custom elements also triggers events, like any other DOM element and they can encapsulate styles using Shadow DOM. Custom elements are first class citizens in the browser and they are a standard, meaning they are going to be here for a very long time. The browser should handle all the rendering stuff so we may question the need for a virtual DOM. Do we really need this overhead when we can do things natively, without extra effort? Do I need to mention the overall cost of CDNs, battery usage, CPU exhaust?

What does all this mean? It means that the next generations of frameworks should focus on patterns and practices and how applications are to be designed. The companies that are behind the frameworks should leave the rendering stuff and performance tweaks for browser vendors. We (developers) should choose what is good for us in terms of productivity, testability and code maintenance and not what is trendy.

By sticking to “use the platform” approach and use native APIs, it will do good for us all in the long run.

For developers it means working with the latest and greatest and for frameworks it means lasting longer and being productive and hell, stop focusing on filling holes in platforms. Then we will have the time to build instead of re-build.

Resources to read: