Introduction
In the previous article, we saw how AJAX and jQuery transformed the web from a static, request-response model into something far more dynamic and interactive.
But as applications became more complex, the patchwork of jQuery plugins, imperative DOM manipulation, and scattered logic began to collapse under its own weight.
We needed more than snippets — we needed structure.
And that’s when Single Page Applications (SPAs) emerged.
What Is a Single Page Application?
A Single Page Application is a web app that:
- Loads a single HTML page initially
- Uses JavaScript to manage routing, rendering, and data updates
- Interacts with the server via APIs (typically JSON over HTTP)
- Avoids full-page reloads entirely
In SPAs, the browser becomes the runtime — not just the display layer.
The Core Shift
Here’s how responsibilities changed from the server to the browser:
Responsibility | Pre-SPA (AJAX/jQuery) | SPA Era |
---|---|---|
Routing | Server-side | Browser (client-side) |
Rendering | Mostly server | Fully in browser |
State Management | Minimal (forms, DOM) | Managed in JS memory |
Data Fetching | AJAX via jQuery | Fetch/XHR, usually via libraries like Axios |
UI Feedback | jQuery-driven | Built into components and state transitions |
The entire application now lived in the frontend.
What Changed in the Developer Experience?
SPAs came with JavaScript frameworks that introduced powerful new ideas:
Components
UI broken into small, reusable pieces with their own logic and state.
Virtual DOM & Declarative Rendering
Instead of manually changing the DOM, you define what the UI should look like, and the framework figures out how to update it.
Client-Side Routing
No more page reloads — frameworks like React Router handled in-browser navigation via the History API.
Frontend State Management
Libraries like Redux and Vuex managed complex client-side state and behavior.
Too Much jQuery → A Flood of Frameworks
jQuery gave us power — but it didn’t scale well for large apps.
Developers were:
- Manually selecting DOM elements
- Mutating UI based on state
- Writing spaghetti code with callbacks and inline logic
This chaos created a need for structure. And that sparked an explosion of libraries and frameworks:
- Backbone.js – gave structure to models, views, and routers
- Knockout.js – introduced declarative bindings with
data-bind
- AngularJS – provided two-way data binding and full app structure
- React – focused on component composition and one-way data flow
- Vue – blended simplicity with structure, quickly rising in popularity
All of these were answers to the same problem: “jQuery is powerful, but we need more discipline.”
Real-World Example: A Dashboard
In the SPA world, a dashboard doesn’t reload — it updates live:
- Clicking sidebar links doesn’t reload the page
- Data is fetched in the background and rendered instantly
- Modals, dropdowns, and forms all live in memory
- Entire layouts are reused and dynamically changed
Users now expect this level of smoothness by default.
But There Were Tradeoffs
Validation Became a Shared Responsibility
In traditional server-rendered apps, validation happened only on the backend. If you submitted a form with an invalid email or empty field, the server would reject it and send back an error.
In SPAs, users expected instant feedback.
That meant:
- The frontend had to validate inputs before submission (for speed and UX)
- The backend still needed to validate data (for security and correctness)
So now, validation logic was duplicated — in two different languages (JavaScript and PHP/Node/etc.). This made development more complex and error-prone, especially for teams trying to stay consistent.
SEO Suffered — And We Tried to Fix It
One of the biggest drawbacks of SPAs was SEO.
Traditional multi-page apps rendered HTML on the server, which search engines could easily crawl and index. But SPAs loaded a bare <div id="app">
and relied on JavaScript to build the UI — meaning crawlers saw an empty page.
This was a major problem for:
- Blogs
- Marketing sites
- E-commerce platforms
- Any public content that needed discoverability
Attempts to Solve It
To fix SEO in SPAs, developers tried several workarounds:
- Pre-rendering / Static Generation
For pages that don’t change often (like landing pages), tools like
prerender.io
, Gatsby, or Next.js's static generation would output plain HTML at build time. - Server-Side Rendering (SSR) Frameworks like Next.js (React), Nuxt.js (Vue), and Angular Universal allowed JavaScript apps to run on the server and return fully-rendered HTML to bots and users alike.
- Hydration After SSR or static generation, the frontend JS "hydrates" the page — attaching event listeners and reactivating interactivity. This gave the best of both worlds: SEO-ready HTML and dynamic UI.
- Dynamic Rendering for Bots Some teams set up logic to detect bots and serve them pre-rendered HTML, while serving SPAs to real users. This was hacky and error-prone, but sometimes necessary.
While these strategies helped, they added complexity, tooling overhead, and often performance issues. It became clear that SPAs weren’t always the right default — especially for content-first sites.
Backend Was Reduced to APIs
As the frontend took on more responsibility — rendering, routing, state, validation — the backend was pushed into the background.
Its new role:
- Serve static files (index.html, JS bundles)
- Provide RESTful APIs or GraphQL endpoints
- Handle authentication, data persistence, and server-side validation
The backend was no longer controlling the user experience — it was simply a data provider.
This shift birthed terms like:
- “Headless backend”
- “API-first architecture”
- “Frontend-heavy apps”
Why This Phase Matters
SPAs represent the peak of frontend-centric architecture. For nearly a decade, “modern web development” meant:
- Build everything in JavaScript
- Talk to APIs
- Ship bundles
- Hydrate the DOM
This mindset dominated tooling, frameworks, hiring, and user experience.
But now, the industry is shifting again — toward rebalancing responsibilities, improving performance, and rediscovering the power of HTML-first rendering.
Summary
SPAs changed the game by:
- Bringing full routing and rendering to the browser
- Making JavaScript the center of the web experience
- Ushering in a new era of frontend frameworks
But with that power came new problems — and that’s what set the stage for the next transition.
In Part 4, we’ll look at where the web is headed now — with server-first rendering, resumability, and a renewed focus on simplicity and speed.
If you found this post helpful, consider supporting my work — it means a lot.
