Ky logo

Ky

基于原生 Fetch API 的轻量、优雅 JavaScript HTTP 客户端,零依赖,gzip 后仅 ~7 KB。

HTTP请求API客户端Fetch封装轻量级

Ky 是由 Sindre Sorhus 创建的轻量级 HTTP 客户端,基于原生 Fetch API 封装,提供自动重试、超时控制、Hooks 拦截、JSON 快捷处理、Standard Schema 响应校验等功能。零依赖、纯 ESM,支持浏览器/Node.js 22+/Bun/Deno。v2.0 带来全新 Hooks 系统和智能超时机制,GitHub 约 17,000 Stars。

Ky

基于原生 Fetch API 的轻量、优雅 JavaScript HTTP 客户端,零依赖,gzip 后仅 ~7 KB。

技术简介说明

Ky 是由 Sindre Sorhus(同时也是 Got 的作者)创建的轻量级 JavaScript HTTP 客户端。它以浏览器原生的 Fetch API 为基础,在其之上封装了自动重试、超时控制、Hooks 拦截、JSON 快捷处理、上传/下载进度追踪等高频实用功能,旨在消除 Fetch API 的样板代码和粗糙边界。

与 Axios 等自行实现 HTTP 层的库不同,Ky 从设计之初就拥抱 Fetch API,不引入额外的请求适配层。这使得 Ky 体积极小(gzip 约 7 KB,约为 Axios 的 1/2)、零运行时依赖,且与浏览器、Node.js 22+、Bun、Deno 等现代运行时天然兼容。Ky 使用 TypeScript 编写,提供完整的类型推导支持。

2026 年 4 月,Ky 发布了重大版本 v2.0,带来了全新的 Hooks 系统(统一状态对象参数)、更智能的超时机制(新增 totalTimeout 全局超时)、内置 Standard Schema 响应校验(兼容 Zod、Valibot 等),以及更精细的错误分类体系。该版本要求 Node.js 22+,是一次面向现代 JavaScript 生态的全面升级。

基本信息

