How Axios Switches Between Browser and Node.js

Axios is an isomorphic (universal) HTTP client capable of running seamlessly in both client-side browser runtimes and server-side Node.js environments using the exact same API. It accomplishes this environment switching through an internal adapter design pattern combined with automated runtime detection and package build configurations. Depending on where the code executes, Axios dynamically delegates network calls to either the browser's native networking APIs or Node.js's built-in networking modules.

The Adapter Pattern

At the core of Axios’s environment-switching mechanism is the adapter pattern. Axios separates the high-level request/response handling (such as interceptors, transformations, and configuration merging) from the low-level network dispatching.

The dispatching is handled by dedicated adapters:

Build-Time Resolution via package.json

Modern module bundlers (such as Webpack, Rollup, and Vite) resolve the correct adapter at build time through conditional exports in Axios's package.json.

Axios defines fields like "browser" and conditional subpath "exports". When a bundler compiles an application for the web, it checks these fields and automatically substitutes the Node.js implementation with the browser implementation. This ensures that Node-specific APIs (which do not exist in the browser) are omitted from client-side bundles, reducing bundle size and preventing runtime errors.

Runtime Environment Detection

If the environment is not determined at build time, Axios detects the environment at runtime by inspecting global variables:

  1. Checking for Node.js: Axios verifies if the runtime includes Node-specific identifiers, such as checking if typeof process !== 'undefined' and process.versions.node exists.
  2. Checking for the Browser: Axios checks for the presence of browser-specific globals like window or document, as well as XMLHttpRequest.

Based on the evaluation of these global objects, Axios automatically assigns the appropriate default adapter to the request configuration.

Custom and Manual Adapter Configuration

Axios also allows developers to override the default switching mechanism manually. By defining the adapter property within the Axios configuration object, developers can enforce a specific transport layer or provide custom adapters for alternative environments, such as Web Workers, Service Workers, or testing mocks:

// Example: Explicitly defining a custom adapter
axios.get('/api/data', {
  adapter: 'fetch' // Or a custom adapter function
});

Through the combination of package.json module mapping, runtime global detection, and the adapter architecture, Axios provides a unified interface across distinct JavaScript execution environments.