Understanding Single Page Applications
Understanding Single Page Applications explains SPA navigation, client-side routing, the History API, API communication, state, performance, SEO, accessibility, security, deployment fallbacks, and enterprise architecture.
Understanding Single Page Applications
Learning Objectives
By the end of this lesson, you will be able to:
- Understand what a Single Page Application (SPA) is.
- Understand how an SPA differs from a traditional multi-page application.
- Understand the role of React in building SPAs.
- Understand the browser navigation lifecycle in an SPA.
- Understand client-side routing.
- Understand how URL changes can happen without a full page reload.
- Understand the role of the History API.
- Understand SPA navigation and rendering.
- Understand API communication in an SPA.
- Understand SPA authentication and session handling at a high level.
- Understand SPA advantages and limitations.
- Understand SEO, performance, and accessibility considerations.
- Understand SPA deployment requirements.
- Understand common SPA architecture patterns.
- Explain SPAs confidently in senior-level interviews.
Introduction
We have already learned:
React↓Project Setup↓Vite↓Folder Structure
Now we need to understand an important architectural concept:
What exactly is a Single Page Application?
React is commonly used to build SPAs, but:
React itself does not automatically make an application a SPA.
React is a UI library.
A SPA is an application architecture and navigation model.
A useful mental model is:
Single Page Application│┌───────────┼───────────┐▼ ▼ ▼Browser React API│ │ │└───────────┼───────────┘▼Dynamic UI
What Is a Single Page Application?
A Single Page Application, or SPA, is a web application where the browser initially loads an application shell and subsequent navigation and data interactions generally happen without requesting a completely new HTML document for every route.
Instead of:
Click link↓Request new HTML document↓Browser reloads page↓New page displayed
a SPA generally works like:
Click link↓Client-side router↓URL changes↓React renders another view↓API requests data if necessary↓UI updates
The important idea is:
The browser stays within the same running application while the visible UI changes.
Traditional Multi-Page Application
Before understanding SPA architecture, let's understand the traditional model.
Imagine a website with:
HomeProductsAboutContact
A traditional server-rendered application might work like this:
Browser││ GET /▼Server│▼HTML│▼Browser
Then the user clicks:
Products
The browser makes another request:
Browser││ GET /products▼Server│▼New HTML│▼Browser reload
The process repeats for every page.
Traditional MPA Architecture
This is commonly called a Multi-Page Application (MPA) model.
Browser│┌─────────┼─────────┐│ │ │▼ ▼ ▼GET / GET /about GET /products│ │ │└─────────┼─────────┘▼Server│┌─────────┼─────────┐▼ ▼ ▼HTML HTML HTML
Each navigation can involve a new document request.
SPA Architecture
A SPA generally starts differently.
The browser requests the application:
Browser│▼Application HTML│▼JavaScript│▼React Application
After that:
User interaction│▼Client-side routing│▼React changes UI│▼API request if required│▼UI updates
The browser doesn't need to download an entirely new HTML document for every application route.
SPA Mental Model
Think of the application as:
Browser│▼Application Shell│▼React│┌──────────────┼──────────────┐▼ ▼ ▼Home Courses Dashboard│ │ │└──────────────┼──────────────┘▼Backend APIs
The shell remains active while React changes the content being displayed.
Is There Really Only One Page?
This causes confusion.
A SPA can have URLs such as:
//courses/courses/react/dashboard/profile/settings
These look like separate pages.
But from the browser's document perspective, the application can still operate within a single loaded document.
So:
"Single Page"
does not mean:
Only one screen exists.
It means:
The application generally operates inside one loaded document rather than loading a completely new HTML document for every navigation.
SPA Navigation
Suppose the user is currently at:
/courses
They click:
React Course
The target is:
/courses/react
A SPA can handle this client-side:
User clicks│▼Router intercepts navigation│▼URL changes│▼React determines matching route│▼CourseDetails component│▼API request│▼Course data│▼UI renders
No complete browser document reload is necessary.
Client-Side Routing
This is one of the most important concepts in SPAs.
A client-side router maps:
URL↓React Component
For example:
/ → HomePage/courses → CoursesPage/courses/react → CourseDetailsPage/dashboard → DashboardPage/profile → ProfilePage
Conceptually:
URL│▼Router│├── /│ └── HomePage│├── /courses│ └── CoursesPage│└── /dashboard└── DashboardPage
We'll study React Router separately later.
React Does Not Provide Routing by Itself
This distinction is important.
React provides:
ComponentsRenderingStateHooksUI composition
Routing is a separate concern.
A React application can use:
React Router
or another routing solution/framework.
Therefore:
React+Router=Client-side navigation
Browser History API
Client-side routing commonly relies on browser capabilities such as:
history.pushState()history.replaceState()popstate
For example, conceptually:
history.pushState({},"","/courses/react");
The URL changes without asking the browser to load a completely new document.
Then the application responds to that navigation and renders the appropriate UI.
What Happens During Navigation?
Let's trace it carefully.
User clicks:
Courses
Step 1
The browser receives the user interaction.
Click↓Navigation handler
Step 2
The router determines the target route.
/courses
Step 3
The URL is updated.
/courses
Step 4
React renders:
CoursesPage
Step 5
The page may request data:
GET /api/courses
Step 6
React receives the data and updates the UI.
API Response↓State↓Render↓UI
Full SPA Request Flow
A real application might work like this:
Browser│▼React Application│┌──────┴──────┐▼ ▼Router Components│ │└──────┬──────┘▼API Client│▼API Gateway│▼Spring Boot APIs│▼Database
The frontend and backend are often separated.
SPA + REST API
A common enterprise architecture is:
Browser│▼React SPA││ HTTPS▼API Gateway│┌────────┼────────┐▼ ▼ ▼User API Course API Payment API│ │ │└────────┼────────┘▼Data Stores
This is particularly common for:
Enterprise dashboardsBanking applicationsLearning platformsAdmin portalsCustomer portalsInternal tools
SPA vs Traditional MPA
| Area | SPA | MPA |
|---|---|---|
| Navigation | Usually client-side | Usually server-driven |
| Document reload | Usually avoided | Common |
| UI updates | React/client application | Server-generated page |
| Initial JavaScript | Often larger | Often smaller |
| Routing | Client-side or framework-managed | Server-side |
| API usage | Usually significant | Varies |
| User experience | Often app-like | Traditional web navigation |
| SEO | Requires careful architecture | Often straightforward |
| Complexity | Higher frontend complexity | More server-side navigation |
| Deployment | Static assets + APIs often possible | Typically server/application hosting |
Neither architecture is universally better.
The right choice depends on the application.
Why Developers Use SPAs
One major reason is the application-like user experience.
Imagine:
Dashboard
with:
SidebarHeaderNotificationsChartsTablesFilters
The user clicks:
Reports
A SPA can update the main content while keeping:
SidebarHeaderApplication state
alive.
This can feel much more like a desktop application.
SPA State
One major advantage of the SPA model is that the application can maintain client-side state across navigation.
For example:
User│▼Dashboard│├── Selected filters├── Sidebar state├── Notifications└── User session
Then the user navigates to:
Reports
Some application-level state can remain available.
However, don't assume all state should remain globally.
State ownership still matters.
SPA Doesn't Mean "No Server"
Another common misconception:
A SPA doesn't need a backend.
Incorrect.
A SPA often depends heavily on backend services.
For example:
React SPA│├── Authentication API├── Course API├── Payment API├── Search API└── Notification API
The SPA simply handles much of the user-interface and navigation behavior on the client.
SPA Authentication
A typical flow could be:
User│▼Login Page│▼Authentication API│▼Authentication Result│▼Client Application│▼Authenticated UI
Modern applications need to carefully design:
AuthenticationAuthorizationToken/session handlingCSRFXSSSecure storageLogoutToken expiration
We'll study these topics separately.
SPA Loading Lifecycle
When the user first opens the application:
Browser│▼HTML│▼JavaScript│▼React Initialization│▼Initial Render│▼API Calls│▼Data Render
This is called the initial application load.
Afterward, navigation can happen without a complete document reload.
Initial Load vs Subsequent Navigation
This distinction is extremely important.
Initial load
Browser↓HTML↓JS/CSS↓React startup↓Initial UI
Subsequent navigation
Click↓Router↓URL↓React↓New UI
The initial load can be expensive if the application ships too much JavaScript.
SPA Performance Challenge
A SPA can become large:
React Application│├── Authentication├── Courses├── Dashboard├── Reports├── Admin├── Analytics└── Payments
If all code is downloaded immediately:
Initial JavaScript↓Very large↓Slow initial load
This is why techniques such as:
Code splittingLazy loadingTree shakingCachingCompressionImage optimization
are important.
We'll study these later.
Code Splitting
Instead of downloading everything:
Initial Load│├── Home├── Dashboard├── Admin├── Reports└── Payments
we can split:
Initial Load│└── HomeLater├── Dashboard├── Admin├── Reports└── Payments
Conceptually:
main.jscourses.jsdashboard.jsadmin.jsreports.js
The user downloads code when it becomes relevant.
Lazy Loading
Suppose:
/admin
is rarely visited.
There's little reason to load the entire Admin feature for every user on the homepage.
Instead:
User opens /│▼Load Home
Later:
User opens /admin│▼Load Admin bundle
This can significantly improve initial loading behavior for large applications.
SPA and SEO
One of the common concerns about traditional client-rendered SPAs is SEO.
Suppose the initial HTML contains:
<div id="root"></div>
and most meaningful content appears only after JavaScript executes.
Search engines have become much better at processing JavaScript, but relying exclusively on client-side rendering can still introduce challenges involving:
CrawlingRenderingMetadataPerformanceSocial sharingIndexing
For public, content-heavy applications, rendering strategies should be considered carefully.
SPA vs SSR
A client-rendered SPA commonly works like:
Browser↓HTML shell↓JavaScript↓React renders
Server-side rendering (SSR) can work more like:
Browser↓Server↓HTML with content↓Browser↓React becomes interactive
This can improve initial content delivery and SEO characteristics for certain applications.
But SSR introduces additional architectural complexity.
SPA vs SSG
Another approach is:
Static Site Generation (SSG)
Pages can be generated ahead of time:
Build Time↓Generate HTML↓Deploy↓User
This can work particularly well for:
DocumentationBlogsMarketing pagesCourse contentStatic websites
A modern React architecture can combine different rendering strategies depending on the page.
Not Every React Application Should Be a Pure SPA
This is an important senior-level insight.
You may have:
Public Website+Authenticated Dashboard
The public website might benefit from:
SSR / SSG
while the dashboard might work very well as:
SPA
So the architectural decision doesn't always have to be:
SPA OR React
It can be:
React application│├── Public content → rendering optimized for SEO│└── Dashboard → SPA-like experience
SPA Deployment
A common SPA deployment architecture is:
User│▼CDN / Web Server│▼React Static Assets│▼Browser Runtime││ API▼API Gateway│▼Backend Services
The React application can be built into static files:
dist/├── index.html└── assets/
These can be served by infrastructure such as:
CDNWeb serverObject storage + CDNContainer
SPA Routing Deployment Problem
This is a very important real-world issue.
Suppose the application supports:
/courses/react
The user opens that URL directly.
The browser sends:
GET /courses/react
to the web server.
But the server may look for:
courses/react
as a physical file.
It doesn't exist.
Result:
404
even though React knows the route exists.
SPA Fallback
The server must often be configured so that unknown application routes fall back to:
index.html
Conceptually:
GET /courses/react│▼Web Server│├── Static asset? → Serve asset│└── Application route?│▼index.html│▼React│▼/courses/react│▼CourseDetailsPage
This is essential for many client-side routed SPAs.
Example with Nginx
Conceptually, an Nginx deployment may use a fallback similar to:
location / {try_files $uri $uri/ /index.html;}
This tells the server:
If the requested file exists→ serve itOtherwise→ serve index.html
Then React's router can handle the route.
The exact production configuration depends on your hosting architecture.
SPA Error Handling
There are several types of errors.
Browser/Application error
React component crashes
API error
GET /api/courses↓500
Route error
/courses/invalid
Deployment error
Direct URL↓Server 404
A mature SPA needs strategies for each category.
SPA Architecture With Spring Boot
Since enterprise React applications often communicate with Java backends, consider:
Browser│▼React SPA│┌────────┴────────┐│ │Router API│ ││ ▼│ API Gateway│ ││ ┌────────┼────────┐│ ▼ ▼ ▼│ Auth Course Payment│ Service Service Service│ │ │ ││ └────────┼────────┘│ ▼│ Databases│▼Browser UI
This is a common enterprise architecture.
SPA and Microservices
A SPA does not mean:
One frontend=One backend
The frontend can consume multiple services.
For example:
React│├── /api/users├── /api/courses├── /api/payments├── /api/notifications└── /api/search
These could be backed by:
User ServiceCourse ServicePayment ServiceNotification ServiceSearch Service
Usually an API gateway or backend-for-frontend layer helps manage this complexity.
SPA and BFF
A Backend for Frontend (BFF) can provide a frontend-specific API layer.
Instead of:
React├── User Service├── Course Service├── Payment Service├── Notification Service└── Search Service
you can have:
React│▼BFF│├── User Service├── Course Service├── Payment Service└── Notification Service
Benefits can include:
Simpler frontend APIAggregationSecurity boundaryFrontend-specific data shapingReduced client orchestration
But BFF introduces another service and operational responsibility.
SPA Advantages
1. App-like experience
Navigation can feel smooth.
2. Rich interactions
Complex interactions can happen without complete page reloads.
3. Client-side state
The application can maintain state across navigation.
4. Separation
Frontend and backend can evolve independently.
5. Reusable UI
React components can be reused extensively.
6. API-driven architecture
The same backend APIs can potentially support:
WebMobileOther clients
SPA Disadvantages
SPAs aren't free.
1. Larger JavaScript payload
The initial application may require significant JavaScript.
2. More frontend complexity
You need to manage:
RoutingStateCachingAuthenticationErrorsLoadingCode splitting
3. SEO considerations
Public content requires careful rendering and metadata strategies.
4. Initial load
The application needs to bootstrap before full interactivity.
5. Browser dependency
More application logic runs on the client.
6. Deployment complexity
Routing fallback must be configured correctly.
SPA Accessibility
A SPA must not sacrifice accessibility.
When navigation happens without a full document reload, developers need to consider:
Focus managementDocument titleScreen reader announcementsKeyboard navigationARIABack/forward navigationLoading states
For example, when navigating to:
/courses/react
the application should ensure that:
Page titleFocusHeading structureScreen reader context
make sense.
SPA Browser Back Button
The browser back button must work naturally.
Suppose:
/↓/courses↓/courses/react↓/dashboard
Press Back:
/dashboard↓/courses/react
Press Back:
/courses/react↓/courses
The client-side router should integrate with browser history so navigation behaves as users expect.
SPA Loading States
API-driven SPAs must handle loading states.
For example:
CoursesPage│▼Loading...│▼API response│▼Course list
But also:
LoadingErrorEmptySuccess
A production component often needs to handle all four.
Data State│├── Loading├── Error├── Empty└── Success
This is a fundamental SPA design pattern.
SPA Data Caching
Suppose the user visits:
/courses
The application fetches:
GET /api/courses
Then they navigate to:
/courses/react
and later return to:
/courses
Should we request the data again?
Not necessarily.
A client-side data layer can use caching:
API│▼Client Cache│├── courses├── course/react└── profile
This can improve responsiveness and reduce unnecessary requests.
Libraries such as TanStack Query can help with server-state management, though we'll cover this separately.
SPA State Categories
A mature application should distinguish between different kinds of state.
State│├── Local UI State│├── Global Client State│├── Server State│└── URL State
Examples:
Local
Modal open
Global
Theme
Server
Course data
URL
?page=2&search=react
Not everything belongs in Redux or another global store.
URL as Application State
Suppose the user searches:
/courses?search=react&page=2
The URL now contains application state:
search = reactpage = 2
This has important advantages:
ShareableBookmarkableBack-button friendlyRefresh-friendly
URL state is especially valuable for:
SearchFiltersPaginationSortingTabs
SPA Security Considerations
A SPA should be designed with browser security in mind.
Important concerns include:
XSSCSRFAuthenticationAuthorizationToken handlingCORSContent Security PolicySecure cookiesDependency security
Never assume:
Client-side route protection=Security
For example:
/admin
being hidden by the React router doesn't prevent someone from directly calling:
POST /api/admin/users
The backend must enforce authorization.
This is a critical enterprise principle:
Frontend authorization improves user experience; backend authorization provides the security boundary.
Client-Side Route Guards
You may have:
/admin
and only authenticated users should see it.
The frontend can implement:
Authenticated?│├── Yes → Admin│└── No → Login
But the backend must still enforce:
Authenticated?Authorized?Role allowed?Permission allowed?
Never trust the browser.
SPA Monitoring
Production SPAs need observability.
Monitor:
JavaScript errorsAPI errorsPage load performanceRoute transitionsUser interactionsFailed network requestsCore Web Vitals
For enterprise applications, this can integrate with:
Application MonitoringLoggingTracingAnalyticsError tracking
A frontend application is a production system and should be observable accordingly.
Practical Exercise
Create a simple SPA with:
//courses/courses/react/about
Architecture:
src/├── app/│ └── routes/│├── pages/│ ├── HomePage.tsx│ ├── CoursesPage.tsx│ ├── ReactCoursePage.tsx│ └── AboutPage.tsx│├── components/│ └── Navigation.tsx│└── main.tsx
Navigation:
Home | Courses | About
Clicking the links should update the URL and displayed view without a complete browser document reload.
This exercise will prepare you for the dedicated routing lessons.
Interview questions & answers
Interview preparation
15 questions grouped by difficulty — expand any card for a model answer and follow-up probe.
Beginner
1What is a Single Page Application?
BeginnerModel answer
A SPA is a web application where the browser initially loads the application and subsequent navigation generally updates the UI client-side without loading a completely new HTML document for every route.
2Is React itself a SPA?
BeginnerModel answer
No.
React is a UI library.
React can be used to build SPAs, but SPA behavior also involves routing, application architecture, and client-side navigation.
3What is client-side routing?
BeginnerModel answer
Client-side routing maps browser URLs to application views or components without requiring a complete document reload for each navigation.
4What is the difference between SPA and MPA?
BeginnerModel answer
A SPA generally maintains one running application and changes views client-side, while an MPA commonly requests and loads a new HTML document when navigating between pages.
Intermediate
5How does SPA navigation work?
IntermediateModel answer
A router intercepts or manages navigation, updates browser history and the URL, determines the matching route, and renders the corresponding React component.
The component can then request the required backend data.
6What is the History API?
IntermediateModel answer
The browser History API provides mechanisms such aspushState,replaceState, andpopstatethat allow applications to manage browser history and URLs without necessarily triggering a full document navigation.7Why does a SPA need a server fallback?
IntermediateModel answer
If a user directly requests a client-side route such as/courses/react, the web server may look for a physical resource at that path. If it doesn't exist, the server could return 404. A typical SPA deployment configures a fallback toindex.html, allowing the client-side router to handle the route.8What is code splitting?
IntermediateModel answer
Code splitting divides application JavaScript into multiple chunks so that users don't have to download the entire application upfront.
Additional chunks can be loaded when specific features or routes are needed.
Advanced
9What are the advantages of a SPA?
AdvancedModel answer
SPAs can provide smooth navigation, rich interactions, persistent client-side state, reusable UI components, and clean separation between frontend and backend APIs.
They're particularly useful for application-like experiences such as dashboards and enterprise portals.
10What are the disadvantages?
AdvancedModel answer
They can have larger initial JavaScript payloads, more frontend complexity, additional SEO considerations, and more complex deployment requirements around routing.
Performance also depends heavily on how the application handles code splitting, caching, rendering, and data fetching.
11How would you improve SPA performance?
AdvancedModel answer
I'd measure first, then consider route-level code splitting, lazy loading, caching, bundle analysis, tree shaking, efficient data fetching, image optimization, compression, CDN delivery, and minimizing unnecessary rendering.
I'd also monitor Core Web Vitals and real-user performance.
12Would you choose SPA for every React application?
AdvancedModel answer
No.
I'd evaluate the application's requirements.
A complex authenticated dashboard is a strong SPA candidate.
A public content-heavy website may benefit from SSR or static generation for initial performance and SEO.
A modern React architecture can also combine different rendering strategies.
13How would you architect a large enterprise SPA?
AdvancedModel answer
I'd define clear feature boundaries, separate shared UI from business-specific code, establish routing and state-management conventions, isolate API communication, implement authentication and authorization correctly, introduce code splitting, establish observability, and define CI/CD and deployment fallback behavior.
14How would you secure a SPA?
AdvancedModel answer
I'd treat the browser as an untrusted environment.
Authentication and authorization would be enforced server-side.
On the frontend I'd implement secure session handling, protect against XSS and CSRF as applicable, use secure cookies where appropriate, enforce HTTPS, apply Content Security Policy, validate API responses, and avoid putting secrets in client-side code.
15How would you handle a SPA with 100+ routes?
AdvancedModel answer
I would organize routes by business domain, use route-level lazy loading and code splitting, establish authorization boundaries, centralize route configuration where appropriate, define consistent loading and error states, and ensure the deployment infrastructure supports SPA fallback routing.
Real-World Architecture Question
Question:
We have a React SPA with 1,000+ records returned by the backend. How would you design it?
A strong answer is:
Backend│▼Pagination / Filtering / Sorting│▼React API Layer│▼Server-State Cache│▼Virtualized / Paginated UI│▼Browser
You shouldn't blindly render 1,000+ complex DOM elements.
Consider:
Server-side paginationFilteringSortingVirtualizationCachingIncremental loading
This connects directly with the kind of enterprise React performance questions you may encounter in interviews.
SPA Architecture Checklist
For a production SPA, consider:
Architecture├── Routing├── State management├── API layer├── Authentication├── Authorization├── Error handling├── Loading states├── Code splitting├── Caching├── Accessibility├── SEO strategy├── Security├── Monitoring├── Testing└── Deployment
A SPA is much more than:
React + Router
Final Mental Model
Keep this architecture in mind:
USER│▼BROWSER│▼React SPA Shell│┌───────────┼───────────┐▼ ▼ ▼Router State UI│ │ │└───────────┼───────────┘▼API Layer│▼API Gateway│┌───────────┼───────────┐▼ ▼ ▼Auth API Course API Payment API│ │ │└───────────┼───────────┘▼Data Stores
And remember the navigation flow:
User Click↓Router↓URL / History↓React Component↓API / Cache↓State↓Render↓Updated UI
The most important principle is:
A Single Page Application is not simply a React application with multiple components. It is an application model where a long-running client application manages navigation, UI state, and interactions while communicating with backend services without requiring a full document reload for every user action.
Next Lesson
How React Renders the UI
Next we'll go one level deeper into what actually happens after React receives your component:
Component↓JSX↓React Element↓Render↓Reconciliation↓Commit↓DOM↓Browser Paint
We'll also introduce the Virtual DOM, reconciliation, rendering phases, and why React doesn't simply "rewrite the HTML" every time state changes.