Down to the Wire

Effectual JS Part 0: Build your own Framework from Scratch!

Web development frameworks are the backbone of modern full-stack engineering. In modern web dev, nearly every project starts with a choice of framework, and builds every further decision atop that.

On the surface, it might be easy to compare & contrast the differences between e.g Vue and React, but to effectively evaluate and use either of them requires a much deeper understanding.

In this blog series, we’ll dive deep into the core concepts used by web dev frameworks and build our own from scratch atop those principles. At the same time, we’ll leverage the latest features modern browsers have to offer.

This is Effectual Web Development.

Introduction

Getting Started

There are so many decisions along the way, and so many discussions to be had.

Before we can even have those, however, we need to start with the fundamentals of what a framework is, and why you would use one.

The Bad Old Days

I wrote my first real web app in 7th grade on a Jailbroken CR-48 Chromebook during health class. It was, as one might expect from a kid, a game! Specifically, I had read about CSS3D transforms, and decided to make a variant of Snake that flipped & rotated the board as you played.

It had 3 levels, and all of the logic was hard coded into a single .html file that dynamically created HTML elements, read user input, and updated their colors according to the game state.

All of this logic required endless use of document.getElementById and Element.style to interface with the DOM. And you know what? It worked! It was annoying and error-prone, but it got the job done.

So why don’t we write code like this anymore?

PHP, MVC, and the dawn of Something New

To be very clear, web frameworks have been around for far longer than I’ve been programming. Even in 7th grade, they were there for me had I wanted to use them.

We’ll start our discussion of them, however, with a controversial claim: PHP was one of the first real web frameworks.

PHP allowed programmers to embed logic inside the generated HTML that could respond to various actions (such as a form submission). Every time one of these actions occured, the server would recompute the state and return it to the client.

In doing so, it served two of the main purposes of a web framework:

  1. Declarative DOM managment: If you’ve ever seen PHP code, you’ll notice that the DOM is never explicitly manipulated. Instead, explicit if (condition) statements could choose which bits of HTML are rendered. In this model the code “declares” what the resulting HTML should be, which then gets rendered by the browser.
  2. State change management: Although most of the heavy lifting is done by the browser itself, PHP was able to allow changes in application state to be reflected in the DOM (by rerending a new page on load or form submission).

Although PHP is clunky and offers an absurd number of foot-guns, the two basic principles here are so important that it has demonstrated an unbelievable staying power.

MVC

However, PHP is only barely a framework. For me, and I suspect many others, the first true frameworks we encountered were Ruby on Rails and Django.

Building off of those two core ideas, they added a third: a separation of concerns.

To a greater or lesser extent, these frameworks abided by the model-view-controller (MVC) pattern wherein the data itself (model), presentation of the data (view), and the logic that connects the two (controller) are each explicitly managed as part of the application’s lifecycle.

By separating these components it became much easier to build complex systems that were not only maintainable, but easy to reason about.

Angular

Angular is not the first frontend-only web framework, but does earn its place in history as the first to have major backing and community support.

Like the above, Angular supports declarative DOM management, state change management, and a separation of concerns via MVC-ish.

However, unlike the others we’ve mentioned, it does not rely on the server being part of the equation. Instead of having the browser send state changes to the server, which would then forcibly update the client, Angular allows the client to update its own state internally and then reconciles those changes to the currently extant DOM.

One thing that’s hard to remember this far out is that Angular felt so much more responsive and snappy than other contemporaries. By not relying on round trips to the server, the changes users’ made would be reflected in near real-time.

React, Vue, and the Modern Web

Angular got a lot of things wrong (especially in version 1.0), but it got enough right that it started the ball rolling for the modern web frameworks of today.

React introduced an even more declarative approach to DOM management, Vue emphasized developer experience and ease of use, and the others that follow build up from these core principles.

Although there are many differences between them, they all share a common set of foundations. As we begin our process of building our own framework, we’ll examine each of these principles closely, and evaluate them for our own use.

Effectual JS

The Plan

Here’s what I want us to do.

We’re going to work together to build a web framework from the ground up, one piece at a time. For each section, we’ll both evaluate the current state of the art, look at how other frameworks have approached the problem, and then build our own version.

Here are my primary objectives for this series:

  1. Understand the core ideas behind web developement frameworks: Once we’re done with this, we should be able to look at any new framework and have a rough intuition of how it works
  2. Learn to leverage the modern web: Developing web apps in 2024 is so much better than it was even 5 years ago. Let’s not force ourselves to live in the past as we’re working on this.
  3. Build something cool: If we’re going to spend the time on this, we might as well make good use of it!

Before We Start

Sadly, we’re not quite ready to get into the actual development of our framework first. Before we can actually write any code, we need to figure out what tools we’re going to leverage and the general patterns we’re going to follow.

Language

Our framework will be written entirely in TypeScript, using ESModules and JSX syntax. This will let us leverage modern JavaScript tooling despite the fact that we’re using a custom framework. Specifically, to justify each of these:

  • TypeScript greatly improves DX and helps us catch errors in real time
  • ESModules are now natively supported in browsers, and make it easy to do dynamic loading in JavaScript
  • JSX will make it easy for us to write our templates in a way that’s more familiar to modern web developers

We’ll build this as a monorepo with nested Yarn workspaces. This will make it easier to split our logic up into separate packages, while at the same time keeping everything in one place and self-synchronized. Everything will be stored in this git repo and checkpointed for each version of the framework.

Let’s Start!

Follow along with us as we build Effectual JS on dttw.tech and effectualjs.com.

Next up: Part 1: Rend(er) me Asunder.