Front-end Frameworks: Solutions or Bloated Problems?

Modern front-end frameworks require you to download a development environment, complete with dependencies, and compile your code before even trying to view it on your browser. Is this a good thing? Is the problem that we are building more complex sites, or is it that the frameworks are complex in their own right, introducing an unnecessary level of complexity?Are front-end frameworks a quick solution or a bloated problem Web development today has evolved a lot since the ’90s; we are able to create entire experiences that are very near what any native application can do, and the development process has also changed. Gone are the days when being a front-end web developer was a matter of opening Notepad, typing a few lines of code, checking it on the browser, and uploading it to an FTP folder.

The Front-end Web Development of the Past

I must start by stating the obvious: The world isn’t like it was 10 years ago. (Shocking, I know.) The only thing that remains constant is change. Back in the day, we had very few browsers, but there were a lot of compatibility issues. Today, you don’t see things like “best viewed on Chrome 43.4.1” much, but back then, it was pretty common. We have more browsers now, but fewer compatibility issues. Why? Because of jQuery. jQuery satisfied the need to have a standard, common library that allowed you to write JavaScript code that manipulates the DOM without needing to worry about how it was going to run on each browser and on each version of each browser—a true nightmare in the 2000s.

Modern browsers can manipulate the DOM as a standard, so the need for such a library has diminished greatly in recent years. jQuery isn’t needed anymore, but we can still find a number of extremely useful plugins that depend on it. In other words, web frameworks may not be necessary, but they are still useful enough to be popular and widely used. This is a trait common to most of the popular web frameworks out there, from React, Angular, Vue, and Ember to style and formatting models like Bootstrap.

Why People Use Frameworks

In web development as in life, having a quick solution is always handy. Have you ever done a router before in JavaScript? Why go through the painful process of learning when you can npm-install a front-end framework to overcome the issue? Time is a luxury when the client wants things done yesterday or you inherit code from another developer designed for a particular framework, or if you are integrating with a team already using a given framework. Let’s face it—frameworks do exist for a reason. If there were no benefits to them, nobody would be using them.

So what are some of the benefits and unique properties of using a web development framework?

Time is money. When you are developing a project and the client doesn’t care which framework you use—indeed, probably isn’t even aware of what you use—they only care about getting results, and the faster the better. Established frameworks let you create an instant sense of progress from the beginning, which the client craves from day 1. Additionally, the faster you develop, the more money you make, since the time freed up by the framework can be redirected to taking on more projects.

It’s all about the community. When choosing a framework, this is a very important point—who is going to help you when you get stuck on an issue? You and I both know that it’s going to happen at some point. You’ll reach a spot where you need to do something that the framework wasn’t intended to do, or that the framework was never designed to give you access to, so having a community supporting you is essential. Development—especially freelance—can be hard, as you are immersed in a virtual world, and if you’re the sole front-end web developer in a team, it means you’re the only one with the experience and expertise to find a solution. But if the front-end framework you use has solid support, there is going to be someone on the other side of the world who has faced the same problem and might be able to help you.

Standards are beautiful. Have you ever noticed that, when you look into an old piece of your own code, you can navigate through it pretty easily? Or at least, more easily than a piece of code written by someone else? You think in a certain way, and you have your own way of naming things and organizing the code. That’s a standard. We all follow them, even if they’re only for ourselves. We tend to eat similar things for breakfast, wake up at a certain hour, and place our keys in the same place every day. And indeed, if we changed up our routines every day, life would be a lot harder just from the overhead of figuring out how to do stuff. Ever lost your keys because you put them in a different place than normal? Standards make life easier. When working as part of a team or a community of developers, they become absolutely indispensible.

Frameworks provide a standard from the moment you install them, guiding you to think and to code in a specific way. You don’t need to spend time creating a standard with your team; you can just follow how things are done in the framework. This makes it easier to work tgether. It’s easier to look for a function when you know that the function must be in a certain file because it is built for adding a route in an SPA, and in your framework, all routes are placed in a file with that name. People with different skill levels can work together if you have this level of standardization, because while the advanced coders know why things are done that way, even junior developers can follow the standard itself.

