REPORT
CEPATO Technical Note2026.02.08

36 Years in Review: A History of Internet Frontend Development

36 years of frontend history: the sweeping technological evolution from 1990 to 2026

Chongxi
Author:Chongxi
steam: —·spotify: —
Tags:#Frontend
ANALYSIS

Studying computer science is studying computer history

0. Introduction#

0.1 Only screen is real#

We often compare the internet to an iceberg: beneath it, tens of thousands of switches, servers and databases rumble away

But for the user in front of the screen — someone holding a phone on the subway, or an office worker at a desk staring at a monitor — only the pixels on the screen are real

If tapping that “commit” button does nothing; if that list stutters as it scrolls; if that page shows a blank white screen while loading
then no matter how elegant the backend architecture or how precise the algorithms, to the user it’s just garbage software

For a long time, frontend developers were jokingly called slicers
In software development’s chain of contempt, frontend often sat at the bottom
Backend engineers thought frontend was just writing HTML tags and styling things — no need to understand memory management, no need to understand concurrency control, not even real programming languages.

Yet the history of these thirty years has proven that prejudice absurd. Frontend development is going through the most violent, most brutal evolution in the history of computer science. We went from merely displaying a physics paper to running Photoshop, 3D games and even IDEs inside the browser sandbox

What this blog post covers is not a tedious ledger of APIs, but the “Romance of the Three Kingdoms” of frontend over the past thirty years

A word before we start: this article is told from my personal perspective and is bound to contain errors; please bear with me / point them out as much as you can.

0.2 Original sin#

To understand why frontend has been so chaotic these thirty years, why frameworks keep multiplying, and why toolchains are complex enough to make you tear your hair out, we have to go back to the origin and examine why the Web was born

When the WWW was born in 1990, Sir Tim Berners-Lee’s design goal was very pure: to let scientists share documents conveniently

Remember the word document. It is the root of all frontend pain and complexity, and in my view, the original sin

  • HTML is for describing document structure
  • HTTP is a stateless protocol: you request a document, take it and go, no connection kept
  • Browser is just a document reader

As commercialization exploded, humans wanted more and more. We no longer wanted a static sheet of paper; we wanted an App

  • We want to do chat in this document reader
  • We want to run a stock exchange here
  • We want to collaboratively edit Excel here
  • We want to watch HDR video here

It’s like being asked to develop Minecraft inside Microsoft Word

What frontend has been doing these thirty years is, in essence:
using a series of crude technologies originally designed for static documents, and through all sorts of clever hacks, forcibly building dynamic applications that rival native OS software

  • Because HTTP is stateless, we invented Cookie and Session, and later came up with JWT
  • Because every click in HTML refreshed the whole page, which felt terrible, we invented AJAX and forcibly turned web pages into SPAs
  • Because DOM operations were too slow, we invented the Virtual DOM, computing everything in memory before touching the real DOM
  • Because JavaScript had no module system when it was born, we invented CommonJS, AMD and UMD, and eventually forced ES Modules into existence

The history of frontend’s evolution is a history of resistance against the browser. We fight the browser’s limitations, network latency and device fragmentation

0.3 Cycles#

As you read this blog, you’ll notice a very interesting phenomenon: the cycle of technology

  • Web 1.0: pages were server-rendered. PHP/JSP assembled the HTML on the server and the browser displayed it directly. That was the extreme of static
  • Web 2.0: for a better interactive experience, we moved all the logic into the browser. The browser became the client and the server only spat out JSON data. That was the extreme of dynamic
  • Now: for first-screen speed and SEO, we realized client-side rendering was too slow. So Next.js and Nuxt showed up again

Humanity went in a circle and seems to be back where it started?

No.

The static of back then was because we couldn’t do dynamic
The static of now is a deliberate choice made for the ultimate experience, after we had mastered dynamic

0.4 Who is frontend?#

In 2000, if you could write <table> layouts and <font> tags, you were frontend (back then it was actually called web designer)
In 2010, if you could use jQuery’s $('#id').click(), you were frontend Now you need to know TS, JIT compilation, HTTP/3, server-side containerization and so on

The boundaries of frontend are expanding without limit.
Upward, we’re encroaching on backend territory with Serverless (even if it’s not great right now)
Downward, we’re calling into C++/Rust through WebAssembly
Outward, we’re building native apps with React Native / Flutter

But no matter how the tech stack changes, there’s one thing I hope frontend developers reading this will remember:

We are the people closest to the user

1. The starting point#

1.1 Tim Berners-Lee’s puzzle pieces#

The starting point of everything was not grand. No venture capital, no IPO, not even a desire to change the world

In 1989, while working at CERN, Tim Berners-Lee faced a very concrete pain point: physicists’ papers and data were too hard to find. They were scattered across different computers in all sorts of formats, and if you wanted to cite someone else’s research you had to look it up by hand

So he came up with a concept: the World Wide Web

