DEV Community

Mark Lai
Mark Lai

Posted on

Why I'm ditching Axios (Spoiler: I moved to Wretch!)

I've been working in the web development field for more than 5years now, but one question has been in my mind since day one: Why Axios is always the "Go to" for HTTP client? Why there seem aren't any competitors?
Although there are a lot of articles about the fetch API, I still found that having an interceptor(middleware pattern) and a configurable instance of the client is essential, especially for commercial-grade applications that have multiple HTTP clients, require adding a lot of headers here and there and complex error handling.

Motivation

1. Axios has had a lot of breaking changes recently

Recently Axios shipped out v0.27.0 which includes some breaking changes and bugs. It's hard to imagine an over 8 years package still not v1.0.0. Although they finally planned to follow semantic versioning (ref: github.com/axios/axios/issues/4614). It already brings a lot of trouble for auto package management like Renovate. Not to mention its fragile codebase.

2. Axios codebase is fragile

The trigger point of this move is that v0.27.0 breaks FormData handling unintentionally(ref: https://github.com/axios/axios/pull/4640). Solving a mobile problem brings in a browser bug. This shows the current maintainer(s) lack the knowledge of the platform it's supporting and how its ancient code works. Not to metion v0.27.0 is shipped 1 year after the the PR merged, more issue just left there for a few years unresolved. With it's low momentum, I doubt this package will move forward steady.

// Some example for weird design choice, it calls your interceptor in the reverse order.
// ref: https://github.com/axios/axios/issues/841
const instance = axios.create();
instance.interceptors.request.use(function () {/*This will run second*/});
instance.interceptors.request.use(function () {/*This will run first*/});
Enter fullscreen mode Exit fullscreen mode

3. Axios is still using the old XMLHttpRequests API

Part of the reason for this is Axios is still using the old XMLHttpRequests API. It has to manually implement a lot of handling and hacks we get for free with Fetch API. Fetch API should be the standard in 2022 as most browser supports it. Fetch API based HTTP client also result in smaller bundle size in general.

So what are the choices out there?

So the objective is pretty clear, a Fetch API based HTTP client with good looking syntax and active maintenance. After a bit of research, there are a few choices, but not all fit my criteria:

  • Got(Node Js only)
  • superagent(also XMLHttpRequests based)
  • Gaxios(Node Js only)

Finally, I got 2 solid contestants, Ky and Wretch. Both are new Fetch API based HTTP clients with small bundle sizes (~3KB, Axios is 6.7KB)

Ky
Ky is created by the same group of Got, which offer some interesting feature. Like treats non-2xx status codes as errors, retries failed requests and event hooks(like Axios interceptor).

const instance = ky.create({
  headers: {
    rainbow: 'rainbow',
    unicorn: 'unicorn'
  }
});

instance.extend({
  hooks: {
    beforeRequest: [
      async ({request, options, error, retryCount}) => {/*request interceptor*/}
    ]
  }
});

instance.extend({
  hooks: {
    beforeError: [
      async (error) => {/*error interceptor*/}
    ]
  }
});

instance.extend({
  hooks: {
    afterResponse: [
      async (error) => {/*response interceptor*/}
    ]
  }
});

Enter fullscreen mode Exit fullscreen mode

Wretch
Wretch on the other hand takes the function chaining approach. It split common error types into separate helper methods so you don't need to result in an interceptor every time

const instance = wretch()
  .auth("Basic d3JldGNoOnJvY2tz")
  .headers({ "Content-Type": "text/plain", Accept: "application/json" })

// helper methods to directly intercept common error
instance()
  .badRequest(err => console.log(err.status))
  .unauthorized(err => console.log(err.status))
  .forbidden(err => console.log(err.status))
  .notFound(err => console.log(err.status))
  .timeout(err => console.log(err.status))
  .internalError(err => console.log(err.status))
  .error(418, err => console.log(err.status))
  .fetchError(err => console.log(err))
  .res()

instance.middlewares([
  next => (url, opts) => {/*request interceptor*/}
])

Enter fullscreen mode Exit fullscreen mode

Why Wretch not Ky

When you go NPM trends you may find Ky has more downloads stars etc... than Wretch, but why do I still go for Wretch?

Although Ky has more stars and downloads, I think it's mostly driven by the hype of the creator of Got. After 6 years of its creation, it also hasn't passed v1.0.0. The creator already creates a milestone for v1.0.0 but it's more than half a year ago with little progress. Wretch on the other hand is already v1.7.9 with planning for v2. So as an adaptor right now, Ky is riskier than Wretch. On top of that, I'm more into the function chaining approach than the object config in Ky, were registering a middlewares with a function is cleaner than extends() in Ky. But it is kind of subjective, I will leave you guys be the judge.

Latest comments (8)

Collapse
 
rnbsov profile image
Lakavaka

How do I create custom interceptor but for response?

instance.middlewares([
next => (url, opts) => {/*request interceptor*/}
])

Collapse
 
kasvith profile image
Kasun Vithanage

Axios uses XMLHTTPRequest because it support download progress

Collapse
 
marklai1998 profile image
Mark Lai

I recently found ProgressAddon in wretch so you don't have to implement it on your own

Collapse
 
marklai1998 profile image
Mark Lai

you can also do it via fetch
the XMLHTTPRequest onprogress event is using the Content-Length header to calc the progress

you can implement the same logic using fetch
ref: stackoverflow.com/questions/472851...

Collapse
 
webjose profile image
José Pablo Ramírez Vargas

I like the availability of fetch in the browser and NodeJS. Hopefully Wretch works on both since it is a fetch wrapper.

Collapse
 
marklai1998 profile image
Mark Lai

I uses Wretch dail for both BE and FE, it works perfectly with the node 18 native fetch without any polyfill

Collapse
 
ekrresa profile image
Ochuko Ekrresa

I've been an axios stan for some time but I would look into Ky and Wretch. Great article!

Collapse
 
andrewbaisden profile image
Andrew Baisden

I always use Axios or Fetch might give Wretch a try.