项目说明
最新版本v2.0.2(2026-04-21 发布)
npm 包名ky
npm 周下载量~570 万次(2026 年数据)
GitHubsindresorhus/ky
GitHub Stars~17,000
LicenseMIT
模块格式ESM(纯 ES Module,不支持 CommonJS require()
维护者Sindre SorhusSeth Holladay
Node.js 要求≥ 22(v2.0 起)
浏览器要求支持原生 Fetch API 的现代浏览器
Bundle 大小~7 KB(gzip)/ ~20 KB(minified),零依赖
TypeScript内置类型定义,原生 TypeScript 编写
累计发布98+ 个版本,488+ 次提交

快速上手

安装

# npm
npm install ky
 
# pnpm
pnpm add ky
 
# yarn
yarn add ky
 
# bun
bun add ky

基础用法

import ky from 'ky';
 
// 最简单的 GET 请求
const json = await ky('https://api.example.com/users/1').json();
 
// 使用快捷方法
const user = await ky.get('https://api.example.com/users/1').json();
 
// POST 请求,自动 JSON 序列化
const result = await ky.post('https://api.example.com/users', {
  json: { name: 'Alice', email: '[email protected]' }
}).json();

创建可复用实例

import ky from 'ky';
 
// 创建带默认配置的实例
const api = ky.create({
  prefix: 'https://api.example.com',
  timeout: 10000,
  retry: { limit: 3 },
  hooks: {
    beforeRequest: [
      (request) => {
        request.headers.set('Authorization', `Bearer ${getToken()}`);
      }
    ],
    afterResponse: [
      async ({ response }) => {
        if (!response.ok) {
          console.error(`请求失败: ${response.status}`);
        }
      }
    ]
  }
});
 
// 使用实例发请求(自动携带 prefix、auth、timeout 等)
const users = await api.get('users').json();
const newUser = await api.post('users', { json: { name: 'Bob' } }).json();

继承与扩展

const baseApi = ky.create({ prefix: 'https://api.example.com' });
 
// 基于基础实例扩展,继承所有配置
const usersApi = baseApi.extend({
  prefix: 'https://api.example.com/users'
});
 
// 也可以继承并覆盖部分配置
const adminApi = baseApi.extend({
  hooks: {
    beforeRequest: [
      (request) => {
        request.headers.set('X-Admin', 'true');
      }
    ]
  }
});

核心概念与架构

基于 Fetch API 的封装

Ky 的设计哲学是 增强而非替代 Fetch API。它直接接收和返回标准的 Request / Response 对象,所有配置与 Fetch 的 RequestInit 完全兼容。Ky 所做的是在 Fetch 之上添加了一层便利功能,而非重新发明请求机制。

┌──────────────────────────────────────────────┐
│              你的应用代码                      │
│  await ky.get('/users').json()              │
└─────────────────┬────────────────────────────┘
                  │
┌─────────────────▼────────────────────────────┐
│           Ky 核心层                           │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐     │
│  │  Hooks   │ │  Retry   │ │ Timeout  │     │
│  │  系统    │ │  引擎    │ │  控制器  │     │
│  └──────────┘ └──────────┘ └──────────┘     │
│  ┌──────────┐ ┌──────────┐ ┌──────────┐     │
│  │  Schema  │ │ Progress │ │  Error   │     │
│  │  校验    │ │  追踪    │ │  分类    │     │
│  └──────────┘ └──────────┘ └──────────┘     │
└─────────────────┬────────────────────────────┘
                  │
┌─────────────────▼────────────────────────────┐
│          原生 Fetch API                       │
│     Request / Response / Headers             │
└──────────────────────────────────────────────┘

ResponsePromise

Ky 返回的不是普通 Promise,而是扩展了 ResponsePromise,链式调用 .json().text().blob() 等响应方法,同时兼容标准 Response 的所有属性和方法。

实例与扩展机制

Ky 支持通过 ky.create() 创建带默认配置的实例,再通过 ky.extend() 基于已有实例派生新实例。这种模式类似于面向对象中的继承,非常适合构建分层 API 客户端。

核心特性

1. 自动重试(Retry)

内置指数退避重试机制,默认重试 2 次,支持自定义重试策略:

const json = await ky.get('https://api.example.com/data', {
  retry: {
    limit: 5,
    methods: ['get', 'post'],
    statusCodes: [408, 413, 429, 500, 502, 503, 504],
    // 自定义延迟函数
    delay: (attemptCount) => 0.3 * (2 ** (attemptCount - 1)) * 1000,
    // 添加抖动防止惊群效应
    jitter: true,
    // 自定义重试判断
    shouldRetry: ({ error, retryCount }) => {
      if (error instanceof HTTPError && error.response.status === 429) {
        return retryCount <= 3;
      }
      return undefined; // 使用默认逻辑
    }
  }
}).json();

2. 超时控制(Timeout)

v2.0 新增 totalTimeout,可以控制包含所有重试在内的总超时时间:

const data = await ky.get('/api/slow-endpoint', {
  timeout: 5000,        // 单次请求超时 5s
  totalTimeout: 30000   // 总超时(含重试)30s
}).json();

3. Hooks 拦截系统

v2.0 统一了 Hooks 参数为单一状态对象,提供 5 种生命周期钩子:

const api = ky.create({
  hooks: {
    // 请求构建前(同步)
    init: [
      (options) => {
        options.searchParams = { apiKey: getApiKey() };
      }
    ],
    // 请求发送前
    beforeRequest: [
      ({ request }) => {
        request.headers.set('Authorization', `Bearer ${token}`);
      }
    ],
    // 重试前(可刷新 token)
    beforeRetry: [
      async ({ request, retryCount }) => {
        const newToken = await refreshToken();
        request.headers.set('Authorization', `Bearer ${newToken}`);
      }
    ],
    // 响应后(可触发重试)
    afterResponse: [
      async ({ response, request }) => {
        if (response.status === 429) {
          return ky.retry({ delay: 5000 });
        }
      }
    ],
    // 错误抛出前(可修改错误)
    beforeError: [
      ({ error, request }) => {
        if (isHTTPError(error)) {
          error.message = `API 错误: ${error.response.status}`;
        }
        return error;
      }
    ]
  }
});

4. Standard Schema 响应校验

v2.0 内置 Standard Schema 支持,可直接使用 Zod、Valibot 等验证器校验响应:

import { z } from 'zod';
import ky, { SchemaValidationError } from 'ky';
 
const UserSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email()
});
 