To realize it, he laid out three puzzle pieces that remain the foundations of the internet to this day:

  1. HTML: a simple markup language for describing document structure (headings, paragraphs, lists). Note that it is only responsible for structure, not for looking good
  2. HTTP: a stateless transfer protocol. You request a document, the server gives it to you, and then the connection closes. This burn-after-reading quality is why the Web was initially just a library, not an “operating system”
  3. URL: giving every document in the world a unique address

On Christmas 1990, on that NeXT computer, he wrote the world’s first browser and first server

What did web pages look like back then?
Only text — just black text on white and blue hyperlinks. Images needed to pop up in a new window to be viewed

Frontend development then was no different from writing a Word document. You only needed to know a few tags like <h1>, <p> and <a>. It was a Read-Only era

1.2 Tables and Spacer GIFs#

With the release of the Mosaic browser (the first widely popular graphical browser), images could finally be mixed with text. Commercial companies began moving onto the internet, and designers arrived with graphic-design thinking

Boom

The designer says: I want a logo in this corner, a three-column layout below the big headline, and a Guide on the right
The engineer looks at the crude HTML and says: you’re treating me like a Japanese salaryman here

HTML at the time had only document flow. No Float, no Position, and certainly no Flexbox

What to do? Clever — or rather, desperate — developers found a loophole: HTML had a tag for displaying data, <table> — the table

If you set the border to 0 (border="0"), the table lines become invisible, right?
If you nest tables inside tables, you can carve out complex layouts, can’t you?

And so the table layout era began

  • The slicer is born: the designer cuts a beautiful web design in Photoshop into dozens of little tofu blocks, and the frontend engineer reassembles them with one giant <table>
  • Nesting hell: to make a rounded box, you might need a 3x3 table with rounded-corner images in the four corners and content in the middle. If the content has layout inside it, nest another table. The code looks like a giant maze
  • Spacer GIF: the greatest “hacking technique” of that era
    • Table cells sometimes collapse, or you want an exact 10px gap — what do you do?
    • You make a 1x1 pixel transparent GIF
    • Then you write <img src="spacer.gif" width="10" height="1">
    • You can’t see it, but it props the space open

This was the first large-scale instance in frontend engineering history of doing whatever it takes to get the result. The semantics were terrible and maintenance was brutally hard (change one character and the whole table might collapse), but it gave web pages a sense of design for the first time

1.3 JavaScript, rushed into existence#

In 1995, Netscape was at the eye of the first browser war. It was under enormous pressure to make web pages move

The pain point was quite mundane: form validation
That was the dial-up era, and connection speeds were atrociously slow. A user filled out a long registration form, clicked submit, the data went to the server, the server discovered the username was empty, and sent the page back to tell the user there was an error. That round trip could take tens of seconds or even a minute. Users lost their minds

Netscape decided there had to be a scripting language that could check forms right in the browser, without going through the server

The task went to Brendan Eich

  • The boss’s requirement: it has to look like Java (Java was at its peak then, and Netscape wanted to ride the hype)
  • Brendan’s ulterior motive: he actually wanted to bring Scheme or Self into the browser. He liked functional programming
  • The result: to ship before Netscape Navigator 2.0’s release, he took only 10 days

The language was first called Mocha, later renamed LiveScript, and finally, on the eve of release, renamed JavaScript for marketing

This is the root of all the complaining about JS that followed:

  • It has Java in its name but nothing to do with Java
  • Its syntax looks like Java, but at heart it’s a functional language
  • Its design is full of hasty compromises:
    • null and undefined both exist, and even the famous typeof null === 'object' bug survives to this day
    • Baffling errors caused by automatic semicolon insertion
    • Extremely loose type coercion ([] + [] = "")

It was designed as a toy language, just for little tricks like changing an image’s color on mouseover, popping up alert dialogs, and checking that an input box isn’t empty

Professional programmers of the time (Java developers, say) turned their noses up at JavaScript. They didn’t consider it programming; it was just script snippets

But Pandora’s box was already open

Crude as it was, it gave the browser the ability to compute logic
With logic, web pages were no longer just documents; they began evolving into apps

It was amid this mess of table tags, transparent image placeholders and a few lines of crude script validation that frontend stumbled into the commercial era of the Web

And just ahead, a giant named Microsoft was about to wake up


2. The first browser war#

2.1 The giant’s crash#

In 1996, Netscape Navigator held nearly 80% of the market. Browsers were paid software back then (or rather shareware), and it was the only gateway to the internet

But Bill Gates woke up. He sent out the famous “Internet Tidal Wave” memo, and the Microsoft aircraft carrier began turning around at full speed

Microsoft adopted the classic Embrace, Extend, Extinguish strategy:

  1. Embrace: Microsoft licensed Spyglass Mosaic and reworked it into Internet Explorer
  2. Extend: to differentiate themselves, both sides started frantically stuffing private extensions into HTML
    • Netscape invented the <layer> tag and <blink> (blinking text — the most annoying tag in history, in my opinion)
    • Microsoft invented <iframe > and <marquee> (scrolling text)
    • Netscape used document.layers to manipulate elements; Microsoft used document.all
    • As a result, developers had to write piles of if (document.all) { ... } else { ... }. This was the ancestor of browser sniffing code
  3. Extinguish: Microsoft deployed its nuclear weapon: free bundling. IE came preinstalled with Windows 95/98. Netscape’s only source of revenue was cut off

