📦nodejs / undici
← 返回首页
An HTTP/1.1 client, written from scratch for Node.js
⚖️ MIT#nodejs#http#client🌐 undici.nodejs.org📅 创建于 2018-05-11🔄 更新于 2026-10-29
🔗 GitHub JavaScript

📄 仓库 README

在 GitHub 查看 ↗
来自 GitHub 仓库自述文件 · 版权归原作者所有

undici

Node CI neostandard javascript style npm version codecov

An HTTP/1.1 client, written from scratch for Node.js.

Undici means eleven in Italian. 1.1 -> 11 -> Eleven -> Undici. It is also a Stranger Things reference.

How to get involved

Have a question about using Undici? Open a Q&A Discussion or join our official OpenJS Slack channel.

Looking to contribute? Start by reading the contributing guide

Install

npm i undici

Benchmarks

The benchmark is a simple getting data example using 50 TCP connections with a pipelining depth of 10 running on Node 24.14.1.

HTTP/1.1

┌────────────────────────┬─────────┬────────────────────┬────────────┬─────────────────────────┐
│  Tests                 │ Samples │ Result             │ Tolerance  │ Difference with slowest │
├────────────────────────┼─────────┼────────────────────┼────────────┼─────────────────────────┤
│  'node-fetch'          │ 50      │ '4711.86 req/sec'  │ '± 2.92 %' │ '-'                     │
│  'undici - fetch'      │ 75      │ '5438.50 req/sec'  │ '± 2.97 %' │ '+ 15.42 %'             │
│  'axios'               │ 45      │ '5448.08 req/sec'  │ '± 2.98 %' │ '+ 15.62 %'             │
│  'request'             │ 65      │ '5809.63 req/sec'  │ '± 2.90 %' │ '+ 23.30 %'             │
│  'http - no keepalive' │ 35      │ '5910.77 req/sec'  │ '± 2.87 %' │ '+ 25.44 %'             │
│  'got'                 │ 50      │ '6047.80 req/sec'  │ '± 2.91 %' │ '+ 28.35 %'             │
│  'superagent'          │ 60      │ '7534.53 req/sec'  │ '± 2.97 %' │ '+ 59.91 %'             │
│  'http - keepalive'    │ 75      │ '9343.41 req/sec'  │ '± 2.90 %' │ '+ 98.30 %'             │
│  'undici - pipeline'   │ 65      │ '13470.70 req/sec' │ '± 2.93 %' │ '+ 185.89 %'            │
│  'undici - request'    │ 80      │ '16850.87 req/sec' │ '± 2.93 %' │ '+ 257.63 %'            │
│  'undici - stream'     │ 101     │ '18488.56 req/sec' │ '± 3.81 %' │ '+ 292.38 %'            │
│  'undici - dispatch'   │ 101     │ '20786.44 req/sec' │ '± 3.08 %' │ '+ 341.15 %'            │
└────────────────────────┴─────────┴────────────────────┴────────────┴─────────────────────────┘

HTTP/1.1 over HTTPS

Using benchmark-https.js against an h1-over-TLS server (50 connections, pipelining depth 10, Node 24.14.1).

┌────────────────────────┬─────────┬───────────────────┬────────────┬─────────────────────────┐
│  Tests                 │ Samples │ Result            │ Tolerance  │ Difference with slowest │
├────────────────────────┼─────────┼───────────────────┼────────────┼─────────────────────────┤
│  'https - no keepalive'│ 10      │ '1358.40 req/sec' │ '± 1.99 %' │ '-'                     │
│  'undici - fetch'      │ 30      │ '3721.76 req/sec' │ '± 2.97 %' │ '+ 173.98 %'            │
│  'https - keepalive'   │ 35      │ '5633.91 req/sec' │ '± 2.84 %' │ '+ 314.75 %'            │
│  'undici - pipeline'   │ 15      │ '6254.05 req/sec' │ '± 2.80 %' │ '+ 360.40 %'            │
│  'undici - request'    │ 25      │ '6669.80 req/sec' │ '± 2.73 %' │ '+ 391.01 %'            │
│  'undici - stream'     │ 25      │ '7019.04 req/sec' │ '± 2.77 %' │ '+ 416.71 %'            │
│  'undici - dispatch'   │ 20      │ '7361.85 req/sec' │ '± 2.90 %' │ '+ 441.95 %'            │
└────────────────────────┴─────────┴───────────────────┴────────────┴─────────────────────────┘

HTTP/2

Using benchmark-http2.js against an h2 server (50 connections, pipelining depth 10, Node 24.14.1).

┌────────────────────────┬─────────┬───────────────────┬────────────┬─────────────────────────┐
│  Tests                 │ Samples │ Result            │ Tolerance  │ Difference with slowest │
├────────────────────────┼─────────┼───────────────────┼────────────┼─────────────────────────┤
│  'undici - fetch'      │ 45      │ '3499.03 req/sec' │ '± 2.93 %' │ '-'                     │
│  'native - http2'      │ 25      │ '4904.58 req/sec' │ '± 2.81 %' │ '+ 40.17 %'             │
│  'undici - pipeline'   │ 60      │ '5836.82 req/sec' │ '± 2.99 %' │ '+ 66.81 %'             │
│  'undici - request'    │ 65      │ '6831.25 req/sec' │ '± 2.83 %' │ '+ 95.23 %'             │
│  'undici - stream'     │ 55      │ '6874.30 req/sec' │ '± 2.91 %' │ '+ 96.46 %'             │
│  'undici - dispatch'   │ 55      │ '7791.23 req/sec' │ '± 2.96 %' │ '+ 122.67 %'            │
└────────────────────────┴─────────┴───────────────────┴────────────┴─────────────────────────┘

