You don’t need a framework. You need a painting, not a frame.
—Klaus Kinski
So, why should you read a book about effectively developing front-end applications without frameworks? Because, sometimes, a framework is just not enough to fulfill your tasks. This book helps you understand the strategies for developing frameworkless applications, and more importantly, it shows you how to choose the right tool for the right job.
This chapter begins with my opinions on frameworks and why I believe that it’s important to learn to live without them. After this short introduction, you start learning how to work without frameworks. I show you examples of rendering, routing, state management, and so on. After you learn how to go frameworkless, you should be able to figure out if it is the right choice for your project.
The last chapter in this book helps you decide which tool is best for you. I also talk about technical decision making and how to evaluate the trade-offs in every decision.
Now that you have an idea of what you can expect from this book, let’s talk about frameworks.
What Is a Framework?
A supporting structure around which something can be built.
This definition is consistent with the general idea of a software framework. If you think about the structure of an Angular application, it matches this definition exactly. Angular offers this structure with out-of-the-box elements like services, components, and pipe, around which you build your application.
In real-life applications, a stack contains other elements. You can use Lodash to manipulate arrays or objects, or Moment.js to parse dates.
Are these framework tools? The JavaScript community tends to call them libraries.
A framework calls your code. Your code calls a library.
Comparing Frameworks to Libraries
I am going to use some code snippets to show the difference between frameworks and libraries. For this comparison, I will use Angular and Moment.js.
Angular Service Example
Angular Component Example
Moment.js Example
Given the previous definition, it’s quite easy to understand that Angular is a framework, while Moment.js is a library (used to manipulate dates). In Angular, to let PeopleListComponent interact with PeopleService, you should use the @Injectable annotation and put the instance in the constructor. Angular offers a structure to fill with your code and a set of utilities (like HttpClient) to help with standard tasks.
Some JavaScript Libraries
Purpose | Libraries |
---|---|
Utilities | Lodash, Underscore.js |
Date manipulation | Moment.js, date-fns |
Data visualization | D3.js, Highcharts |
Animations | Tween.js, Anime.js |
HTTP requests | axios |
I deliberately left out React—one of the most popular tools front-end developers—from this list. So, is React a library or a framework? Before answering this question, I want to introduce a new concept that will help shed some light on this topic: the framework’s way.
The Framework’s Way
As you saw in Listing 1-3, Moment.js has no opinion on how to integrate it into your code. Angular is very opinionated. You may see some of its strong ideas in the simple example shown in the previous section. The following sections discuss some of the constraints.
Language
Even if it is actually doable to build an Angular application with plain ECMAScript, TypeScript is the de facto standard in the Angular ecosystem. TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Apart from type checking, it lets you use features that are not present in the original language, such as annotations.
TypeScript could be very useful if you are used to working with strongly typed languages. But if you use Angular, all of your code is written in a language that requires a transpiler.
Dependency Injection
AngularJS Dependency Injection
Later in the book , you will see how to create a very simple service locator to keep your code well organized.
Observables
Angular is heavily designed around RxJS, a library for reactive programming using observables. To get data from PeopleListService, you have to use the subscribe method of the Observable object. This approach is different from the other front-end frameworks, where HTTP requests are designed like promises. Promises are a standard way to represent the eventual completion (or failure) of an asynchronous operation. RxJS lets you easily transform an observable into a promise, and vice versa.
Angular Service Without Observables
Angular Component Without Observables
Note
PeopleListComponent is a class that uses the people service. It has no particular usefulness apart from showing you how to work with promises. I use to call all the constraints of a framework “the framework’s way.”
Apart from the constraints created by the core team of the framework, other constraints are part of the framework’s way. For example, the de facto standards from the community are almost as important as the core ones. In the AngularJS ecosystem, John Papa’s style guide ( https://github.com/johnpapa/angular-styleguide/tree/master/a1 ) was “the way” to write AngularJS applications. You were not enforced to use it, but most of the code that you read on the web was built that way.
Keep in mind that these constraints are neither bad nor good, but it’s very important to analyze “the way” of the framework that a team chooses in order to assess if it’s the right tool for the project.
Let’s Talk About React
How is the framework’s way related to knowing if React is a library or a framework? React is defined on its web site as “a JavaScript library for building user interfaces.”
React-Pose Animation Example
As you can see in Figure 1-2, you don’t directly animate the square. You just declare how to map the state with the animation (visible or hidden), and then change the state. This is the core of the declarative pattern used in React.
React Animation with Web Animations API
If you’re a React developer, this second example may seem out of place. This is because you’re moving the square with an imperative pattern. This “strangeness” is why I believe that React is a framework and not just a library. I believe this not because of its code, but because of the constraints that the community accepted by using it. In other words, the declarative pattern is a part of React’s way.
Tip
Where there is a “framework’s way” of doing things, there is a framework.
Brief History of JavaScript Frameworks
This section is a very brief history of front-end frameworks. It’s not meant to be comprehensive, but it’s an opinionated view of the most important milestones in the front-end ecosystem.
jQuery
Created by John Resig in 2006, jQuery is the mother of all JavaScript frameworks. By far, it is the most-used framework in production, as you can see at http://libscore.com/#libs . The most important feature of jQuery is its famous selector syntax: var element = $('.my-class').
It may seem useless today but you have to consider that in 2006, browsers were not aligned as they are today. This is the real value that jQuery brought to the front-end world. jQuery created a lingua franca between the browsers. It helped the community to grow around a common ground. In addition to the selector syntax, a lot of features were added to the core project, such as AJAX requests, animations, and other utilities. It rapidly became the Swiss Army knife of front-end development.
jQuery has an official UIKit called jQueryUI, which is easily pluggable, and so the web is full of plugins for every need. Today, front-end developers tend to joke about jQuery, but it’s been a cornerstone of modern web development.
AngularJS
If jQuery can be seen as the invention of writing, AngularJS is probably the equivalent of Gutenberg’s printing press. AngularJS was originally developed in 2009 by Miško Hevery as a side project; later, he became a Google employee. For this reason, AngularJS is actually maintained by Google engineers. The 1.0 version was released in May 2011. AngularJS was hugely successful in making single-page applications a mainstream pattern.
AngularJS Two-Way Data Binding Example
Two-way data binding lets developers quickly create web applications. Over time, however, a lot of developers left AngularJS because two-way data binding is not suitable for large applications. In any case, AngularJS has the merit of introducing a lot of developers to the front-end ecosystem.
React
Basic React Component with Some Lifecycle Methods
React works with a declarative paradigm. Usually, you don’t modify the DOM directly; instead, you change the state with the setState method and let React do the rest.
Technically, React is a rendering library and not a framework. This fact allows the front-end community to fill in the gaps with a lot of very interesting ideas, especially for state management. I talk about some of these libraries, including Redux and MobX, in Chapter 7.
Angular
Angular was previously known as Angular2 because the project was intended to be a new version of AngularJS. The team behind the project took the semantic versioning very seriously, thus Angular2 became a completely different framework. Such a different approach between the two versions caused a period of panic around the project. After the first release of Angular2 in September 2016, the team decided to rename the project Angular, probably due to a planned release cycle featuring a new major version every six months.
Angular tried to appeal to the corporate world. A lot of corporations developed single-page applications with AngularJS, but the tool was not designed for very large applications. The fact that TypeScript is the de facto standard for working with Angular helped a lot of Java and C# developers start developing front-end applications.
Technical Debt
When you need to add a feature to a project, you always have a range of options. Some of them are quick and messy, while others are well designed but slower to put in production. In order to better understand the impact of this kind of decision, Ward Cunningham created the concept of technical debt ( http://wiki.c2.com/?WardExplainsDebtMetaphor ). The metaphor itself is quite simple: every time that you choose the dirty solution, you incur a debt.
The Cost of Frameworks
Why did I dedicate a section to technical debt? Because I firmly think that every framework has technical debt. I know that this is a very strong statement, but let’s think again about the debt metaphor. You start incurring debt when you choose a path that is not optimal in order to gain something else, usually velocity. My point is that someone else’s code is not optimal for solving my exact problem. Of course, I’m talking about an ideal world where in every new project, a team has the time to build everything from scratch. I would be naive to think that I will work with plain JavaScript in every project. But I would be equally naive to think that frameworks are free of charge. Every framework has a cost in terms of the difficulty to change the code in the future. The cost is the fact that a framework imposes its architecture on your code. Over time, software needs change, because of the market or other factors, and our architecture should change too. But most of the time, a framework is a roadblock in this sort of change.
Technical Investment
At the beginning of this chapter, I stated that this book is not against frameworks. This statement seems in contrast with the idea that every framework has technical debt. You are probably wondering how frameworks can be a good thing if they always have technical debt. Technical debt is not always a bad thing. In the financial world, debt is not automatically a bad thing. For example, to buy a house, you usually need a loan, which is debt. But people tend to not consider a loan a bad thing, but an investment. On the other hand, if a friend without a stable job wants to go to a bank to get a loan to buy a Ferrari, you will probably try to stop him. The difference is not in the debt itself but in the reason behind the debt.
In software development, there is the same kind of mechanism. If we use a quick solution for a good reason, it is not technical debt, it is a technical investment. An investment is a type of debt, but it is not reckless. And a framework, when chosen for a good reason, is not a cost but an asset. In Chapter 8, I will show you some of the techniques that I use as a consultant to understand if a framework is an asset for a project, and how to choose the framework that “costs” less.
Summary
This chapter defined a “framework” and explained how it is different from a library. I discussed my personal history of JavaScript frameworks, and I pointed out values to the front-end ecosystem. Lastly, you learned the meaning of technical debt and its relationship with frameworks.
In the next chapter, I talk about rendering and the basic principles behind DOM manipulation.