try {
  const user = await ky.get('/api/user/1').json(UserSchema);
  // user 类型自动推导为 { id: number; name: string; email: string }
  console.log(user.name);
} catch (error) {
  if (error instanceof SchemaValidationError) {
    console.error('数据校验失败:', error.issues);
  }
}

5. 上传/下载进度追踪

// 下载进度
const response = await ky.get('https://example.com/large-file', {
  onDownloadProgress: ({ percent, transferredBytes, totalBytes }) => {
    console.log(`下载进度: ${(percent * 100).toFixed(1)}%`);
  }
});
 
// 上传进度
await ky.post('https://example.com/upload', {
  body: formData,
  onUploadProgress: ({ percent }) => {
    console.log(`上传进度: ${(percent * 100).toFixed(1)}%`);
  }
});

6. 智能错误分类

v2.0 引入了清晰的错误类型体系:

错误类触发条件关键属性
HTTPError非 2xx 状态码response, request, data
NetworkErrorDNS 失败、连接拒绝request, cause
TimeoutError请求超时request
SchemaValidationErrorSchema 校验失败issues
ForceRetryErrorafterResponse 触发重试customDelay, code
import ky, { isHTTPError, isNetworkError, isTimeoutError } from 'ky';
 
try {
  const data = await ky.get('/api/data').json();
} catch (error) {
  if (isHTTPError(error)) {
    console.error(`HTTP 错误: ${error.response.status}`, error.data);
  } else if (isTimeoutError(error)) {
    console.error('请求超时');
  } else if (isNetworkError(error)) {
    console.error('网络错误:', error.cause);
  }
}

7. 方法快捷入口

提供所有 HTTP 方法的快捷调用:

ky.get(url, options)
ky.post(url, options)
ky.put(url, options)
ky.delete(url, options)
ky.patch(url, options)
ky.head(url, options)

8. 实例继承与 replaceOption

通过 extend() 继承配置时,数组类选项(如 hooks)默认追加。使用 replaceOption 可覆盖而非追加:

import ky, { replaceOption } from 'ky';
 
const base = ky.create({
  hooks: { beforeRequest: [addAuth, addTracking] }
});
 
// 替换而非追加
const clean = base.extend({
  hooks: replaceOption({ beforeRequest: [onlyThisHook] })
});
// clean 的 beforeRequest 现在只有 [onlyThisHook]

9. 跨平台支持

同一份代码可运行于浏览器、Node.js 22+、Bun 和 Deno:

// 浏览器、Node.js 22+、Bun、Deno 均可直接运行
import ky from 'ky';
 
// 无需 polyfill,无需条件导入
const data = await ky('https://api.example.com').json();

10. JSON 智能处理

自动序列化请求体、解析响应体,v2.0 对空响应做了更严格的处理:

// 请求体自动 JSON 序列化
await ky.post('/users', { json: { name: 'Alice' } });
 
// 响应体自动 JSON 解析
const user = await ky.get('/users/1').json();
 
// v2.0: 空响应和 204 响应会抛出错误(不再静默返回空字符串)

生态图

                          ┌─────────────────────┐
                          │     Ky 核心生态      │
                          └──────────┬──────────┘
                 ┌───────────────────┼───────────────────┐
                 │                   │                    │
    ┌────────────▼──────┐ ┌──────────▼──────────┐ ┌──────▼──────────────┐
    │  官方关联包        │ │  代码生成工具        │ │  社区扩展            │
    │                   │ │                     │ │                      │
    │ • ky-universal    │ │ • @hey-api/openapi  │ │ • ky-hooks-change-  │
    │ • fetch-extras    │ │   -ts (Ky v1 客户端)│ │   case               │
    │ • is-network-error│ │ • AdonisJS API      │ │ • @smeijer/ky       │
    │ • parse-sse       │ │   Client            │ │   (CJS 兼容版)       │
    │ • Got (Node.js)   │ │                     │ │ • @gdoudeng/        │
    │                   │ │                     │ │   cocos-ky           │
    └───────────────────┘ └─────────────────────┘ └──────────────────────┘

    ┌──────────────────────────────────────────────────────────────────────┐
    │                        Schema 校验生态                               │
    │  Zod 3.24+  ·  Valibot  ·  ArkType  ·  Typia  (Standard Schema)     │
    └──────────────────────────────────────────────────────────────────────┘

    ┌──────────────────────────────────────────────────────────────────────┐
    │                        运行时兼容                                    │
    │  浏览器(现代)  ·  Node.js 22+  ·  Bun  ·  Deno  ·  Cloudflare     │
    │  Workers                                                            │
    └──────────────────────────────────────────────────────────────────────┘

