TwitterFacebookInstagramYouTubeDEV CommunityGitHub
Client-side JavaScript (JS) Frameworks - Part 1

Client-side JavaScript (JS) Frameworks - Part 1

JavaScript frameworks are an essential part of modern front-end web development, providing developers with tried and tested tools for building scalable, interactive web applications. Before we pick a framework and start learning about it, I think it's important that we first understand what a client-side JavaScript framework is, what it does and why it exists. So, that's exactly what we will be learning in this article.

In this article, we will:

  • Learn a brief history of JavaScript
  • Dig deep to understand why JavaScript was created in the first place
  • Explore main features of JavaScript frameworks

A brief history of JavaScript

Why was JavaScript needed in the first place? Good question!😉 Again, everything created was created to solve a problem. So, what problems was JavaScript created to solve?

Before JavaScript was created, web pages exist only as static documents. In the 90s, internet connectivity was very slow as we were still using dial-up connections with telephone lines and modems. Most user actions in the interface trigger an HTTP request back to a web server.

Imagine a user filling out a form on a website. The validation of the input files on any form required a full round trip to the server. The server does some processing, retrieving data to validate the form values before returning an HTML page to the client. While the server is doing its thing, the user is waiting. And at every page reload, the user waits some more. This was not only a painful exercise as the internet speed was very slow but also resulted in the loss of data if the form was not filled out correctly. It lacks the inherent responsiveness of desktop applications.

Netscape Navigator, one of the most popular web browsers in the 90s, sought out to solve this problem by finding a way to validate the input fields on the client-side without having to make a round trip to the server. This is how JavaScript was born, merely as a scripting language to validate forms on the client-side.

To make it happen, Netscape turned to Brendan Eich, a software engineer with lots of experience with developing programming languages. At around the same time, Netscape laid the groundwork for a deal with Sun Microsystems. The idea was to sign a deal with Sun Microsystems to license Java. The preliminary concept was to embed Java Virtual Machine (JVM) right in Navigator which would allow developers to build complex Java applications (later called applets) and run them on the web.

However, given the nature of the web community, which was a cobbled-together community of hobbyists and enthusiasts. Some had years of experience in the computer science field. Others had none at all. Netscape realized that what they really needed was a "companion language" because Java is a very difficult language to manage without a background in computer science. It's extremely powerful, but relies on complex principles like object-oriented programming. Therefore, any language made specifically for the web, needed to be both powerful and approachable to the average developer. Something that would allow developers to change text, move elements around, and generally experiment without errors flashing on screen every time they messed up something. A scripting language that could easily be embedded right into the HTML of a web page, that was still powerful enough to lay down a foundation for more adventurous programmers looking to build complex applications.

That's what Eich was tasked with creating, and that was exactly what he delivered. JavaScript officially made it into the first beta version of Netscape Navigator 2.0, released in September of 1995. With just a simple script tag, developers were able to create fairly complex applications.

script-tag-html

Why do we need JavaScript frameworks?

When JavaScript debuted in 1996, it revolutionized how the web is used. It's no longer just a place to read things, but to do things. Originally, web pages were simple text pages that were used to share information in the form of text; there were no videos, games, animations, etc. A number of tools were later developed in order to allow the web to be as interactive as we know it today. Dynamic HTML (DHTML) and Asynchronous JavaScript and XML (AJAX) are two examples of such tools that are worth mentioning in the context of helping us understand the need for JavaScript frameworks.

AJAX and DHTML are two technologies that are used in order to create more interactive web pages compared to the plain boring HTML pages. The main difference between DHTML and AJAX is that DHTML changes the elements on the web pages depending on user's actions while AJAX allows the browser to request certain elements one at a time in order to reduce the strain on the server and the Internet connection.

Although it's possible to implement DHTML and AJAX with plain vanilla JavaScript, it's cumbersome. Therefore, developers who worked with JavaScript wrote tools to solve problems they faced and packaged them into reusable packages called libraries, so they could share their solutions with others. This shared ecosystem of libraries eventually led to the development of several JavaScript frameworks. The development of these frameworks also redefined how the web is used. Modern, complex, interactive websites, referred to as web applications now allow users to do things that used to be possible only in native applications installed on the user's computer.