In 1998, Netscape was crushed and acquired by AOL. But before dying, it made a decision that changed history: open source (dun dun dun)

They threw all of Netscape’s chaotic code at the community and founded Mozilla. That seed lay buried for many years before growing into a great tree called Firefox

2.2 IE6: imperial glory and crash#

In August 2001, Windows XP shipped, and with it came Internet Explorer 6.0

We need to judge this former king objectively. Looking back at IE6 from 2026, it’s synonymous with outdated, buggy and insecure. But in 2001, IE6 was the most advanced browser in the world, bar none (after all, you can’t judge the past by today’s standards)

  • It was the best CSS renderer: compared with earlier versions, its CSS1 support was actually pretty good (despite the famous box model bug)
  • It was the fastest JS engine: V8 was still in the womb back then
  • It brought the spark of AJAX: ActiveXObject("Microsoft.XMLHTTP") was introduced with IE5/6

IE6 quickly grabbed 95% of the market. Microsoft won, and so it disbanded the browser team (lol)
Web time stopped

From 2001 to 2006, a full five years, browser technology made no substantive progress. I call these five years the Web’s Dark Ages

For frontend (dedicated frontend developers were starting to appear by then), these five years were five years of fighting bugs:

  • Box model bug: the standard said width is the content width; IE6 said width includes the border. So we learned CSS Hacks: _width: 200px; (only IE6 recognized properties starting with an underscore)
  • PNG transparency problem: IE6 didn’t support PNG-24 alpha transparency, so everything showed against a gray background. We were forced to write filter code (AlphaImageLoader) or keep using GIFs
  • Double margin bug: the margin of floated elements would mysteriously double. The fix? display: inline

We were no longer builders but fixers. The barrier to frontend development became mysticism; you had to memorize dozens of IE6 quirks to write a normal page

2.3 DHTML and Flash#

In an era when HTML/CSS stagnated and standards split, humanity’s desire for dynamic interaction didn’t disappear. That desire found outlets in two directions

2.3.1 DHTML#

DHTML (Dynamic HTML) was not a standard but a marketing term
It meant: using JS to modify CSS properties and make static HTML move

It was the era of effects

  • Web pages had text trails drifting after the mouse
  • Navigation menus bounced when they expanded
  • The status bar had scrolling marquee text

Most frontend developers couldn’t write JS; they were script porters. They went to sites like DynamicDrive.com, copied a few hundred lines of JS, pasted it into the page, and tweaked the parameters. JS was seen as an ornament back then — a toy that made a page look cool (or extremely Shamate)

2.3.2 Flash#

Since HTML was so bad and different browsers rendered it inconsistently, why not step outside the browser?

Macromedia Flash (later acquired by Adobe) burst onto the scene
It was, in effect, a virtual machine inside the browser

  • Consistency: whether you were on IE or Netscape, as long as you had the Flash plugin, it looked exactly the same. This was the most powerful counterattack against compatibility hell
  • Multimedia: it could play video and audio (HTML couldn’t at the time)
  • Vector graphics: it could do animations that scaled without loss (SVG wasn’t a thing yet)
  • A powerful language: ActionScript. While JS was still handling form validation, ActionScript 2.0/3.0 was already a fully object-oriented language with classes, inheritance and interfaces

In those days, the top-tier frontend engineers were actually Flash Developers. They made Happy Farm, they made video sites (the early 土豆 / 优酷 players), they made incredibly gorgeous corporate websites

Flash was the true prelude to Web 2.0
It proved that web pages could be more than documents — they could be games, movies and complex applications
But it was a black box. Search engines couldn’t read it, and mobile devices (the iPhone later on) couldn’t run it

Amid this seemingly unsolvable deadlock, the Web was brewing a real revolution
And in far-off CA, Google was quietly rewriting Gmail’s code, preparing to give the world a little shock using the XMLHTTP interface IE6 had forgotten about


3. Web pages begin to breathe#

3.1 The Gmail shock#

On April Fools’ Day 2004, Google launched Gmail. Everyone thought it was a joke, because it offered 1GB of free storage (mainstream email at the time had only 2MB)

But what really stunned geeks wasn’t the capacity — it was the experience

Before that, web interaction was synchronous:

  1. The user clicks “next page”
  2. The browser goes blank
  3. The server generates new HTML
  4. The browser re-renders the entire page

In Gmail, when you clicked an email subject, the page didn’t refresh. The list stayed on the left and the message content appeared on the right in an instant.
It felt so much like a native app that many suspected Google was using Flash or a Java Applet

It wasn’t. They were using a pure, native technology Microsoft had forgotten in a corner: XMLHTTP

  • Microsoft developed this technology in 1999 for Outlook Web Access and shipped it with IE5. But Microsoft didn’t value it itself, treating it as an inconspicuous ActiveX control
  • Jesse James Garrett names it: in 2005, this UX designer wrote a famous article coining the term AJAX (Asynchronous JavaScript and XML) for this whole class of “communicate with the server without refreshing the page” techniques