When Frameworks Fail

A few years ago, saying something like “I don’t use frameworks—I don’t see any real benefit from them” would bring people with torches and pitchforks to your door. But today, more and more people are asking themselves, “Why should I use a framework at all? Do I really need them? Is it that hard to code without them?”

I’m certainly one of them—I’ve never been a fan of any specific framework, and I’ve been coding without them for my entire career. If I have a choice in the matter, my choice is always, “No, thanks.” I’ve been developing in JavaScript for years and in ActionScript before that. I was coding in Flash when most people already considered it dead. (I know, I know… but I was doing lots of animations, and animation in plain HTML is hard.) So if you’re one of the many who never think about coding without frameworks, let me show you some reasons why you might be struggling.

“One size fits all” is a lie. Could you imagine writing a single piece of software that can do everything you’ve accomplished in your career? That’s one of the main problems with web development frameworks. Your project has very specific needs, which we tend to solve by adding libraries, plugins, or add-ons to extend the framework’s scope. No framework offers 100% of what you need, and no framework is 100% composed of things that you’re going to find useful.

Having too much code that you don’t use can result in load time lag for your site, which becomes more important with each additional user. Another issue is that the “one size fits all” mindset results in inefficient code. Take, for example, $(‘sku-product').html('SKU 909090');, which is jQuery code that, in the end, we all know is going to be translated into something like document.getElementById('sku-product').innerHTML = 'SKU 909090';.

That kind of difference on a single line might seem unimportant, but changing the content of a specific element of the page is precisely the virtue of React. Now, React goes through the process of creating a representation of the DOM and analyzing the differences in what you try to render. Wouldn’t it be easier to just target the content that you want to change from the beginning?

That tangle of weeds you’re walking through is growing thorns. Have you ever been in the situation where you’re using your framework and trying to add a library to it, just to realize that the library version you need doesn’t work well with the framework version that you’re using? Sometimes it takes more effort to make two pieces of code work together than it does to just write the code yourself. And since the frameworks and libraries that you use are often built on other frameworks and libraries that can have hidden incompatibilities that you can’t even anticipate, the problem can grow exponentially more complex, reaching a point where they’re impossible to manage if you want the project to keep growing.

Keeping up with the Joneses is a thing. Ever worked on a project in AngularJS only to find out that you need something that didn’t appear until Angular 4 was released? Did you even know that Angular 5 has been released? This is another huge issue; even if you’re sticking to a single front-end framework, when a new major release happens, things can change so much that the code you worked so hard to make won’t even run on the new version. This could result in anything from annoying little changes that need to be made on a lot of files to a complete rewrite of your code.

Keeping up with the latest builds of a framework is challenging, but on the same note, other frameworks suffer when updates stop completely and they can’t keep up with the rest of technology. In 2010, both AngularJS and Backbone were released for the first time. Today, Angular is on its fifth major version, and Backbone is completely out of the spotlight. Seven years seems like a long time. If you build websites, they’ve probably changed completely in aesthetic and function. If you’re building an app, betting on the wrong framework might put the company in a tough—and expensive—situation later, when things need to be rewritten.

When all you’ve got is a hammer, everything looks like a nail. If you’ve used web development frameworks frequently, this has probably happened to you, where a single codebase defines the shape of the code you use in the future, even if it’s only peripherally related. Let’s say you’re going to build a platform like YouTube and you want to use Framework X. There might be a point where, even if it sounds ridiculous in this day and age, you decide to use Flash for the videos because that’s what comes built in with the framework.

Frameworks have opinions, and they are strong; React, for example, forces you to use JSX in a specific way. You can see code being used in that way everywhere. Is there an alternative? Yes. But who uses it? This isn’t always a bad thing, but if you need to perform complex animations, you might only need a framework for animating and not the entirety of React. I’ve seen people do crazy things like add jQuery to a page just to append a node to an element, something that could be accomplished in vanilla JS with document.getElementById('id_of_node').appendChild(node);.

Eval Is Evil, but .innerHTML Is Machiavellian

I want to take the time to explore this point separately because I think this is one of the reasons more people don’t code without frameworks. When you see how most code works when trying to add something to the DOM, you’ll find a bunch of HTML injected by the .innerHTML property. We all seem to agree that eval is bad for running JavaScript code, but I want to put .innerHTML in the spotlight here. When you inject HTML code as a plain string, you lose any reference you might have had to any of the nodes you created. It’s true that you might get them back by using getElementsByClassName or assigning them an id, but this is less than practical. When trying to change the value of one of the nodes, you’ll find yourself rendering the entire HTML back again.

This is good when you start coding. You can make lots of simple things easily without much experience. The problem happens with the complexity of modern websites, which tend to be more like apps—this means that we need to constantly change the values of our nodes, which is a high-cost operation if you’re doing it by reattaching the entire structure via .innerHTML. React solves this problem efficiently via a shadow DOM, and Angular addresses it by using binding as an easy way to modify a value shown on a page. However, it can also be solved fairly easily by keeping track of the nodes you create and saving the ones that will be reused or updated in variables. There are also other reasons to stay away from .innerHTML in general.

The Biggest Myths about Coding Without Frameworks

Time is money. Yep, I’m bringing this concept back from earlier. Many people feel like if they stop using a popular web framework, we will instantly devolve to the internet of the 90s, when <marquee> was everyone’s favorite tag, rotating GIFs on a Geocities site were hip and edgy, Alta Vista was the go-to for web searches, and hit counters were ubiquitous.

With web frameworks, your first lines of code seem to make a lot of time-saving progress, but at some point, the gains turn to losses. You spend your time reading about how to make the framework do things it isn’t built for, how to integrate libraries and make them play nice with the framework, and finding out that the code you built while following the framework’s standards isn’t going to work at all and now you need to rewrite it. When you do things without a framework, you start slower, but you make steady progress. In the end, it’s all about where you want the easy part to be. It won’t make much difference in total time.

My code will be longer than the Great Wall. Writing without a framework is like buying a movie instead of subscribing to a streaming service. You don’t get instant access to hundreds of movies that you want to watch, but you also don’t have to spend money on thousands of other movies you’d never even consider downloading from the store. You can just write what you need.

Is the middleman useful? Sure. But it’s not usually necessary. Every line of code you write has more meaning, as there’s no need for you to adapt to the requirements of a framework. It can feel like you are writing more code with pure JavaScript because the way to create the DOM elements takes lines to create an element, attach it to the DOM, and perhaps add a class for styling, as opposed to calling up a single line of code in JSX. But if you compare code using a library like jQuery or React, vanilla JS can be pretty similar in length. Sometimes it’s longer, but sometimes it’s shorter, too.

There’s no need to reinvent the wheel. The mantra of computer science professors everywhere. And it’s true—it just doesn’t have to mean frameworks specifically. Sending an Ajax request to load or save data is a requirement in almost every web app, for example, but not having a framework doesn’t mean that you need to write the code anew every time. You can create your own library or codebase, or you can extract code from others. The smaller it is, the easier it is to modify or adjust as needed, so it comes in handy when you need something specific for a project. It’s easier to modify 100-200 lines of code than navigate through the mountain of files that a third-party library or framework might contain.

It will only work for small project. This is a very common myth, but not true at all; currently, I am working on an entire system to manage all aspects of a company online in a single place, including a module that is something like Google Drive. Whether with frameworks or without them, I go through very similar steps and encounter very similar problems. The difference is negligible. However, without frameworks, my entire code is smaller and more easily manageable.

I WANT PROOF

Okay. Let’s stop talking about theory and jump to a real-world example. Some days ago, I needed to show a list of brands with logos for a store. The initial code used jQuery, but it had a problem where, when loading in Mozilla, it was showing a broken image icon for brands that didn’t have logos uploaded yet. We can’t have the store looking unfinished just because Company X hasn’t finished their end of the work yet, but the feature needed to go live.

The following code uses the jQuery equivalent of .innerHTML:

var list_brand_names = ['amazon', 'apple', 'nokia'];
var img_out = '';
for (i=0;i<list_brand_names.length;i++) {
   var brandName = list_brand_names[i].toLowerCase();
  img_out += "<a href='/pages/" + brandName + "'><img src='images/" + brandName + "' /></a>";
}
jQuery("#brand-images").html(img_out);

Without going too deep into the pros and cons of jQuery, the problem here is that we don’t have any reference to the images we created. While there are solutions that don’t involve changing code, let’s use this opportunity to see how it can be done without any library at all:

var brands = ['amazon', 'apple', 'nokia'];
var brand_images = document.getElementById("brand-images");
for (var iBrand = 0; iBrand < brands.length; iBrand++) {
  var link = document.createElement('a');
  link.setAttribute('href', '/pages/' + brands[iBrand]);
  link.style.display = 'none';
  brand_images.appendChild(link);

  var image = new Image();
  image.src = "images/" + brands[iBrand] + "png";
  image.onload = function(){
    this.parentNode.style.display = '';
  }
  link.appendChild(image);
}

The original jQuery code was six lines long, while the vanilla JS solution took twelve. To solve the problem, hiding each image until it’s been loaded, takes twice as long to code. So let’s look at the alternative. Can it be solved in jQuery too? Check it out:

img_out += "<a href='/pages/" + brandName + "' style="display:none"><img src='images/" + brandName + "' onload="showImage(this)"/></a>";
function showImage(image){
  image.parentNode.style.display = "";
}

With a couple additional lines of code, there is now only a three-line difference between the jQuery and the vanilla, but on the jQuery, you can see that the img_out line is quickly growing very complex, to the point where you need to pause and think carefully about what you’re doing. Coding the DOM directly by using node functions to add attributes, functions, and the like might be more lengthy, but each line has a clearer, more precise meaning, making it easier to read and maintain in the future.

Let’s take a look at React:

function BrandLink(props) {
  var url = "images/" + props.brand + ".png";
  return (<a href="{props.brand}"><img src={url}/></a>);
}
class Brands extends React.Component {
  constructor() {
	super();
	this.state = {brands: ['amazon', 'apple', 'nokia']};
  }
  render() {
	const links = this.state.brands.map((step, move) => {
  	return (<BrandLink brand={step} key={step}/>);
	});
	return (<div className="brands">{links}</div>);
  }
}
ReactDOM.render(<Brands />, document.getElementById("root"));

This version is clearly sub-optimal. The code is no shorter than it is in vanilla, and we still haven’t even gotten to the point of solving the problem and hiding the links until the image inside them has loaded.

For every example, the results are going to be different. Sometimes, jQuery will be shorter. Sometimes, React will win. There are times when vanilla JS can be shorter than both of them. In any case, the goal here wasn’t to prove that one was inherently superior to the other, but to demonstrate that there isn’t a significant difference between using vanilla JS and using a framework when it comes to code length.

Conclusion

As with just about any real-life issue, nothing is black or white. Coding without web development frameworks might be the best solution for some of your projects and a nightmare in others. Just as with every tool, the key is in learning not just how to use it, but when, and what the advantages and disadvantages to using it might be. Coding in pure JavaScript is just like with any framework—mastering it takes time before you feel comfortable using it.

But the key difference, at least for me, is that frameworks come and go, and even if a framework is popular for a long time, it can change dramatically from one version to another. Pure JavaScript will be an option for much longer, until it stops being relevant entirely and some other language emerges. Even then, there will be more concepts and strategies that you can migrate directly from one language to another than you can with a given framework to another. Time and effort being roughly equivalent where a single project is concerned, the reduction in knowledge depreciation and the lessons you can take with you to the next challenge are very important factors to consider.

This post was written by Juan Carlos Arias Ambriz, JavaScript Developer for Toptal.