How to Configure Axios for Legacy Browsers

Configuring the Axios HTTP client for legacy browser environments without relying on global modern polyfills requires managing dependencies, scoping asynchronous primitives locally, and configuring the underlying network adapter. This guide outlines how to maintain compatibility in older runtimes—such as Internet Explorer 11 or legacy embedded web views—by selecting the correct library version, bundling localized Promise implementations, and customizing the request transport layer.

1. Choose a Compatible Axios Version

Axios transitioned to ES6+ features and dropped native Internet Explorer support starting in version 1.0.0. To minimize modern runtime dependencies:

Example Babel configuration snippet for Webpack:

module: {
  rules: [
    {
      test: /\.js$/,
      include: [/node_modules\/axios/],
      use: {
        loader: 'babel-loader',
        options: {
          presets: [['@babel/preset-env', { targets: 'ie 11' }]]
        }
      }
    }
  ]
}

2. Provide a Scoped Promise Implementation

Axios fundamentally relies on the Promise API to manage asynchronous operations. If modern global polyfills (like core-js) cannot be loaded into window.Promise, you must inject a local Promise implementation directly into your application code before instantiating Axios.

Install a lightweight implementation such as promise-polyfill:

npm install promise-polyfill

Assign the implementation locally without polluting the global namespace:

import Promise from 'promise-polyfill';
import axios from 'axios';

// Create an Axios instance that handles promises locally
const apiClient = axios.create({
  baseURL: 'https://api.example.com',
  timeout: 10000
});

export function request(config) {
  return new Promise((resolve, reject) => {
    apiClient(config)
      .then(resolve)
      .catch(reject);
  });
}

3. Explicitly Enforce the XMLHttpRequest Adapter

Axios dynamically chooses between fetch and XMLHttpRequest depending on the environment. Legacy browsers lack window.fetch. Explicitly enforce the standard XHR adapter to prevent runtime resolution errors.

import axios from 'axios';

const legacyClient = axios.create({
  baseURL: 'https://api.example.com',
  // Force the use of the standard XHR adapter
  adapter: 'xhr'
});

4. Implement a Custom Adapter for Pure Callback Workflows

If an environment does not support ES6 Promises and polyfilling is entirely prohibited, configure Axios with a custom transport adapter built directly on the native XMLHttpRequest API:

function legacyXHRAdapter(config) {
  return new Promise((resolve, reject) => {
    var request = new XMLHttpRequest();
    request.open(config.method.toUpperCase(), config.url, true);

    // Set custom headers
    if (config.headers) {
      Object.keys(config.headers).forEach(function(key) {
        request.setRequestHeader(key, config.headers[key]);
      });
    }

    request.onload = function() {
      var responseData = request.responseText;
      try {
        responseData = JSON.parse(responseData);
      } catch (e) {
        // Fallback to text if JSON parsing fails
      }

      var response = {
        data: responseData,
        status: request.status,
        statusText: request.statusText,
        headers: request.getAllResponseHeaders(),
        config: config,
        request: request
      };

      if (request.status >= 200 && request.status < 300) {
        resolve(response);
      } else {
        reject(new Error('Request failed with status code ' + request.status));
      }
    };

    request.onerror = function() {
      reject(new Error('Network Error'));
    };

    request.ontimeout = function() {
      reject(new Error('Timeout of ' + config.timeout + 'ms exceeded'));
    };

    request.send(config.data || null);
  });
}

const customAxiosInstance = axios.create({
  adapter: legacyXHRAdapter
});

5. Handle Legacy Data Formats

Older browsers may not have consistent implementations of FormData or URLSearchParams. To send structured payload data without modern web APIs:

import qs from 'qs';

customAxiosInstance.post('/endpoint', qs.stringify({ key: 'value' }), {
  headers: {
    'Content-Type': 'application/x-www-form-urlencoded'
  }
});