From then on, web pages had a background thread
It could quietly fetch data from the server while you weren’t looking. Web pages began to breathe

3.2 JSON, an accidental standard#

The “X” in AJAX stands for XML. At the time, XML really was the standard format for data exchange
But parsing XML in JavaScript was an absolute disaster. You had to write piles of getElementsByTagName, and the code was verbose and slow

Then a Yahoo architect named Douglas Crockford stepped up
He discovered that JavaScript had a native data representation — object literals

PRTCL // JAVASCRIPT
// XML
<user><name>Chongxi</name><age>23</age></user>
// JSON
{ "name": "Chongxi", "age": 23 }

Crockford didn’t even invent it; he merely discovered it. He named this format JSON

  • It’s natively a JS object, so parsing is extremely simple (early on people just used eval(), insecure as that was)
  • It’s far lighter than XML (all those angle brackets gone, saving bandwidth)

This was the most effortless victory in Web history
Thanks to frontend developers’ enthusiastic advocacy, backend engineers found that generating JSON was easier than generating XML too. So the “X” in AJAX became a name without substance, and JSON ruled the world

3.3 Firebug#

Before 2006, the only tools for debugging JS were: alert('Here 1'); alert('Variable x is: ' + x);

Developers groped around like blind people. If the code errored, IE just showed a yellow exclamation mark in the lower left telling you an object was missing, and the line number was always wrong

In January 2006, Joe Hewitt released the Firefox add-on Firebug

  • It could inspect elements: point the mouse somewhere and it highlighted. Oh my god, we could edit CSS right in the browser and see the result
  • It had a Console: console.log() finally replaced alert()
  • It could set breakpoints
  • It could capture network requests

Firebug was the first cornerstone of frontend engineering It turned frontend development from mystical guesswork into scientific observation


4. Write Less, Do More#

4.1 The savior#

Even with AJAX and Firebug, frontend development was still excruciating The pain point was: fragmentation

  • Getting an element:
    • Standard browsers: document.getElementById
    • To get by Class: IE6 didn’t support getElementsByClassName. You had to write your own loop to traverse the DOM
  • Binding events:
    • Standard: addEventListener
    • IE: attachEvent
  • Getting computed styles:
    • Standard: getComputedStyle
    • IE: currentStyle

Every frontend engineer had a utils.js on their computer holding hundreds of lines of dirty compatibility code

In August 2006, John Resig released jQuery at BarCamp NYC
Its core idea was brutally simple: hide all browser differences behind the $ symbol

4.2 The art of chaining#

jQuery invented a highly expressive API style: method chaining

The old code:

PRTCL // JAVASCRIPT
var div = document.getElementById('CEPATO');
div.style.color = 'red';
div.style.display = 'block';
div.onclick = function() { alert('clicked'); };

The jQuery code:

PRTCL // JAVASCRIPT
$('#CEPATO').css('color', 'red').show().click(function() {
alert('clicked');
});
  • The Sizzle engine: the heart of jQuery. It let JS select elements the way CSS does (div > ul.list li:first-child). That was black magic at the time
  • Implicit iteration: $('.item').hide() automatically hides every .item on the page; no for loop needed

jQuery quickly became the de facto standard. Microsoft even ended up bundling jQuery IntelliSense into Visual Studio

4.3 The golden age of copycats#

Another great thing about jQuery was its plugin mechanism ($.fn.extend)
It gave rise to the earliest prototype of componentization in frontend

  • Lightbox: click an image, the background dims and the image enlarges
  • Carousel: an image slider
  • Datepicker: a date picker

Countless slicers who didn’t understand how JS worked could, just by downloading jQuery plugins and tweaking CSS, assemble a site full of interactions
jQuery dramatically lowered the bar for frontend, but it also sowed disaster: masses of spaghetti code and abusive DOM manipulation made pages slower and slower


5. The engine arms race#

5.1 Speed#

As AJAX and jQuery spread, the amount of JS in web pages grew exponentially
From a few hundred lines to a few thousand, even tens of thousands… and then

The browser couldn’t keep up

JS engines back then were all interpreters: read a line, run a line. Extremely inefficient
If web apps wanted to replace desktop software, the biggest bottleneck was slowness

5.2 Google’s overt scheme#

In September 2008, Google released a comic book introducing a new browser: Chrome
With it came a brand-new JS engine: V8

V8 did something earth-shattering: JIT
It didn’t interpret code; it compiled JavaScript straight into machine code and ran that

  • When V8 first shipped, JS execution was faster than IE by an untold multiple
  • Multi-process: one tab crashing wouldn’t bring down the whole browser. This was also a Chrome first

V8 changed everything

  • It proved JS could run blazingly fast
  • It gave JS the ability to handle extremely complex logic (not just form validation)
  • Since V8 was so fast and was a standalone C++ library, why not take it out and run JS on a server? (And a year later, Node.js was born)