官方关联包

包名说明
ky-universal在 Node.js(旧版本)和浏览器中同时使用 Ky(通过 polyfill)
fetch-extrasFetch API 实用工具集(含 Standard Schema 校验的 parseJSON()
is-network-error检测是否为 Fetch 网络错误
parse-sse解析 Server-Sent Events(SSE)数据流
Got同一作者的全功能 Node.js HTTP 客户端(推荐纯 Node.js 场景使用)

社区扩展

包名说明
ky-hooks-change-case请求/响应自动大小写转换(camelCase ↔ snake_case)
@smeijer/ky支持 CommonJS 的 Ky 分支版本
@gdoudeng/cocos-ky适配 Cocos Creator 游戏引擎的 Ky 变体

集成工具

工具集成方式
@hey-api/openapi-ts从 OpenAPI 规范生成类型安全的 Ky 客户端
AdonisJS API ClientAdonisJS 前端类型安全 API 客户端基于 Ky 构建

适用场景

1. 前端 SPA / SSR 应用

Ky 的极小体积(~7 KB gzip)使其成为 React、Vue、Svelte、Next.js 等前端应用的理想 HTTP 客户端,对 bundle 大小影响极小。

2. 微前端与微服务网关

通过 ky.create()ky.extend() 轻松构建多层级 API 客户端,每个微服务拥有独立配置和认证逻辑。

3. Edge Computing / Serverless

Ky 天然支持 Cloudflare Workers、Vercel Edge Functions、Deno Deploy 等边缘运行时环境,零依赖、纯 ESM 的特性与边缘计算完美匹配。

4. 需要自动重试的 unreliable 网络环境

内置的指数退避重试、抖动、全局超时机制,使其在移动网络、IoT 设备、弱网环境下表现优异。

5. 类型安全 API 客户端

配合 TypeScript 和 Standard Schema(Zod/Valibot),可构建从请求到响应的全链路类型安全客户端。

6. 渐进式 Fetch API 增强

团队已使用原生 Fetch 但需要增加重试、超时、拦截等功能时,Ky 提供最小迁移成本——因为它直接基于 Fetch,不改变底层行为。

7. 全栈同构项目

一套代码同时运行于浏览器和 Node.js(22+),无需条件导入或 polyfill 配置。

开发与工程化

TypeScript 支持

Ky 原生使用 TypeScript 编写,提供完整的类型推导:

interface User {
  id: number;
  name: string;
  email: string;
}
 
// 使用 Standard Schema 推导类型
const user = await ky.get('/user/1').json(UserSchema);
// user: { id: number; name: string; email: string }
 
// 泛型方式(不推荐,v2.0 推荐用 Schema)
const data = await ky.get('/users').json<User[]>();

ESM 模块

Ky v2.0 是纯 ES Module 包。如果你的项目使用 CommonJS,有几个选择:

// 方式一:使用动态 import(Node.js)
const { default: ky } = await import('ky');
 
// 方式二:使用 CJS 兼容分支
// npm install @smeijer/ky
import ky from '@smeijer/ky';
 
// 方式三:在 package.json 中设置 "type": "module"

测试集成

// Vitest 测试示例
import { describe, it, expect, vi } from 'vitest';
import ky from 'ky';
 
// Mock fetch
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(
  new Response(JSON.stringify({ id: 1, name: 'Alice' }), {
    status: 200,
    headers: { 'Content-Type': 'application/json' }
  })
));
 
describe('API Client', () => {
  it('should fetch user data', async () => {
    const user = await ky.get('https://api.example.com/users/1').json();
    expect(user).toEqual({ id: 1, name: 'Alice' });
  });
});

构建工具兼容

构建工具兼容性备注
Vite✅ 完全兼容推荐,ESM 原生支持
webpack 5✅ 兼容需要 experiments.outputModule 支持 ESM
esbuild✅ 完全兼容
Turbopack✅ 完全兼容Next.js 15+ 默认使用
Rollup✅ 完全兼容

性能与安全

性能特征

