Axios has evolved from version 0.x to 1.x through several major updates. Understanding these changes is crucial for maintaining projects and upgrading.
1. Version History Overview
Major Version Milestones
shell┌─────────────────────────────────────────────────────────────────┐ │ Axios Version Evolution Timeline │ ├─────────────────────────────────────────────────────────────────┤ │ 2014 │ v0.1.0 │ Initial release, Promise-based HTTP client │ │ 2015 │ v0.9.0 │ Added interceptor functionality │ │ 2016 │ v0.12.0 │ Added request cancellation (CancelToken) │ │ 2017 │ v0.16.0 │ Support for async/await │ │ 2018 │ v0.18.0 │ Security update, fixed XSS vulnerability │ │ 2019 │ v0.19.0 │ Improved error handling, added validateStatus│ │ 2020 │ v0.20.0 │ TypeScript type improvements │ │ 2020 │ v0.21.0 │ Major security update │ │ 2022 │ v1.0.0 │ Official 1.0 release, Promise improvements │ │ 2023 │ v1.6.0 │ Support for Fetch API adapter │ └─────────────────────────────────────────────────────────────────┘
2. Important Version Changes
v0.19.0 Major Changes
javascript// Before v0.19.0 - Error handling axios.get('/user') .catch(error => { // 404 errors also enter catch if (error.response) { // Server responded with error status code } }); // After v0.19.0 - Introduced validateStatus axios.get('/user', { validateStatus: function (status) { // Default: status >= 200 && status < 300 return status < 500; // Only 500+ throws error } }); // Custom error handling const instance = axios.create({ validateStatus: (status) => { return status >= 200 && status < 300; // Default value } });
v0.20.0 TypeScript Improvements
typescript// Type definitions before v0.20.0 import axios from 'axios'; // Type definitions were not complete axios.get('/user').then(response => { // response.data type is any }); // Improvements after v0.20.0 import axios, { AxiosResponse } from 'axios'; interface User { id: number; name: string; } // Generic support axios.get<User>('/user').then((response: AxiosResponse<User>) => { // response.data type is User const user: User = response.data; }); // Request configuration type import { AxiosRequestConfig } from 'axios'; const config: AxiosRequestConfig = { url: '/user', method: 'get', headers: { 'Content-Type': 'application/json' } };
v1.0.0 Major Changes
javascript// Before v1.0.0 - CancelToken (deprecated) import axios from 'axios'; const CancelToken = axios.CancelToken; const source = CancelToken.source(); axios.get('/user', { cancelToken: source.token }); source.cancel('Operation canceled'); // After v1.0.0 - AbortController (recommended) const controller = new AbortController(); axios.get('/user', { signal: controller.signal }); controller.abort('Operation canceled'); // Compatibility handling - support both methods function makeRequest(url, cancelTokenOrSignal) { const config = {}; if (cancelTokenOrSignal instanceof AbortSignal) { config.signal = cancelTokenOrSignal; } else { config.cancelToken = cancelTokenOrSignal; } return axios.get(url, config); }
v1.6.0 Fetch API Adapter
javascript// v1.6.0 introduced Fetch API adapter import axios from 'axios'; // Use Fetch API adapter const instance = axios.create({ adapter: 'fetch' // or require('axios/adapters/fetch') }); // Traditional XHR adapter (default) const xhrInstance = axios.create({ adapter: 'http' // or require('axios/adapters/xhr') }); // Conditional adapter selection const instance = axios.create({ adapter: typeof window !== 'undefined' && 'fetch' in window ? 'fetch' : 'xhr' });
3. Compatibility Issues and Solutions
Browser Compatibility
javascript// Check browser compatibility function checkAxiosCompatibility() { const issues = []; // Check Promise support if (typeof Promise === 'undefined') { issues.push('Promise not supported'); } // Check XMLHttpRequest if (typeof XMLHttpRequest === 'undefined') { issues.push('XMLHttpRequest not supported'); } // Check Fetch API (if using fetch adapter) if (typeof fetch === 'undefined') { issues.push('Fetch API not supported (optional)'); } return issues; } // Polyfill solutions // 1. Promise Polyfill import 'es6-promise/auto'; // 2. Fetch API Polyfill import 'whatwg-fetch'; // 3. Complete compatibility handling import axios from 'axios'; // Configure adapter fallback if (typeof XMLHttpRequest === 'undefined') { // Node.js environment axios.defaults.adapter = require('axios/lib/adapters/http'); }
Node.js Version Compatibility
javascript// Engine requirements in package.json { "engines": { "node": ">=12.0.0" } } // Runtime check const semver = require('semver'); const nodeVersion = process.version; if (!semver.satisfies(nodeVersion, '>=12.0.0')) { console.warn(`Axios requires Node.js >= 12.0.0, current: ${nodeVersion}`); } // Adaptation for different Node versions const http = require('http'); const https = require('https'); const instance = axios.create({ httpAgent: new http.Agent({ keepAlive: true }), httpsAgent: new https.Agent({ keepAlive: true }), // Node.js 12+ support maxBodyLength: Infinity, maxContentLength: Infinity });
Version Detection and Adaptation
javascript// axios-version-compat.js import axios from 'axios'; // Get axios version const axiosVersion = axios.VERSION; // Version comparison utility function compareVersions(v1, v2) { const parts1 = v1.split('.').map(Number); const parts2 = v2.split('.').map(Number); for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) { const p1 = parts1[i] || 0; const p2 = parts2[i] || 0; if (p1 > p2) return 1; if (p1 < p2) return -1; } return 0; } // Select API based on version export function createCompatibleInstance(config = {}) { const isV1 = compareVersions(axiosVersion, '1.0.0') >= 0; const instance = axios.create({ ...config, // Default config for v1.0.0+ ...(isV1 && { transitional: { clarifyTimeoutError: true } }) }); // Version-specific interceptors if (isV1) { // Interceptors for v1.x instance.interceptors.request.use( (config) => { // v1.x specific handling return config; }, (error) => Promise.reject(error) ); } else { // Interceptors for v0.x instance.interceptors.request.use( (config) => config, (error) => Promise.reject(error) ); } return instance; } // Compatible cancel token wrapper export function createCancelToken() { const isV1 = compareVersions(axiosVersion, '1.0.0') >= 0; if (isV1) { // v1.x uses AbortController const controller = new AbortController(); return { token: controller.signal, cancel: (message) => controller.abort(message) }; } else { // v0.x uses CancelToken const source = axios.CancelToken.source(); return source; } }
4. Upgrade Guide
Upgrading from v0.x to v1.x
javascript// Upgrade checklist const upgradeChecklist = { // 1. Check CancelToken usage checkCancelToken: () => { // Replace with AbortController // Old code const source = axios.CancelToken.source(); // New code const controller = new AbortController(); }, // 2. Check error handling checkErrorHandling: () => { // Ensure validateStatus config is correct axios.defaults.validateStatus = (status) => { return status >= 200 && status < 300; }; }, // 3. Check TypeScript types checkTypeScript: () => { // Update type imports // import { AxiosResponse } from 'axios'; }, // 4. Check adapter configuration checkAdapter: () => { // If using custom adapter, needs update } }; // Automatic upgrade script function migrateAxiosCode(code) { // Replace CancelToken code = code.replace( /axios\.CancelToken\.source\(\)/g, 'new AbortController()' ); // Replace cancelToken config code = code.replace( /cancelToken:\s*source\.token/g, 'signal: controller.signal' ); // Replace cancel call code = code.replace( /source\.cancel\(/g, 'controller.abort(' ); return code; }
Dependency Version Locking
json// package.json - Lock version { "dependencies": { "axios": "^1.6.0" }, "devDependencies": { "@types/axios": "^0.14.0" }, "resolutions": { "axios": "1.6.0" } } // package-lock.json / yarn.lock // Ensure lock files are committed to version control
5. Version Compatibility Testing
javascript// __tests__/axios-compat.test.js import axios from 'axios'; describe('Axios Version Compatibility', () => { test('should have correct version', () => { expect(axios.VERSION).toBeDefined(); expect(axios.VERSION).toMatch(/^\d+\.\d+\.\d+/); }); test('should support AbortController in v1.x', () => { const [major] = axios.VERSION.split('.').map(Number); if (major >= 1) { const controller = new AbortController(); expect(() => { axios.get('/test', { signal: controller.signal }); }).not.toThrow(); } }); test('should support legacy CancelToken', () => { if (axios.CancelToken) { const source = axios.CancelToken.source(); expect(source.token).toBeDefined(); expect(typeof source.cancel).toBe('function'); } }); test('should handle errors consistently', async () => { try { await axios.get('http://invalid-domain-that-does-not-exist.com'); } catch (error) { expect(error).toBeDefined(); expect(error.message).toBeDefined(); } }); });
6. Best Practices
Version Management Strategy
javascript// 1. Use fixed version // package.json { "dependencies": { "axios": "1.6.0" // Do not use ^ or ~ } } // 2. Wrap axios to isolate version impact // api/client.js import axios from 'axios'; const apiClient = axios.create({ baseURL: process.env.API_URL, timeout: 10000, headers: { 'Content-Type': 'application/json' } }); // Wrap request methods to hide axios details export const api = { get: (url, config) => apiClient.get(url, config), post: (url, data, config) => apiClient.post(url, data, config), // ... other methods }; // 3. Regular update strategy // Create update script scripts/update-axios.js const { execSync } = require('child_process'); const axios = require('axios/package.json'); console.log(`Current axios version: ${axios.version}`); // Check latest version fetch('https://registry.npmjs.org/axios') .then(res => res.json()) .then(data => { const latest = data['dist-tags'].latest; console.log(`Latest axios version: ${latest}`); if (latest !== axios.version) { console.log('Update available. Run: npm update axios'); } });
Compatibility Configuration Template
javascript// config/axios.js import axios from 'axios'; // Detect environment const isBrowser = typeof window !== 'undefined'; const isNode = !isBrowser; const axiosVersion = axios.VERSION; // Base configuration const baseConfig = { timeout: 10000, headers: { 'Content-Type': 'application/json' } }; // Environment-specific configuration const envConfig = isNode ? { // Node.js configuration httpAgent: new (require('http').Agent)({ keepAlive: true }), httpsAgent: new (require('https').Agent)({ keepAlive: true }) } : { // Browser configuration withCredentials: true, xsrfCookieName: 'XSRF-TOKEN', xsrfHeaderName: 'X-XSRF-TOKEN' }; // Version-specific configuration const versionConfig = axiosVersion.startsWith('1.') ? { // v1.x configuration transitional: { clarifyTimeoutError: true, forcedJSONParsing: true } } : { // v0.x configuration }; // Create instance const instance = axios.create({ ...baseConfig, ...envConfig, ...versionConfig }); export default instance;
Version Compatibility Quick Reference
| Feature | v0.18.x | v0.19.x | v0.20.x | v0.21.x | v1.0.0+ |
|---|---|---|---|---|---|
| CancelToken | ✅ | ✅ | ✅ | ✅ | ⚠️ Deprecated |
| AbortController | ❌ | ❌ | ❌ | ❌ | ✅ |
| Fetch adapter | ❌ | ❌ | ❌ | ❌ | ✅ |
| validateStatus | ✅ | ✅ Improved | ✅ | ✅ | ✅ |
| TypeScript | ⚠️ | ⚠️ | ✅ Improved | ✅ | ✅ |
| ESM support | ⚠️ | ⚠️ | ⚠️ | ✅ | ✅ |
| Security fixes | ✅ | ✅ | ✅ | ✅ | ✅ |
Summary
- Version Selection: New projects recommended to use v1.6.0+, old projects migrate gradually
- Compatibility Handling: Wrap axios usage to isolate version differences
- Upgrade Strategy: Test before upgrading, use lock files
- API Selection: Prioritize new standards (AbortController)
- Monitor Updates: Watch for security updates and breaking changes