Skip to content

Commit 067350b

Browse files
authored
Add benchmarks for openapi-fetch (#1299)
1 parent ad894a5 commit 067350b

File tree

11 files changed

+467
-88
lines changed

11 files changed

+467
-88
lines changed

docs/src/content/docs/openapi-fetch/index.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,13 @@ description: Get Started with openapi-fetch
77

88
openapi-fetch applies your OpenAPI types to the native fetch API via TypeScript. Weighs **2 kb** and has virtually zero runtime. Works with React, Vue, Svelte, or vanilla JS.
99

10-
| Library | Size (min) |
11-
| :----------------------------- | ---------: |
12-
| **openapi-fetch** | `2 kB` |
13-
| **openapi-typescript-fetch** | `4 kB` |
14-
| **openapi-typescript-codegen** | `345 kB` |
10+
| Library | Size (min) | GET performance |
11+
| :------------------------- | ---------: | :------------------------ |
12+
| openapi-fetch | `2 kB` | `151k` ops/s (fastest) |
13+
| openapi-typescript-fetch | `4 kB` | `99k` ope/s (1.4× slower) |
14+
| axios | `32 kB` | `90k` ops/s (1.6× slower) |
15+
| superagent | `55 kB` | `42k` ops/s (3× slower) |
16+
| openapi-typescript-codegen | `367 kB` | `71k` ops/s (2× slower) |
1517

1618
The syntax is inspired by popular libraries like react-query or Apollo client, but without all the bells and whistles and in a 2 kb package.
1719

packages/openapi-fetch/.eslintignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
test/openapi-typescript-codegen.min.js

packages/openapi-fetch/README.md

+7-5
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
openapi-fetch applies your OpenAPI types to the native fetch API via TypeScript. Weighs **2 kB** and has virtually zero runtime. Works with React, Vue, Svelte, or vanilla JS.
44

5-
| Library | Size (min) |
6-
| :----------------------------- | ---------: |
7-
| **openapi-fetch** | `2 kB` |
8-
| **openapi-typescript-fetch** | `4 kB` |
9-
| **openapi-typescript-codegen** | `345 kB` |
5+
| Library | Size (min) | GET performance |
6+
| :------------------------- | ---------: | :------------------------ |
7+
| openapi-fetch | `2 kB` | `151k` ops/s (fastest) |
8+
| openapi-typescript-fetch | `4 kB` | `99k` ope/s (1.4× slower) |
9+
| axios | `32 kB` | `90k` ops/s (1.6× slower) |
10+
| superagent | `55 kB` | `42k` ops/s (3× slower) |
11+
| openapi-typescript-codegen | `367 kB` | `71k` ops/s (2× slower) |
1012

1113
The syntax is inspired by popular libraries like react-query or Apollo client, but without all the bells and whistles and in a 2 kB package.
1214

packages/openapi-fetch/package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,14 @@
5858
"version": "pnpm run prepare && pnpm run build"
5959
},
6060
"devDependencies": {
61+
"axios": "^1.4.0",
6162
"del-cli": "^5.0.0",
62-
"esbuild": "^0.19.0",
63+
"esbuild": "^0.19.2",
6364
"nanostores": "^0.9.3",
64-
"openapi-typescript": "^6.4.2",
65+
"openapi-typescript": "^6.5.0",
66+
"openapi-typescript-codegen": "^0.25.0",
67+
"openapi-typescript-fetch": "^1.1.3",
68+
"superagent": "^8.1.2",
6569
"typescript": "^5.1.6",
6670
"vitest": "^0.34.1",
6771
"vitest-fetch-mock": "^0.2.2"
+97
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import axios from "axios";
2+
import { Fetcher } from "openapi-typescript-fetch";
3+
import superagent from "superagent";
4+
import { afterAll, bench, describe, vi } from "vitest";
5+
import createFetchMock from "vitest-fetch-mock";
6+
import * as openapiTSCodegen from "./openapi-typescript-codegen.min.js";
7+
import createClient from "../dist/index.js";
8+
9+
const BASE_URL = "https://api.test.local";
10+
11+
const fetchMocker = createFetchMock(vi);
12+
13+
fetchMocker.enableMocks();
14+
fetchMocker.mockResponse("{}");
15+
afterAll(() => {
16+
fetchMocker.resetMocks();
17+
});
18+
19+
describe("setup", () => {
20+
bench("openapi-fetch", async () => {
21+
createClient();
22+
});
23+
24+
bench("openapi-typescript-fetch", async () => {
25+
const fetcher = Fetcher.for();
26+
fetcher.path("/pet/findByStatus").method("get").create();
27+
});
28+
29+
// axios: N/A
30+
31+
// superagent: N/A
32+
});
33+
34+
describe("get (only URL)", () => {
35+
let openapiFetch = createClient({ baseUrl: BASE_URL });
36+
let openapiTSFetch = Fetcher.for();
37+
openapiTSFetch.configure({
38+
init: { baseUrl: BASE_URL },
39+
});
40+
41+
bench("openapi-fetch", async () => {
42+
await openapiFetch.GET("/url");
43+
});
44+
45+
bench("openapi-typescript-fetch", async () => {
46+
await openapiTSFetch.path("/url").method("get").create()();
47+
});
48+
49+
bench("openapi-typescript-codegen", async () => {
50+
await openapiTSCodegen.PullsService.pullsGet();
51+
});
52+
53+
bench("axios", async () => {
54+
await axios.get("/url", {
55+
async adapter() {
56+
return "{}";
57+
},
58+
});
59+
});
60+
61+
bench("superagent", async () => {
62+
await superagent.get("/url").end();
63+
});
64+
});
65+
66+
describe("get (headers)", () => {
67+
let openapiFetch = createClient({ baseUrl: BASE_URL, headers: { "x-base-header": 123 } });
68+
let openapiTSFetch = Fetcher.for();
69+
openapiTSFetch.configure({
70+
init: { baseUrl: BASE_URL, headers: { "x-base-header": 123 } },
71+
});
72+
73+
bench("openapi-fetch", async () => {
74+
await openapiFetch.GET("/url", { headers: { "x-header-1": 123, "x-header-2": 456 } });
75+
});
76+
77+
bench("openapi-typescript-fetch", async () => {
78+
await openapiTSFetch.path("/url").method("get").create()(null, { headers: { "x-header-1": 123, "x-header-2": 456 } });
79+
});
80+
81+
bench("openapi-typescript-codegen", async () => {
82+
await openapiTSCodegen.PullsService.pullsGet();
83+
});
84+
85+
bench("axios", async () => {
86+
await axios.get(`${BASE_URL}/url`, {
87+
headers: { "x-header-1": 123, "x-header-2": 456 },
88+
async adapter() {
89+
return "{}";
90+
},
91+
});
92+
});
93+
94+
bench("superagent", async () => {
95+
await superagent.get(`${BASE_URL}/url`).set("x-header-1", 123).set("x-header-2", 456).end();
96+
});
97+
});

packages/openapi-fetch/test/openapi-typescript-codegen.min.js

+10
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/openapi-fetch/test/v1.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,11 @@ export interface components {
351351
"application/json": components["schemas"]["StringArray"];
352352
};
353353
};
354+
Tag: {
355+
content: {
356+
"application/json": string;
357+
};
358+
};
354359
User: {
355360
content: {
356361
"application/json": components["schemas"]["User"];

packages/openapi-fetch/test/v1.yaml

+7-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
openapi: 3.1
1+
openapi: 3.1.0
22
info:
33
title: Test Specification
44
version: '1.0'
@@ -480,6 +480,12 @@ components:
480480
application/json:
481481
schema:
482482
$ref: '#/components/schemas/StringArray'
483+
Tag:
484+
content:
485+
application/json:
486+
schema:
487+
type:
488+
string
483489
User:
484490
content:
485491
application/json:

packages/openapi-fetch/tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
"target": "ESNext",
1313
"types": ["vitest/globals"]
1414
},
15-
"include": ["src"],
15+
"include": ["src", "test"],
1616
"exclude": ["node_modules"]
1717
}

packages/openapi-typescript/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
"@types/node": "^20.4.9",
7272
"degit": "^2.8.4",
7373
"del-cli": "^5.0.0",
74-
"esbuild": "^0.19.0",
74+
"esbuild": "^0.19.2",
7575
"execa": "^7.2.0",
7676
"vite": "^4.4.9",
7777
"vite-node": "^0.34.1",

0 commit comments

Comments
 (0)