指标数值
包体积(gzip)~7 KB
包体积(minified)~20 KB
运行时依赖0
初始化开销极低(无运行时抽象层)
请求开销与原生 Fetch 基本一致(仅增加少量 Hooks 判断)
重试延迟指数退避:0.3 × 2^(n-1) × 1000 ms

安全考量

  • 零依赖:消除了供应链攻击风险(相比之下,2026 年 3 月 Axios 曾遭受 npm 供应链攻击)
  • 默认信任 Fetch:继承浏览器的 CORS、Cookie、证书验证等安全机制
  • HTTPError 默认抛出:非 2xx 响应自动报错,避免静默处理错误数据
  • Schema 校验:v2.0 内置 Standard Schema,在响应解析阶段即可拦截非法数据
  • eval() / 动态代码:Ky 源码无任何动态代码执行

与 Axios 安全事件对比

2026 年 3 月 31 日,Axios 的 npm 账号遭到供应链攻击( attributed to 朝鲜威胁行为者),受影响版本在约 3 小时内被修复。这一事件让许多团队重新审视 HTTP 客户端的依赖链安全性——Ky 的零依赖设计天然避免了此类风险。

技术对比

特性Ky v2.0AxiosGotofetch
包体积(gzip)~7 KB~14 KB~48 KB~3.8 KB
运行时依赖00少量0
基于 Fetch✅ 原生❌ 自有实现❌ 自有实现✅ 原生
浏览器支持✅ 现代浏览器✅ 全版本⚠️ 需适配
Node.js 支持≥ 22全版本≥ 16全版本
Bun / Deno
TypeScript✅ 原生✅ 有类型✅ 原生✅ 原生
自动重试✅ 内置❌ 需手动✅ 内置✅ 内置
Hooks/拦截器✅ 5 种✅ 请求/响应✅ 多种⚠️ 有限
超时控制✅ 单次+总计
进度追踪✅ 上传+下载✅ 仅上传
Schema 校验✅ Standard Schema
请求取消✅ AbortController✅ CancelToken✅ AbortController
Cookie 处理浏览器原生需配置✅ tough-cookie浏览器原生
CommonJS❌ 纯 ESM❌ ESM
周下载量~570 万~5000 万+~1500 万~670 万

选型建议

场景推荐
前端 SPA、追求小体积Ky 或 ofetch
大型遗留项目、需要广泛兼容Axios
纯 Node.js 服务端、需要高级功能Got
Nuxt / unjs 生态ofetch
边缘计算 / ServerlessKy
需要 Schema 校验的类型安全Ky

最佳实践

1. 使用实例封装 API 层

// lib/api.ts
import ky from 'ky';
 
export const api = ky.create({
  prefix: import.meta.env.VITE_API_BASE_URL,
  timeout: 10000,
  retry: { limit: 2 },
  hooks: {
    beforeRequest: [
      ({ request }) => {
        const token = localStorage.getItem('token');
        if (token) {
          request.headers.set('Authorization', `Bearer ${token}`);
        }
      }
    ],
    beforeError: [
      ({ error }) => {
        if (error instanceof HTTPError && error.response.status === 401) {
          // 全局处理 token 过期
          redirectToLogin();
        }
        return error;
      }
    ]
  }
});
 
// features/user/api.ts
import { api } from '@/lib/api';
import { UserSchema } from './schema';
 
export const userApi = {
  getById: (id: number) => api.get(`users/${id}`).json(UserSchema),
  list: () => api.get('users').json(UserSchema.array()),
  create: (data: CreateUserInput) =>
    api.post('users', { json: data }).json(UserSchema),
};

2. 配合 Zod 实现端到端类型安全

// schema/user.ts
import { z } from 'zod';
 
export const UserSchema = z.object({
  id: z.number(),
  name: z.string(),
  email: z.string().email(),
  role: z.enum(['admin', 'user', 'guest']),
  createdAt: z.string().datetime()
});
 
export type User = z.infer<typeof UserSchema>;
 
// api/user.ts — 返回类型自动推导,无需手动标注
const users = await userApi.list();
// users: User[]

3. 合理使用重试策略

const api = ky.create({
  retry: {
    limit: 3,
    // 仅对幂等方法重试
    methods: ['get', 'put', 'head', 'options', 'trace'],
    // 不要对 4xx 客户端错误重试
    statusCodes: [408, 429, 500, 502, 503, 504],
    // 全局超时兜底
    maxRetryAfter: 30000
  }
});

