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:
- Use Axios v0.27.2 or lower: The 0.x release line was written to support ES5 runtimes with minimal reliance on modern browser APIs.
- Transpile Axios from
node_modules: If you must use Axios v1.x+, configure your bundler (such as Webpack or Rollup with Babel) to includenode_modules/axiosin the transpilation process targeting ES5.
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-polyfillAssign 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:
- Serialize JSON payloads using
JSON.stringifymanually or via Axios's default transform functions. - Serialize URL-encoded form data using a standard query string
encoder rather than
URLSearchParams:
import qs from 'qs';
customAxiosInstance.post('/endpoint', qs.stringify({ key: 'value' }), {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
});