How Axios Handles SSR in Next.js and Nuxt
This article explains how the Axios HTTP client operates within Server-Side Rendering (SSR) architectures such as Next.js and Nuxt. It covers how Axios executes seamlessly across client and server environments through its isomorphic design, how to manage context-specific challenges like cookie forwarding and relative URLs, and the best practices for preventing cross-request data leaks on the server.
Isomorphic Execution and Adapters
Axios is an isomorphic (or universal) library, meaning identical code can run in both the browser and a Node.js server. It achieves this using platform-specific adapters:
- Node.js Environment (Server): Axios uses native
Node.js
httpandhttpsmodules to dispatch network requests. - Browser Environment (Client): Axios relies on the
XMLHttpRequestinterface (or the Fetch API in newer builds) to handle requests directly within the browser runtime.
When a page is rendered on the server in Next.js or Nuxt, Axios automatically switches to its Node.js adapter to fetch data before the final HTML is generated and sent to the client.
Handling SSR in Next.js
In Next.js, SSR data fetching occurs primarily within server-only
functions like getServerSideProps (Pages Router) or inside
React Server Components and Server Actions (App Router).
Absolute URLs Requirement
Node.js does not have an implicit origin (such as
window.location.origin). Because of this, relative
endpoints like /api/user will fail during server execution.
Requests must use fully qualified absolute URLs (e.g.,
https://api.example.com/user or
http://localhost:3000/api/user).
Forwarding Headers and Authentication
Server-side requests made by Axios do not automatically include
browser cookies or user headers. In getServerSideProps, you
must manually extract incoming request headers from the
context object and assign them to the Axios
configuration:
export async function getServerSideProps(context) {
const { req } = context;
const response = await axios.get('https://api.example.com/profile', {
headers: {
cookie: req.headers.cookie || '',
authorization: req.headers.authorization || '',
},
});
return {
props: {
user: response.data,
},
};
}Handling SSR in Nuxt
Nuxt provides built-in mechanisms (such as useAsyncData
and the older @nuxtjs/axios module) to coordinate data
fetching across both boundaries.
Dynamic Base URLs
Nuxt allows defining different base URLs depending on the execution
context. When using Axios in Nuxt, configure a baseURL for
client-side requests and a browserBaseURL or
server-specific base URL for internal API communication (often targeting
internal Docker networks or localhost).
Nuxt SSR Context and Interceptors
In Nuxt, interceptors can attach session data during SSR. By
accessing the Nuxt event context (useRequestEvent in Nuxt 3
or the context parameter in Nuxt 2 plugins), Axios can be
configured to mirror authentication tokens and cookies:
// Nuxt 3 plugin example
export default defineNuxtPlugin(() => {
const event = useRequestEvent();
const api = axios.create({
baseURL: process.server ? process.env.INTERNAL_API_URL : process.env.PUBLIC_API_URL,
});
if (process.server && event) {
api.defaults.headers.common.cookie = event.node.req.headers.cookie || '';
}
return {
provide: { api },
};
});Core SSR Challenges and Solutions
1. Avoiding State and Credential Leaks
In a client-only single-page application, a single global Axios instance works well. In SSR, the Node.js server serves multiple users concurrently. Storing user-specific credentials (like tokens or cookies) on a shared, global Axios instance creates a critical security vulnerability where one user's session data can leak to another user.
Solution: Create fresh, request-scoped Axios
instances using axios.create() inside server lifecycle
hooks or plugins for each incoming request.
2. Hydration Mismatches and Duplicate Requests
If data is fetched on the server using Axios, that same data must be
passed down to the client as part of the initial state payload (via
Next.js props or Nuxt
useState/useAsyncData). If the client does not
receive the initial state, Axios will execute the request a second time
on the client upon page load, resulting in layout flickering or
hydration errors.
3. Server-to-Server Network Latency
When rendering on the server, using public domain names can route traffic out through public DNS and load balancers back into the same server infrastructure.
Solution: Configure Axios to use private, internal
network addresses (such as http://127.0.0.1:port or
internal service names in containerized environments) when
process.server or
typeof window === 'undefined' evaluates to true.