4. 利用 extend() 实现模块化

// 基础实例
const baseApi = ky.create({ prefix: 'https://api.example.com' });
 
// 认证模块
const authApi = baseApi.extend({
  prefix: 'https://api.example.com/auth',
  hooks: {
    beforeRequest: [(request) => {
      request.headers.set('X-Auth-Module', 'auth');
    }]
  }
});
 
// 用户模块(继承认证)
const userApi = authApi.extend({
  prefix: 'https://api.example.com/users'
});

技术局限与边界

1. 纯 ESM,不支持 CommonJS

Ky v2.0 是纯 ES Module 包,无法通过 require('ky') 加载。如果你的项目仍在使用 CommonJS 或旧版构建工具,需要使用 @smeijer/ky 分支或动态 import()

2. Node.js 22+ 要求

v2.0 将 Node.js 最低版本从 18 提升到 22,如果你的项目需要支持 Node.js 18 或 20,需使用 Ky v1.x。

3. 无内置请求/响应拦截器链

Ky 使用 Hooks 系统替代了 Axios 风格的拦截器链。虽然 Hooks 功能更强大,但从 Axios 迁移需要适配思维模型。

4. 非 2xx 默认报错

Ky 默认将所有非 2xx 状态码视为错误并抛出 HTTPError。如果你需要处理 4xx/5xx 响应而不触发异常,需要手动捕获:

try {
  const data = await ky.get('/endpoint').json();
} catch (error) {
  if (isHTTPError(error) && error.response.status === 404) {
    // 处理 404
  }
}

5. 空响应处理变更

v2.0 中,.json() 在遇到空响应体和 204 响应时会抛出错误,不再像 v1.x 那样静默返回空字符串。

Ky 依赖浏览器原生的 Cookie 处理机制,不提供像 tough-cookie 这样的跨域 Cookie 管理。Node.js 环境下需要自行配置。

7. 社区生态规模

相比 Axios 的 5000 万+ 周下载量,Ky 的 ~570 万下载量虽然可观,但第三方插件、教程、Stack Overflow 问答资源相对较少。

学习资源

官方资源

技术文章

社区讨论

2026 年现状

版本状态

截至 2026 年 7 月,Ky 的最新稳定版本为 v2.0.2(2026-04-21 发布)。v1.x 系列最后版本为 v1.13.x(2025 年 10 月),仍可通过 npm 安装使用,但不再积极开发新功能。

社区增长

  • GitHub Stars:~17,000,持续稳步增长
  • npm 周下载量:~570 万次,在轻量级 HTTP 客户端中处于领先地位
  • 维护活跃度:98+ 个版本发布,488+ 次提交,2026 年仍有持续更新

行业趋势

  1. Fetch API 成为标准:随着 Node.js 22+ 原生支持 Fetch API,基于 Fetch 构建的 HTTP 客户端(如 Ky)获得越来越强的平台支持
  2. 供应链安全意识提升:2026 年 3 月的 Axios 供应链攻击事件让更多团队关注零依赖库的价值,Ky 的零依赖设计成为竞争优势
  3. Schema 校验成为标配:Ky 2.0 内置 Standard Schema 响应校验,与 tRPC、Zod 等类型安全生态深度融合
  4. 边缘计算普及:Ky 的零依赖、纯 ESM、跨运行时特性使其成为边缘计算场景的首选 HTTP 客户端之一
  5. 从 Axios 迁移:越来越多团队开始评估从 Axios 向 Ky 迁移,特别是在新项目和对 bundle 大小敏感的场景中

迁移建议

当前方案迁移到 Ky 的考量
Axios → Ky主要变化:拦截器 → Hooks、CancelToken → AbortController、默认报错行为一致。收益:体积减少 ~70%、零依赖、Schema 校验
Fetch 原生 → Ky几乎无缝迁移,Ky 兼容 Fetch API。收益:自动重试、超时、Hooks
Got → Ky如项目同时运行于浏览器和 Node.js,Ky 可统一两端。纯 Node.js 场景 Got 功能更全
ofetch → Ky非 Nuxt/unjs 生态项目,Ky 的 Hooks 系统更强大