Undici vs. Fetch

Overview

Node.js includes a built-in fetch() implementation powered by undici starting from Node.js v18. However, there are important differences between using the built-in fetch and installing undici as a separate module.

WebAssembly requirement

Undici's HTTP/1 parser requires WebAssembly. There is no alternative parser when WebAssembly is unavailable, for example in Node.js configurations where --jitless disables it. The existence of fetch does not imply that it can make HTTP/1 requests in that environment.

When the HTTP/1 parser is needed without WebAssembly, Client and dispatcher requests fail with an Error whose code is ERR_WEBASSEMBLY_NOT_SUPPORTED. fetch rejects with a TypeError carrying that error in error.cause. Importing Undici, accessing fetch, and using Headers, FormData, Request, or Response do not themselves require the HTTP/1 parser.

The error is defined locally in Undici and does not depend on Node.js providing that error code. For built-in fetch, this behavior depends on the bundled Undici version. Node.js receives upstream fixes through its normal vendored Undici update, rather than changes to the generated bundle alone.

Built-in Fetch (Node.js v18+)

Node.js's built-in fetch is powered by a bundled version of undici:

// Available globally in Node.js v18+
const response = await fetch('https://api.example.com/data');
const data = await response.json();

// Check the bundled undici version
console.log(process.versions.undici); // e.g., "5.28.4"

Pros: - No additional dependencies required - Works across different JavaScript runtimes - Automatic compression handling (gzip, deflate, br) - Built-in caching support (in development)

Cons: - Limited to the undici version bundled with your Node.js version - Less control over connection pooling and advanced features - Error handling follows Web API standards (errors wrapped in TypeError) - Performance overhead due to Web Streams implementation

Undici Module

Installing undici as a separate module gives you access to the latest features and APIs:

npm install undici
import { request, fetch, Agent, setGlobalDispatcher } from 'undici';

// Use undici.request for maximum performance
const { statusCode, headers, body } = await request('https://api.example.com/data');
const data = await body.json();

// Or use undici.fetch with custom configuration
const agent = new Agent({ keepAliveTimeout: 10000 });
setGlobalDispatcher(agent);
const response = await fetch('https://api.example.com/data');

Pros: - Latest undici features and bug fixes - Access to advanced APIs (request, stream, pipeline) - Fine-grained control over connection pooling - Better error handling with clearer error messages - Superior performance, especially with undici.request - HTTP/1.1 pipelining support - Custom interceptors and middleware - Advanced features like ProxyAgent, Socks5Agent, MockAgent

Cons: - Additional dependency to manage - Larger bundle size

When to Use Each

Use Built-in Fetch When:

  • You want zero dependencies
  • Building isomorphic code that runs in browsers and Node.js
  • Publishing to npm and want to maximize compatibility with JS runtimes
  • Simple HTTP requests without advanced configuration
  • You're publishing to npm and you want to maximize compatibility
  • You don't depend on features from a specific version of undici

Use Undici Module When:

  • You need the latest undici features and performance improvements
  • You require advanced connection pooling configuration
  • You need APIs not available in the built-in fetch (ProxyAgent, Socks5Agent, MockAgent, etc.)
  • Performance is critical (use undici.request for maximum speed)
  • You want better error handling and debugging capabilities
  • You need HTTP/1.1 pipelining or advanced interceptors
  • You prefer decoupled protocol and API interfaces

Performance Comparison

Based on benchmarks, here's the typical performance hierarchy:

  1. undici.request() - Fastest, most efficient
  2. undici.fetch() - Good performance, standard compliance
  3. Node.js http/https - Baseline performance

Migration Guide

If you're currently using built-in fetch and want to migrate to undici:

// Before: Built-in fetch
const response = await fetch('https://api.example.com/data');

// After: Undici fetch (drop-in replacement)
import { fetch } from 'undici';
const response = await fetch('https://api.example.com/data');

// Or: Undici request (better performance)
import { request } from 'undici';
const { statusCode, body } = await request('https://api.example.com/data');
const data = await body.json();

Keep fetch and FormData together

When you send a FormData body, keep fetch and FormData from the same implementation.

Use one of these patterns:

// Built-in globals
const body = new FormData()
body.set('name', 'some')
await fetch('https://example.com', {
  method: 'POST',
  body
})
// undici module imports
import { fetch, FormData } from 'undici'

const body = new FormData()
body.set('name', 'some')
await fetch('https://example.com', {
  method: 'POST',
  body
})

If you want the installed undici package to provide the globals, call install() first:

import { install } from 'undici'

install()

const body = new FormData()
body.set('name', 'some')
await fetch('https://example.com', {
  method: 'POST',
  body
})

install() replaces the global fetch, Headers, Response, Request, and FormData implement

📈 近 7 天 Star 趋势

每日新增 Star(柱)与累计 Star(线)· 数据来自 GitHub

🏆 排名变化趋势

在各榜单中的排名历史(数字越小越靠前)

📋 历史上榜记录

每次快照的详细数据
日期 榜单 排名 周期新增 总 STAR