5.3 WebKit#

Meanwhile, Apple’s open-source WebKit engine (derived from KHTML) began to rise. Safari and early Chrome both used WebKit
It was the cornerstone of the mobile internet. When the first iPhone launched, Jobs refused to support Flash and only backed web standards
Which meant the coming mobile web wave would belong to WebKit… or would it?

At this point, frontend had:

  1. Interactivity
  2. A data standard
  3. Developer tools
  4. A standard library
  5. A high-performance engine

Everything was ready
But as code volume ballooned, a massive crisis was coming
We had guns and cannons, but we lacked tactics. We could write flashy effects, but we couldn’t maintain large systems

Next up is engineering and the architectural revolution: Node.js takes the stage, and frontend finally starts thinking like a proper software engineer

6. Nodejs#

If in the first twenty years frontend was dancing in chains inside the browser sandbox, then starting in 2010, frontend engineers pulled off an earth-shattering, heaven-and-earth-weeping jailbreak that completely rewrote the rules of the game

6.1 Ryan Dahl’s crazy experiment#

At JSConf EU in 2009, a young man named Ryan Dahl gave a demo

He did something that seemed to betray his ancestors: he pulled the V8 engine out of Google Chrome, bolted filesystem and network modules onto it, and made it run on a server

It was like pulling the engine out of a Ferrari and mounting it on a tractor

The project was called Node.js

At first, everyone thought it was a revolution in backend technology (non-blocking I/O, high concurrency)
But soon frontend engineers discovered an earth-shattering secret: wait — if the server can run JS, does that mean we can write… in JS…

Before that, if you wanted to minify a JS file, you had to use YUI Compressor, written in Java
If you wanted to preprocess CSS, you had to use Sass, written in Ruby
Frontend developers’ toolchains were in other people’s hands

With Node.js, frontend gained the right to build its own wheels

6.2 npm#

In 2010, Isaac Z. Schlueter released npm

Before that, if we wanted jQuery, we downloaded jquery.js from the official site, dropped it in the project folder, and wrote <script src="jquery.js"> in the HTML. If jQuery depended on another library, you had no idea until it errored

npm changed everything: npm install jquery
This wasn’t just a download tool; it introduced semantic versioning and the dependency tree
Frontend code was no longer fragments scattered everywhere, but an organized, reusable module system

6.3 Automated builds: Grunt and Gulp#

With Node.js (a runtime) and npm (package management) in hand, frontend engineers began writing automation scripts

  • Grunt: a configuration-based build tool. You write a giant JSON object telling it to first concatenate files A and B, then minify, then rename
  • Gulp: a stream-based build tool. The code reads as smoothly as a pipeline:
    PRTCL // JAVASCRIPT
    src('src/*.js')
    .pipe(babel())
    .pipe(uglify())
    .pipe(dest('dist/'));

This was the beginning of frontend engineering
We no longer refreshed the browser by hand or compressed images by hand
Frontend development evolved from handcraft to assembly line


7. The MVC free-for-all and the great mobile migration#

7.1 Steve Jobs’s verdict and the rise of HTML5#

In April 2010, Steve Jobs published his famous open letter, Thoughts on Flash
He listed Flash’s six sins (battery drain, poor touchscreen support, being closed, etc.) and announced that the iPhone/iPad would never support Flash

At that moment, the Web’s fate was rewritten
The gates of the mobile internet swung open, and the only passport was HTML5

So every company needed a mobile version of its site
But phone CPUs and networks were far worse than computers’, and screens were much smaller
Simple jQuery effects stuttered terribly on phones. We needed web pages that were more efficient and felt more native

7.2 The spaghetti code crisis#

As requirements grew more complex (making a web version of Excel or Trello, say), frontend codebases broke the 100,000-line mark
jQuery’s fatal flaw was fully exposed: it hid state in the DOM

Imagine you’re building a shopping cart

  • With jQuery: you read text from span.total-price, convert it to a number, add 1, then write it back to the span
  • What if three other places on the page also show the total? You have to update three places by hand
  • What if you miss one? There’s your bug

This add water when the dough is too dry, add flour when it’s too wet kind of code, tangled and complex, is called spaghetti code
Once the project grows, maintaining it is pure hell

7.3 Searching for order#

To solve this, frontend began learning from backend and adopted the classic software architecture pattern: MVC
The core idea: data (Model) is the source, and the view (View) is merely a projection of the data

7.3.1 The first-generation explorer: Backbone.js#

Backbone was very lightweight. It gave you three base classes: Model, Collection and View

  • It told you: keep data in the Model, not in the DOM
  • When the Model changes, it fires a change event
  • The View listens for the event and manually updates the DOM (still with jQuery)
  • It established order, but writing it was still exhausting — lots of glue

