Over the years, I have worked on projects using SPA. One thing has become increasingly clear to me: the web development community's love affair with Single-Page Application (SPA) has led us to overcomplicate many projects that could be simpler, faster, and more accessible.
This isn't another "React vs Angular vs Vue" debate. Rather, it's an invitation to step back and reconsider our fundamental approach to building for the web in 2025.
The SPA Dominance: How We Got Here
When I started my career, SPA were revolutionary. The promise was enticing: rich, desktop-like experiences delivered through the browser. Frameworks like React, Angular, and Vue made it possible to build complex interfaces with relatively clean code organization.
SPA quickly became the default choice for new projects. Job listings demanded React experience. Bootcamps centered their curricula around these frameworks. Conference talks assumed SPA as the baseline.
But somewhere along the way, we stopped asking a crucial question: is this approach actually the best fit for what we're building?
I recently planned to create a blogging website and the first question unconsciously showed in my mind was "Angular or React?". Only after a while, I realize it should not be about frameworks. This mindset reflects how thoroughly SPA thinking has permeated our industry.
First Principles: What Are We Really Trying to Accomplish?
User Needs vs. Developer Convenience
When I strip away assumptions and return to first principles, I always come back to this: what do users actually need?
Users need websites that:
- Load quickly
- Work reliably
- Are accessible to everyone
- Accomplish their goals with minimal friction
They don't care about our component architecture, state management solutions, or build pipelines. They don't benefit from our hot module reloading during development.
Yet so much of our framework choice discussion centers on developer experience rather than user experience. I've been guilty of this myself—choosing tools because they make my workflow more pleasant, not because they deliver the best end result.
The Interaction Spectrum
Not all web projects have the same requirements. I find it helpful to think about a spectrum of interaction complexity:
Static Content: When Simple HTML Wins
For content-focused websites—blogs, marketing sites, documentation—the interaction model is primarily:
- User requests a page
- Server returns the complete HTML
- User reads/consumes content
- User clicks to another page, returning to step 1
For these cases, generating static HTML (whether at build time or request time) often provides the best performance. A framework like Astro, 11ty, or even a traditional CMS can deliver lightning-fast experiences without shipping a single line of JavaScript to the browser.
Partial Interactivity: The Sweet Spot
Many web applications fall into a middle ground—mostly content-focused with some interactive elements:
- Forms with validation
- Filtering and sorting interfaces
- Cart/checkout flows
- Comment sections
These interactions benefit from JavaScript but don't necessarily require a full SPA architecture. This is where approaches like HTML-over-the-wire (HTMX, Hotwire, etc.) or the "islands architecture" really shine.
Full Interactivity: When SPA Make Sense
I'm not anti-SPA. For truly application-like experiences with complex state management needs, SPA remain appropriate:
- Data dashboards with real-time updates
- Complex editing interfaces (like Figma or Google Docs)
- Applications with offline functionality requirements
- Interfaces with constant user interaction and minimal page transitions
The Technical Foundations
Rediscovering HTML's Power
HTML has evolved significantly since SPA gained popularity. Elements like <dialog>
, <details>
, and improved form controls handle interactions that once required JavaScript. Semantic HTML also provides accessibility benefits that custom JavaScript components often miss.
I've caught myself reaching for JavaScript solutions when HTML already provides what I need:
<!-- Instead of a JavaScript-powered accordion -->
<details>
<summary>Click to expand</summary>
<p>This content appears when expanded.</p>
</details>
CSS: More Capable Than Ever
Modern CSS can handle animations, transitions, layout challenges, and even some interactive behaviors that previously required JavaScript:
- Grid and flexbox for complex layouts
- CSS variables for theming
@media
and@container
queries for responsive design:has()
for parent selectors- Scroll-driven animations
JavaScript: Used Thoughtfully, Not Abundantly
JavaScript remains essential for web development, but I've learned to use it more judiciously:
- As an enhancement, not a requirement
- Loaded progressively as needed
- With performance budgets in mind
This approach of progressive enhancement ensures that core functionality works even when JavaScript fails or is slow to load—which happens more often than we'd like to admit, especially on mobile networks.
Performance Considerations
Core Web Vitals and Why They Matter
Google's Core Web Vitals have given us concrete metrics to assess user experience:
- Largest Contentful Paint (LCP): How quickly the main content loads
- First Input Delay (FID): How responsive the page is to user interaction
- Cumulative Layout Shift (CLS): How stable the layout is during loading
In my experience, SPA frameworks often struggle with these metrics out of the box, requiring significant optimization work. Server-rendered approaches tend to perform better initially, giving teams more breathing room before optimization becomes necessary.
The Real Cost of JavaScript
Every kilobyte of JavaScript has a cascading effect on performance:
- It must be downloaded
- It must be parsed and compiled
- It must be executed
- It consumes memory during execution
On low-end devices—which represent a significant portion of global web users—these costs are amplified. I've seen JavaScript-heavy sites take 10+ seconds to become interactive on budget Android phones, even with decent network conditions.
Modern Approaches to non-SPA Development
Several modern approaches are making non-SPA development more powerful and developer-friendly. Here are a few that have caught my eye:
Progressive Enhancement
Start with functional HTML and CSS, then layer on JavaScript for enhanced experiences. Tools like Alpine.js and Stimulus provide lightweight ways to add interactivity without a full framework.
Islands Architecture
Pioneered by frameworks like Astro, this approach allows you to embed interactive components (even from React or Vue) within otherwise static HTML. Each "island" of interactivity hydrates independently, minimizing JavaScript overhead.
HTML-Over-the-Wire
HTMX, Hotwire Turbo, and Laravel Livewire allow dynamic updates by sending HTML fragments over the network rather than JSON data. This approach provides SPA-like interactions while keeping rendering logic on the server.
Tools and Frameworks Supporting non-SPA Development
The ecosystem for non-SPA development has matured significantly:
- Static Site Generators: 11ty, Hugo, Jekyll
- Server-Side Frameworks with Rich Capabilities: Laravel, Ruby on Rails, Phoenix
- Islands Architecture: Astro, Marko
- HTML-Over-the-Wire: HTMX, Hotwire, Livewire
- Minimal JS Libraries: Alpine.js, Stimulus, Svelte
- Modern Build Tools: Vite, Parcel
Many of these tools provide developer experiences that rival SPA frameworks while producing more efficient output.
Conclusion: The Path Forward
I'm not going to abandon SPA altogether—they remain the right solution for certain use cases. What I am approaching is a more thoughtful, context-aware approach to choosing the architecture.
By returning to first principles and focusing on user needs rather than developer trends, we can make better technical decisions and create better experiences.
The web's fundamental technologies—HTML, CSS, and JavaScript—have evolved tremendously. Often, the simplest approach using these native capabilities will outperform complex framework solutions.
Before starting your next project, I encourage you to ask:
- What level of interactivity do users genuinely need?
- Could a simpler approach meet those needs with better performance?
- Am I choosing this technology for user benefit or developer familiarity?
The answers might lead you away from the SPA default and toward a solution that better serves your users and business goals.