DEV Community

seanbh
seanbh

Posted on • Originally published at Medium on

Do We Still Need Frontend Frameworks in 2024?


Photo by Jon Tyson on Unsplash

I recently encountered an argument that new web development should not utilize a frontend framework (Angular, React, Vue, etc.) due to the maintenance burden of keeping up with new versions of dependencies. The argument is that this maintenance burden is not justified because most applications just don’t need frontend frameworks anymore.

Is this true? Let’s examine this claim in the context of a typical development shop in a med/large size company, which is responsible for many applications — both enterprise and consumer facing. I’ll be using Angular as my framework example.

Frameworks were Never Required

The crux of the argument is that because of advancements in JavaScript, CSS and browser features, frameworks are no longer required. But I think this overstates the case somewhat. Frameworks were never required to do anything. Frontend frameworks ship JavaScript (with HTML embedded within the JavaScript) and CSS. So, frameworks never did anything that couldn’t be done with JavaScript/CSS alone. They just made it much easier to do those things and as a result much faster.

It’s very similar to the .NET framework. When .NET was released, there was nothing that it could do that could not be done with C/C++. The .NET framework just made it a lot easier, and therefore faster to do Windows development. I can remember some pushback when .NET came out from C/C++ developers who argued that you should just bite the bullet and learn C/C++. I remember at first feeling somewhat inferior to those developers since I was using a framework whose stated purpose was to make things easier and that felt like “cheating”.

But businesses want results fast. As a result, a framework that makes development much easier and faster is going to catch on and that is what happened with .NET. It was hard to justify investing the time to learn and develop with C/C++ when .NET was so much easier and was what companies were looking for.

I think the situation was (and still is) similar with frontend JavaScript frameworks. Sure, you can do everything with just plain JavaScript/CSS/HTML, but when there are alternatives available that are easier to learn and implement and that allow you to deliver solutions much faster it’s hard not to pursue that path — at least for companies that must deliver many applications with limited resources.

Framework features

It is true that there have been advancements in JavaScript and browser features and many of those have been driven by frontend frameworks. ES6 support for classes and modules gives us a way to structure our code in plain JavaScript. The ability to create custom elements that encapsulate functionality and communicate via custom events enables us to create reusable components. These advancements make it easier to develop using vanilla JavaScript than it used to be.

But I’m not convinced that we are in a place where vanilla JavaScript has parity with frontend frameworks when it comes to building complex web applications quickly.

For example, let’s look at the custom element example of a counter component. A counter component is one of the simplest reactive components you can implement and is often used for demonstration purposes. On the left is the implementation of a counter component as a custom HTML element using only vanilla JavaScript. On the right is the same implementation using an Angular component (v17).

Comparison between custom element and an Angular component
Comparison between a custom element and an Angular component

The Angular component is implemented using fewer than half as many lines as the custom element. In addition, Angular generates the boilerplate of the component so that I only had to write the code in the red boxes. Also, with the Angular solution I have the option to move the template into its own HTML file which I much prefer. If we see this much difference in the implementation of the simplest component, what will it look like for a complex component?

Another thing to note is that Angular sanitizes values before injecting them into the DOM to guard against XSS vulnerabilities. That’s not necessary for this component, but it is for many other components, and this is an example of functionality that teams would have to implement for themselves in a reusable way.

Furthermore, JavaScript is not a type-safe language — i.e., type errors are not discovered until runtime, and you get little to no useful intellisense. Whether or not type checking is important is a separate topic, but many believe that it is and that is why Angular uses TypeScript in order to have compile time type checking and provide robust intellisense. Of course, you can use TypeScript without using a frontend framework, but you would have to take care of the transpilation yourself.

Finally, frameworks like Angular provide more than just an easier way to create custom components. They also provide services and other functionality. To give just one example, in Angular it is easy to create an interceptor that you can use to modify all HTTP requests. Such an interceptor is useful for doing things like adding an authentication header value for API calls. Let’s look at how we might implement something like this ourselves in the next section.

Dependencies Don’t Go Away — They Just Shift

Let’s go back to the example of an HTTP interceptor that was just mentioned in the last section. How would I accomplish this if I was just using vanilla JavaScript?

At first, I might duplicate the logic everywhere I make a request. I would quickly realize that I’m violating the DRY principle and would move this logic into a shared module and then import this module everywhere I wanted to use it. But then I would realize that I want other applications in my company to be able to use this functionality, so I would make it into a library so that all applications could use it in a versioned manner.

Then I would realize that different applications have different use cases so I would need to make the code configurable so that it would work in different scenarios. Then I would realize that it would be nice to be able to do this multiple times for the same request and so I would come up with a way to apply multiple changes to the same request and do it in the order determined by the developer.

Each time I make changes to the library I must be aware of the different ways in which the library is being used and take care not to break existing implementations. If the native webRequest browser API changes in some fundamental way or is superseded by something else, I will want to take advantage of those changes in the library. Indeed, I may be forced to make those changes and make them quickly if something changes that affects browser support — i.e., if browser updates are going to cause my solution not to work anymore.

But I may not be able to do that in a 100% backwards compatible way. So, in that case I will have to retain the backwards compatible implementation while also implementing a new solution and figure out a way to migrate the consumers of my library. All of this takes place without any third-party dependencies. But now the applications in my organization have a dependency on this library which I must maintain myself. Obviously, this is only one example of shared functionality and there would of course be many others.

Embracing Open Standards is Good

But I do take the point that if we are able to do something that is natively supported, we should try and do it natively. I believe Angular agrees with this and they regularly drop their custom implementations as JavaScript, CSS and browsers evolve.

For example, they deprecated their custom flex box solution in favor of using plain CSS once the custom solution was no longer needed. They have also introduced a way to configure the HttpClient to use the native fetch API. Angular is also moving away from using their own modules now that modules are supported in ES6.

Conclusion

Do we use a solution that someone else has provided or do we roll our own? It’s not a new question. Generally, I think companies opt for using solutions that others have provided to speed up development and because they do not have the resources (in terms of skill or quantity or both) to implement their own solutions.

However, this does come with the trade-off that you have to keep up with the dependencies you introduce. But I think for many companies implementing enterprise applications, the balance is still in favor of using a frontend framework.

Top comments (1)

Collapse
 
f1lt3r profile image
F1LT3R