Table of contents
- JavaScript, The Programming Language
- The Great Browser Wars
- jQuery Was Born
- Backbone.js & AngularJS Entered the Chat
- Transpiling With CoffeeScript
- Node.js, JS Goes in the Upside Down
- React & the Descent Into Tooling Madness
- TypeScript & The Botched Type Surgery
- Sunshine and Rainbows With Svelte
- Htmx Deployed to the Front
- Notable Exceptions
This article is inspired by Fireship's short video on web development.
JavaScript, The Programming Language
To start the article let me give you a very brief history lesson on JavaScript to understand why modern front-end development looks the way it does.
Netscape Communications Corporation, initially known as Mosaic Communications Corporation, was a pioneering American technology company that developed the first widely-used web browser, Netscape Navigator.
In 1995, Netscape hired Brendan Eich with the goal of embedding the Scheme programming language into its Netscape Navigator.
However, within just 10 days of his hiring, Eich had allegedly created a new programming language, initially named Mocha, later renamed LiveScript, and finally called JavaScript.
Contrary to what the name suggests, JavaScript has little to do with the Java programming language. The naming decision was more of a marketing strategy since Java was gaining popularity at that time. In the late 1990s, Netscape attempted to standardize JavaScript through Ecma International, leading to the creation of the ECMAScript standard.
Despite the ups and downs in JavaScript's history, including its battle with Microsoft during the browser wars, more on that below, it has stood the test of time and is now one of the most popular programming languages in the world.
Meanwhile, Netscape was acquired by AOL in 1999 and that was that, the product was discontinued in 2008.
The Great Browser Wars
To understand what mess created that we tried to fix with more mess that we call modern front-end development we have to revert time all the way back to the mid-90s/early 2000s.
You see, back in the early 2000s there wasn't much choice regarding browser flavors. You either used Netscape / Firefox or Microsoft Internet Explorer (IE), the former having the majority of market share in the high 90%.
Safari and macOS (originally called Mac OS X) were just a blip on the radar no developer was taking seriously. I don't remember Safari having more than 0.5% market share in the early 2000s.
Microsoft in the Gates & Ballmer era, but especially in the Gates era, was "very competitive" to say the least, and by "very competitive" I mean they simply annihilated any and all competition.
The Web wasn't any different in Microsoft's eyes. Browsers weren't different from other commercial products, users had to buy these applications and install them on their PC.
Microsoft wanted ALL the market share, so what they did was simply ship their browser, IE, with Windows as the default browser, so when users "opened the Internet" it was IE shining back in their faces.
As a response, Netscape tried to bundle their browser with other software that mainly ISPs provided to their customers, but Microsoft, being a behemoth, pulled the rug under their feet by requiring all 3rd party applications to be bundled with IE instead, making it a "required component for network access on Windows".
Then they did whatever they were feeling like with the scripting languages in IE disregarding any standards other vendors were trying to come up with. It was either Microsoft's way or the highway, they simply did not care about web standards.
If it were for Microsoft, we would all be using IE and VBScript today (even if I consider VBscript to be a more capable scripting language than JS back in the day).
Oh, and they also reverse-engineered Netscape Navigator's scripting language that was JavaScript and called it JScript.
In the end, Microsoft was found guilty of monopolizing the Web browser market and the verdict was that OS and browser must be two separate things and end users must be given the choice of using whatever browser they wanted.
Between VBScript, JScript, and JavaScript, the latter won out simply because developers could use a single scripting language to develop for multiple browsers, but there was a time when a web page would use half-baked JavaScript and VBScript code intermingled in a large HTML mess.
Note: There were also many other scripting languages like PerlScript or ASP. Much like what WebAssembly is trying to solve today so developers can use any programming language on the client side and still be performant and cross-browser compatible.
jQuery Was Born
In the early 2000s, the Web was truly a wild-wild west place. There were many competing standards, and vendors still discovering how to "program" for the Web.
If today's front-end development can be described as complex, back in the day it was chaotic and there weren't many online tutorials to turn to for help.
Because of this, jQuery was created. Its original purpose was to expose a unified, cross-browser compatible API to the developers. You see, before jQuery if, for example, you wanted to listen to JS events you had to program it for at least two different "standards", if not more, to be cross-browser compatible.
The code below is a tiny glimpse into the nightmare called web development circa 2005.
function myEvent() {
alert('click event');
}
if (elem.addEventlistener) {
elem.addEventListener("click", myEvent, false);
} else if (elem.attachEvent) {
elem.attachEvent("onclick", myEvent);
}
jQuery's execution was really good. Having a solid and simple API ironing out cross-browser compatibility issues so the developers don't have to, furthermore pioneering targeting browser features instead of browser user agents was a game changer.
I remember first reading about jQuery on QuirksMode and was completely amazed at how simple was to work with. I only needed a single script
tag and boom, there it was, all my problems fixed, with a single line.
It was an instant hit with web developers gaining mass adoption and driving a lot of modern web standards we love and use today. Let's not forget that jQuery still can be considered the most widely used JavaScript framework today even though some say it's mostly thanks to WordPress.
After "fixing" browser JS compatibilities the next step in jQuery's evolution was its plugin system. For the core to remain small, jQuery implemented a plugin system so developers could ship other library code and still use the goodies from jQuery; and what developers mainly created were reusable UI widgets like the famous jQuery Datepicker.
Backbone.js & AngularJS Entered the Chat
Backbone.js, released in 2010, was among the pioneers in bringing structure to client-side web applications and taking baby steps towards single-page applications (SPA).
Some developers would argue that Backbone's more important role was kickstarting the philosophical shift towards front-end development.
Not to take away the fame from the YUI Library which dabbled with the notion already.
Before Backbone.js websites were delivered by a server-side application pushing HTML and CSS to the client-side browser and "progressively" enhancing the UX with JavaScript, hence the term "progressive enhancement".
As websites became more interactive, this necessitated keeping a client-side data model in sync with the server-side model and the DOM. Backbone.js addressed this need with a design built around an MVC-like (Model View Controller) architecture, thus marking a significant milestone in component-based web development.
AngularJS, on the other hand, is the brainchild of Google, first released in 2010, and subsequently, Angular 2+ from 2016 forward (collectively referred to as Angular), is not a library, unlike Backbone.js.
Angular is a full-fledged, "feature-rich" JavaScript framework. It introduced the concept of “directives” (later implemented by Vue), which provided an elegant mechanism to extend the HTML syntax, thus allowing developers to create their custom HTML elements and an important concept in component-based development.
With "directives", Angular enabled the creation of reusable components, a feature that would significantly enhance code maintainability and readability. So said the "marketing brochure".
Ultimately, both Backbone.js and Angular started important conversations in the web development community about creating more efficient, maintainable, and scalable client-side applications, and starting the component-based web development "madness".
Transpiling With CoffeeScript
CoffeeScript's role in the evolution of JS frameworks is mainly attributed to the concept of "transpiling", in other words, the concept of source-to-source compilation; and it was created by the same person who created Backbone.js.
CoffeeScript's answer to developers who hated working with JS at this point and managing all the quirks and intricacies of the language is to create a new language altogether and then transform that language into JavaScript to be able to be used in browsers.
Beyond easier syntax, the advanced features of CoffeeScript, such as destructuring assignments, classes, and array comprehension, have significantly simplified the process of building web components and ultimately these features found their way back into modern JavaScript.
Node.js, JS Goes in the Upside Down
I think that Node.js was the fuel on the slow-burning fire that started the fast-paced development of client-side technologies and the adoption of the many modern JavaScript standards that we have today.
Prior to Node.js, JavaScript was essentially a client-side language used for adding interactivity to web pages. Web developers had little to work with in terms of tooling for JS development, mostly relying on web browsers for runtime execution, and often resorting to manual code minification and concatenation by using other server-side technologies.
The advent of Node.js brought JavaScript to the server-side, enabling developers to execute JavaScript outside the context of a browser.
Even though the original premise (and proof) of Node.js is that JavaScript can be used anywhere, promising a more streamlined web development workflow, optimize code, catch errors, and automate repetitive tasks by using the same programming language on both server- and client-side, in fact, it kickstarted the exact opposite trend. After all, it's not Node's fault how people are using the technology.
Node.js provided a platform for developing such tools, resulting in a rich ecosystem of packages like Grunt, Gulp, Webpack, Babel, and others.
Arguably the second biggest innovation of Node.js was its package manager, NPM which drastically simplified the installation and distribution of JavaScript libraries and tools.
React & the Descent Into Tooling Madness
Now, we have arrived in full SPA, interactive, rich-web, enhanced to the gills mode web app territory and I believe React needs no introduction.
React, even though it didn't pioneer the complicated ecosystem we have around front-end development today, it sure influenced how we do things the React way™.
With the ever-more need to create highly interactive and performant web applications more and more tooling was created around module-based JavaScript code and the FOMO of tech engineering leads somewhat resulted in what we have today.
My first introduction to React was in 2014-2015 when my team was outsourcing for a Silicon Valley client where the tech leads were fully sold on the early React Flux Architecture.
I remember being adamantly against JSX echoing the larger web development community's voice: "How could any sane developer embed HTML into JavaScript?!".
But there it was, HTML in JS, then CSS in JS, and then as with many things in web development you have to learn to love it. Managing the application state in the browser and then reacting to it is all the rage now.
React started and Vue continued the shift towards JavaScript-centric development by encouraging developers to write everything in JavaScript, including markup language and styles advocating "create once, use it anywhere" components, or at least that was the promise. React took it even further with React Native, the ambitious promise of using everything everywhere, including mobile, and writing it only once.
React also fueled the trend of this front-end feedback loop where more and more tooling and JS modules are created every day to further improve or fix the downsides of major JS frameworks that everybody decided to use not questioning whether it made sense to use the way it was intended to be used.
Note: If you have an hour, go watch the React.js Documentary. Yes, it's good filming and production.
TypeScript & The Botched Type Surgery
Just like CoffeeScript, TypeScript is a source-to-source programming language and not a JS framework, but plays a pivotal role in the evolution of these frameworks.
At least that's what Microsoft and many thousands of developers are advocating.
Don't get me wrong, type safety in a programming language is paramount, but I'm not fully onboard with bolting types on top of a language where dynamic types are intended to be a feature and not a bug.
In this regard, I agree with DHH on the false promises of TypeScript and why it makes sense not to use it in their products.
Before TypeScript came into play, JavaScript was known for its difficulty to manage in large-scale projects, and not just mainly because of the lack of static types. However, the lack of static typing doesn't make the language better and it made debugging and maintaining code increasingly complex as a project grew in size.
TypeScript also offers powerful features like interfaces, enum types, and optional parameters that are absent in JavaScript but can be important to "taming the beast" in more complex JS projects.
Also, TypeScript provides developer tooling that enables more accurate autocompletion, refactoring capabilities, and more (also, autocompletion and lint rules can be set up and just use JSDoc).
But TypeScript is essentially an additional layer on top of JavaScript, introducing a level of complexity and overhead that may not be required or suitable for every project or development team.
Although TypeScript provides a wide range of enhancements, it comes at the cost of needing to learn an entirely new language with its syntax, rules, and best practices. Not to mention figuring out type rules that other JS frameworks have implemented. For smaller projects or teams, this may prove to be a significant deterrence.
TypeScript requires developers to annotate their variables, function returns, and arguments with their types. While this can make code easier to read and debug in large projects, it can slow down development. In other words, the very feature that makes TypeScript awesome in large-scale projects can turn into a horrible nightmare for smaller ones oftentimes reverting back to JavaScript is more productive.
At the end of the day what TypeScript did is to start the conversation of having opt-in static types in JS maturing the language, which is awesome.
Sunshine and Rainbows With Svelte
By now every front-end developer has had it with the JS ecosystem. This is where Svelte enters the picture.
One of the primary problems SvelteJS is trying to solve is the unnecessary bloating that results from the usage of "traditional" frameworks, because by now React, Angular, and even Vue are considered "traditional" and conventional.
Another area that Svelte is trying to amend is the steep learning curve presented by other frameworks and libraries. While frameworks such as React or Angular offer great power and flexibility, they can be overwhelming for beginners due to their complexity. Svelte, in contrast, is developed to be much more intuitive and easy to grasp. With its simpler syntax and less boilerplate code, developers with only a basic understanding of HTML, CSS, and JavaScript can become proficient in using Svelte in a relatively short time.
Svelte can also be considered to be a programming language that compiles HTML-, CSS-, and JS-like code instead of a parser that parses regular HTML/CSS/JS.
If we think about Svelte as a programming language then the code we write is a separate language that happens to look like HTML, CSS, and JS, but it's not. This is why Svelte goes into devDependencies
because we don't need any of Svelte's code in production in contrast with React and others.
Typically, with traditional JavaScript frameworks, the client's browser must load the entire JavaScript bundle, parse, compile, and execute it before the user can interact with the application. This process can be slow and negatively impact the user experience, particularly on mobile or slow networks. SvelteJS solves this problem by doing the heavy lifting during the build process.
Svelte, unlike React, is much more opinionated on how to do things which is not necessarily a bad thing. This is most notably can be seen in SvelteKit.
Also, Svelte is one of the major frameworks that started talking about the place of MPAs (multi-page applications) in client-side development. Before that MPAs were considered this antiquated development method that no developer would use, ever (wink, wink).
Still, Svelte tries to shine a beacon of hope in the muddy waters of broken front-end development.
Htmx Deployed to the Front
Okay, we are slowly coming full circle.
If you never heard of htmx I don't blame you. It's a relatively new JS framework (at least its modern iteration), more like a paradigm shift from modern front-end development.
While CoffeeScript, TypeScript, and Svelte all try to fix JavaScript by using something similar to JS, but only the good parts™ then converting the whole thing into JS, the creator of htmx wants to start from scratch by not using JS altogether.
Alright, the above paragraph is not a fact, but it's funny nonetheless.
Htmx essentially lets web developers access AJAX, CSS Transitions, WebSockets, JS Events, and SSEs (server-sent events) directly in HTML without needing to write JavaScript (okay, some JS). It introduces a new approach (okay, it's not entirely new) to enhancing web apps by seamlessly transforming static HTML into dynamic content.
Unlike other heavy JavaScript frameworks, htmx aims to shift the balance of responsibilities, taking a simpler approach to web development. By allowing developers to execute common dynamic UI interactions directly in HTML with its extensive attributes, or some would say directives, it significantly reduces the dependency on JavaScript.
This reaffirms the principle of progressive enhancement in web development, where HTML and CSS handle the foundation and layout, while JavaScript is kept lightweight and used for added interactivity when needed.
What's worse is that htmx is annoyingly simple. It's worse that we had to descend into slow madness to see the light at the end of the front-end development tunnel when there wasn't any tunnel nor pitch-black darkness because the techniques used by htmx were always there, invented by others decades ago.
Through the use of backend languages, developers are allowed to build and modify their applications and keep data and state on the backend where it should be, whilst keeping the UI dynamic and responsive on the frontend where it should be.
Ultimately this is a good thing because young developers will discover the true joys of front-end web development by not using modern JS frameworks at all, and this is not to say that React, Vue, Svelte, and Angular will vanish into thin air anytime soon. Baby steps.
Full-stack devs are back baybieeee...
Notable Exceptions
I know I skipped many notable web technologies such as Alpine, Astro, Babel, Bun, Dojo, EmberJS, Esbuild, ES6, ExtJS, Express, Gatsby, GraphQL, Jamstack, KnockoutJS, Lit, MeteorJS, MERN, MooTools, Next, Nuxt, Parcel, Polymer, Preact, PWAs, Remix, REST, RollupJS, Rome, Ruby on Rails, RxJS, SproutCore, Sass, Skypack, Snowpack, SolidJS, Stencil, Stylex, Vite, Vue, Zig, and others... that all contributed to modern front-end development in some shape or form.
The main reasons are that 1) I can't cover everything, 2) a lot of technologies have overlapping ideas, and finally 3) I'm not that familiar with a lot of these technologies to have a sensible opinion about them.