A framework is a library that offers opinions about how software gets built. These opinions allow for predictability and homogeneity in an application. Predictability allows software to scale to an enormous size and still be maintainable.

Main features of JS frameworks

Each major JS framework has a different approach to updating the DOM, handling browser events, and providing enjoyable developer experiences. Below are some of the main features shared among different JS frameworks. Each framework may have its own implementation, but at the core, they all share these common features. A good understanding of these common features at a high level is very useful when it comes to deciding which framework to use for your application. So, let's dive in.🤿

  1. Domain-specific languages (DSLs)
    All JS frameworks use DSLs in order to build applications. For example, React uses JavaScript XML (JSX), Ember uses Handlebars, and Angular uses TypeScript.

A domain-specific language is a computer language that's targeted to solve a particular kind of problem, rather than a general purpose language that's aimed at any kind of software problem.

DSLs can't be read by the browser directly; they must be transformed into JavaScript or HTML first. Framework tooling generally includes the required tools to handle this transformation, or can be adjusted to include the necessary tools. While it is possible to build framework apps without using these DSLs, embracing them will streamline the development process.

Examples of common DSLs are CSS, regular expressions, SQL, etc.

  1. Components
    Most frameworks have some kind of component model. Regardless of their opinions on how components should be written, each framework's components offer a way to describe the external properties they may need, the internal state that the component should manage, and the events a user can trigger on the component's markup.
    For example, React components can be written with JSX, Ember components with Handlebars, and Angular and Vue components with a templating syntax that lightly extends HTML.

    • Properties (props): external data that a component needs in order to render.
    • State: Similar to props, state influences the output of render. However, the main difference between props and state is that props get passed to the component (similar to a function parameter) whereas state is managed within the component (similar to variables declared within a function) and represents information about the component's current situation.
    • Events: In order to be interactive, components need ways to respond to browser events, so our applications can respond to our users. Each framework provides its own syntax for listening to browser events, which reference the names of the equivalent native browser events.
  2. Styling
    Each framework offers a way to define styles for components.

  3. Dependency Handling
    As with other features, each framework provides its own mechanism for handling dependencies - using components inside other components. Components tend to import components into other components using the standard JS module syntax or something similar.

    • Components in components:
      One key benefit of component-based UI architecture is that components can be composed together. Just like you can nest HTML tags inside each other to build a website, you can use components inside other components to build a web application.

    • Dependency injection:
      The problem of passing data through many layers of components is called prop drilling, which is not ideal for large applications. To overcome this problem, frameworks provide dependency injection - a way to get certain data directly to the components that need it, without passing it through intervening levels. Again, each framework has a slightly different implementation, but the effect is ultimately the same.

    • Lifecycle:
      In the context of a framework, a component's lifecycle is a collection of phases a component goes through from the time it is appended to the DOM and then rendered by the browser (mounting) to the time that is removed from the DOM (unmounting).

      Each framework names these lifecycles differently, and not all give developers access to the same phases. However, all frameworks follow the same general model: they allow developers to perform certain actions when the component mounts, when it renders, when it unmounts, and at many phases in between these.

  4. Rendering Elements
    Although each framework takes a slightly different approach in how components are rendered, all of them track the current rendered version of your browser's DOM, and make decisions about how the DOM should change as components in your application re-render.

    Because frameworks make these decisions for you, you typically don't interact with the DOM yourself. This abstraction away from the DOM is more complex and more memory-intensive than updating the DOM yourself, but without it, it's impossible to program in the declarative ways that frameworks provide.

  5. Routing
    To avoid a broken experience in sufficiently complex apps with lots of views, each of the frameworks provides libraries that help developers implement client-side routing in their applications.

  6. Testing
    Although testing tools are not built into the frameworks themselves, the command-line interface tools used to generate framework apps provide access to the appropriate testing tools for unit and integration testing.

I hope you enjoyed a little bit of the history lesson in this article. I truly believe that the best way to learn is trying to understand the WHY before the WHAT and the HOW, and one of the best ways to do that is to learn through history. In Part 2 of this article, we will explore the popular JavaScript frameworks throughout the history of web development. Stay tuned!

Photo Credits:

  1. [Background photo created by wirestock - www.freepik.com (https://www.freepik.com/photos/background)