7.3.2 AngularJS (v1#

Released in 2009, wildly popular by 2012. AngularJS brought two concepts that shook the world:

  1. Two-way data binding:

    PRTCL // HTML
    <input ng-model="username">
    <h1>Hello, {{ username }}</h1>

    You type in the input and the text in the <h1> below changes in real time
    Without writing a single line of JS event listener code That was plain magic at the time

  2. Dependency injection: Want to use the $http service? Just write it in the function parameters and Angular hands it to you automatically

AngularJS turned HTML into a template language. It multiplied development efficiency tenfold
For a while, the whole world was rewriting projects in Angular. Frontend engineers felt they were finally developing software instead of writing scripts

7.4 AMD vs CMD#

While Node.js and frameworks were exploding, one fundamental problem remained unsolved: the JavaScript language itself had no module system (until ES6)

How do I reference one JS file from another? The <script> tag was not only ugly, but dependency order was hard to manage (jquery.js had to come before plugin.js)

So community standards were born:

  • CommonJS: the standard Node.js uses (require/module.exports). It loads synchronously, which suits servers but not browsers (network requests mean waiting)
  • AMD (RequireJS): Asynchronous Module Definition. define(['dep1'], function(dep1) { ... }). It was the ruler on the browser side
  • CMD (SeaJS): a standard proposed by Taobao’s 玉伯, closer to CommonJS’s writing habits (dependencies declared near where they’re used)

This wasn’t just a technical battle; it was a battle for community influence

At this point, we had completed the initial accumulation for industrialization

  1. We had build tools and started developing like a proper army
  2. We had MVC frameworks and started separating data from views
  3. We had the mobile market, and our status rose to unprecedented heights

But AngularJS’s two-way binding ran into serious performance problems in large-scale applications
Meanwhile Facebook’s engineers were struggling with an app called Instagram. They thought the MVC pattern was wrong for frontend too
They proposed a more radical idea: what if the view is just a function?

8. React and the paradigm shift#

8.1 The heresy of JSX#

In 2013, when Facebook engineer Jordan Walke open-sourced React, the community’s reaction was fury
Some even said: this destroys ten years of our hard work

Why? Because of JSX
In the past, the best practice was separation of concerns: HTML for HTML (templates), JS for JS (logic)
React said: no, we’re putting HTML inside JS

React’s core insight was that UI rendering logic (event handling, state changes) and UI presentation logic (DOM structure) are essentially tightly coupled. Forcing them into separate files is only physical separation, not logical separation

JSX isn’t a template; it’s syntactic sugar for JavaScript. That means you have all the power of a Turing-complete language (variables, if/else, loops, functions) to describe the interface, instead of being limited to clunky template syntax (ng-repeat, v-if)

This was a revolution in thinking: we’re no longer writing pages, we’re writing components

8.2 Virtual DOM#

At the moment React was taking the most abuse, its performance saved it. Facebook had a hard problem: in an extremely complex feed, how do you update messages efficiently?
With jQuery, you had to manually find which DOM node changed; with Angular 1, it would frantically run dirty checking, causing the page to stutter

React proposed the Virtual DOM:

  1. Snapshot: every time state changes, I generate a new virtual DOM tree in memory (pure JS objects)
  2. Diff: I compare the old and new trees with an efficient algorithm (O(n)) to find even a single attribute change
  3. Patch: I apply only that tiny changed part to the real browser DOM

This was a victory of mathematics
React doesn’t even need to know the browser exists. It abstracts rendering into a function: UI = f(State)
Change the state and the UI changes automatically. Developers never have to touch document.getElementById again. Manual DOM manipulation became history

8.3 Redux, the ascetic#

React only solved the View. What about data?
Facebook proposed the Flux architecture, which Dan Abramov later simplified into Redux

Redux was extremely tedious: Action, Reducer, Store, Dispatch. Changing one field meant writing four files
Why were we torturing ourselves like this?

Because in large applications, predictability matters more than convenience

  • One-way data flow: data only flows downward
  • Pure functions: reducers must be pure, the same input always yielding the same output
  • Rewind: because state is immutable, you can roll back to any earlier state at any time

Redux cured the chaotic state management of the MVC era, at the cost of a ton of boilerplate


9. Vue’s progressive philosophy#

9.1 Evan You’s subtraction#

Just as React was trying to educate the world with functional programming, a former Google employee named Evan You was thinking: is there a way to get both Angular’s template convenience and React’s virtual DOM performance?

In 2014-2015, Vue.js took off
Its core philosophy was progressive

  • Want to drop it in via CDN for a small widget? Sure, use it like jQuery
  • Want a single-page app? Sure, bring in Vue Router and Vuex
  • Want a large-scale project? Sure, bring in Vue CLI

Vue didn’t force you to learn JSX; it kept HTML templates. This made countless developers who came from the HTML/CSS/jQuery era feel warmth. In Greater China, Vue became the absolute ruler

Stacking armor: I used “Greater China” purely out of personal habit — don’t flame me if you don’t like it

9.2 The reactive magic of Object.defineProperty#

The most fascinating part of Vue 2.0 was its reactivity system It used ES5’s Object.defineProperty (getters/setters)

  • When you pass an object to Vue’s data, Vue walks all its properties and turns them into getters/setters
  • When a component renders and reads a property, Vue records that this component depends on that property
  • When the property changes (the setter is called), Vue notifies every component that depends on it to update

This was more efficient than Angular 1’s dirty checking and more automated than React’s manual setState. It was magic, but for most developers, a happy kind of magic

10. The Tower of Babel of builds#

10.1 Webpack alchemy#

In this period, the file frontend engineers hated most was probably webpack.config.js
As SPAs spread, a project might have hundreds of JS files, dozens of CSS files and hundreds of images

Webpack stepped up and said: in my eyes, everything is a module

  • JS is a module, CSS is a module (import './style.css'), images are modules (import img from './logo.png')
  • Loader: a transformer that turns Sass into CSS, ES6 into ES5, images into Base64
  • Plugin: the butler, handling code minification, code splitting and injecting environment variables

Webpack was extremely powerful and extremely complex. It even gave birth to a new job title: Webpack configuration engineer
But it was also Webpack that finally gave frontend an industrial-grade build pipeline. At last we could do Tree Shaking (shaking the tree to remove unused code) and on-demand loading

10.2 Let’s live in the future#

In June 2015, ES6 (ECMAScript 2015) was officially released
It was the biggest update since JavaScript was born: class, module, arrow function, promise, const/let
JS finally looked like a proper language

But browsers (especially the villainous IE) didn’t support it
Babel (formerly 6to5) appeared

It’s a compiler. It reads ES6 code in, converts it into equivalent ES5 and spits it out
That means: frontend developers are no longer limited by the user’s browser version
We can write code with 2026’s syntax standard and run it on a 2010 browser through Babel

This was a huge boost to frontend’s confidence: we controlled the language’s development

10.3 TypeScript’s prodigal return#

Around 2018, as projects broke the million-line mark, weakly typed JS became the biggest hidden danger
”Cannot read property ‘x’ of undefined” was the culprit behind every production incident

Microsoft’s TypeScript finally had its day

  • It’s a superset of JS
  • It brought static type checking
  • It brought extremely powerful IDE IntelliSense

At first, everyone found writing types a hassle (turning TS into anyScript
but when you’re refactoring a five-year-old component and the IDE tells you exactly where it breaks, you’ll kneel down and thank TypeScript
No TS, no frontend gradually became industry consensus

At this point, the four pillars of modern frontend were established:

  1. Component frameworks
  2. Type systems
  3. Build tools
  4. Modern syntax

We built a magnificent Tower of Babel
But the tower grew heavier and heavier
The node_modules folder became a black hole (well, not that light). An npm install took 5 minutes, an npm run build took 3 minutes (well, not that fast)
SPA first-screen loads got slower and slower, and SEO remained a pain point

The pendulum of history was about to swing again
In pursuit of ultimate speed, we began to reflect: have we stuffed too much into the browser?

11. The static revival#

11.1 The cost of SPAs#

From 2016 to 2019, if you weren’t doing SPAs, you were embarrassed to call yourself frontend
But when the whole world was writing web pages in React, the problems showed:

  1. TTFB: for a user to open the page, they first had to download a multi-megabyte JS bundle; only after the browser parsed it could the first line of text render. On a 3G network, that meant 5-10 seconds of white screen
  2. SEO drops to zero: Google’s crawler can execute JS, but Bing’s or Baidu’s crawlers often come up empty. For news and e-commerce sites, being unsearchable is death

The myth of CSR was shattered

11.2 Next.js and Nuxt#

Vercel (the company behind Next.js) stepped up
Their idea was simple: if rendering in the browser is slow, why not go back to rendering on the server?

  • Isomorphic rendering:
    • The user’s first visit: the server runs the React code, generates an HTML string and returns it directly
    • Subsequent clicks: the browser takes over and it becomes an SPA

This sounds a lot like PHP/JSP in 1998, but the difference is: frontend and backend are one codebase (all JS/TS). Frontend engineers took back control of rendering while also keeping performance in mind

11.3 Static generation#

For blogs, docs and marketing pages, the content doesn’t change once in a blue moon — why compute it again on every request?
Gatsby and Next.js popularized SSG

  • Build time: on the developer’s computer, React compiles 1,000 blog posts into 1,000 .html files
  • Distribution: toss them onto a CDN
  • Access: when a user visits, they fetch a static file from the nearest CDN node. That’s the fastest speed the laws of physics allow

We went full circle back to Web 1.0’s static file model — but the things producing those files are Web 4.0’s automated pipelines


12. Hydration and the art of deception#

12.1 The uncanny valley effect#

SSR and SSG brought a new problem: “watering”
When the server returns HTML, the page looks finished, and the buttons are right there
The user impatiently clicks a button: nothing happens

Why? Because the JS hasn’t finished downloading and the event listeners haven’t been attached yet.
This period is called the uncanny valley. The user thinks it’s alive, but it’s actually dead

This is modern frontend’s biggest pain point: to let users see content sooner, we not only send HTML, we have to send an identical copy of JS to activate it. The data goes over twice

12.2 Island architecture#

In 2021, Astro asked a soul-searching question:
My blog posts are static — why am I loading the React library to render them?

Astro’s answer was 0 JS

  • The whole page is pure HTML
  • Only the comment section component and the like button are React components
  • The browser only loads the JS for those two little islands

This was a rebellion against the React suite. It marked frontend’s turn toward fine-grained loading. We no longer stuff an elephant into the fridge; we just put in a few bananas

This is also one of the reasons I personally like Astro so much

12.3 Edge computing#

Today’s backend is no longer just a server in a data center, but Edge Functions spread across the globe
Vercel / Cloudflare Workers let frontend engineers write a piece of JS and deploy it to 200 cities worldwide

The user’s request is routed to the nearest node, where a tiny V8 environment is waiting for it
The boundaries of the frontend engineer have extended to the very edge of the network

13. The dimensional strike on toolchains#

13.1 Vite blitzes frontend#

In 2020, Evan You (him again) released Vite
Webpack’s pain point at the time: starting the dev server for a large project meant waiting 30 seconds or even a minute, because Webpack had to bundle every file

Vite: browsers support import now — why bundle at all?

  • No-Bundle development: Vite does almost nothing at startup. It compiles whichever file you request. Startup time: 300ms
  • This huge difference in experience let Vite devour Webpack’s market share like a virus

13.2 The invasion of Rust and Go#

Vite is built on esbuild (written in Go)
Next.js is built on SWC / Turbopack (written in Rust)

Frontend toolchains are undergoing a dimensional strike.

  • Before: compilers for JS written in JS (Babel, Terser). Slow, single-threaded
  • Now: compilers for JS written in systems languages (Rust/Go). Fast, multicore parallel
  • Result: build speed improved by 10x to 100x

This marks a massive raise in the bar for frontend infrastructure. Before, knowing JS was enough to build a wheel; now you need to understand Rust and memory management

13.3 The atomization of CSS: Tailwind CSS#

In the styling world, a war of taste and bad taste has ended. Tailwind CSS won

It looks a lot like inline styles from 1999: <div class="flex items-center justify-between p-4 bg-blue-500">
Many people found it hideous at first sight
But after a while it feels amazing:

  • No class names to invent: no more agonizing over names like container-inner-wrapper
  • No dead code: the CSS file no longer grows without limit
  • Design system: colors and spacing are all standardized

It changed frontend’s muscle memory for writing styles

14. Frontend is dead, long live frontend#

14.1 The return of full-stack#

React introduced RSC
You can write SQL to query the database directly in a React component:

PRTCL // JAVASCRIPT
// This runs on Server
async function UserList() {
const users = await db.query('SELECT * FROM users');
return <div>{users.map(u => <p>{u.name}</p>)}</div>;
}

The boundary between frontend and backend has blurred completely (though this also gave rise to even more outrageous problems
Frontend engineers are no longer slicers, nor API consumers
We’re becoming product engineers. One person can build a complete, high-performance application

14.2 AI#

In 2023, ChatGPT and other companies’ LLMs arrived. Write a centered layout? Write a regex validation? Write a complex reducer?
AI generates it in a second

Has the bar for frontend development gone down or up?

  • The bar for low-level code has disappeared. AI writes it faster than you, and these are exactly the people AI replaces
  • The bar for system architecture has gone up. You need to understand SSR, hydration, databases, security and all sorts of other things to direct AI in assembling a good product

14.3 The next thirty years#

Looking back over these thirty years:
From <table> layouts in 1990 to Rust-compiler-driven Edge SSR in 2025

  • We once moved everything into the browser for movement
  • Now we move everything back to the server for speed

History is not a simple circle but a tower spiraling upward
We’ve returned to the server, but we brought back componentization, declarative programming and an extreme engineering system

The Web is still young
As long as humans still need to interact with the digital world through screens, the mission of the frontend engineer will never end

15. Conclusion#

And so we’ve run through the Romance of the Three Kingdoms that belongs to frontend
We started with Tim Berners-Lee’s scratch paper and came all the way to today
This is the story of countless developers fighting the browser, compromising with it, and finally taming it

And we’ve also come to understand:
Why do we have to learn so many messy tools?
Because we took a pile of paper originally meant for wiping your ass, and through decades of stacking buffs, forcibly built a skyscraper out of it

Chongxi
CHONGXIAuthor
Steam—
Spotify—
Published at:2026.02.08
Classified
Distribution Notice

36 Years in Review: A History of Internet Frontend Development

Author CHONGXI/2026.02.08/CEPATO-2026-0208-HISTOR

This work is licensed under CC BY-NC-SA 4.0. Redistribution, remixing and adaptation are allowed for non-commercial use, provided the same license is used and the original author is credited.

SubscribeDonate
Discussion
Archive_Ref
Copyright © 2011–2026 Chongxi & CEPATO
Powered by Astro & CEPATO-NEXT
StatusNon-Collaborative_Entity // CEPATO_NEXT_v27.0

Type a keyword to search