Node.js v21, the latest Node update, is now available as a stable release. It supersedes v20 in the 'Current' release line, which has been promoted to the long-term support (LTS) channel as of 24 October.
This new version stabilizes the fetch
and WebStreams
API, adds a built-in
WebSocket client, improves support for ES modules, and brings some notable
performance improvements (as well as a customary update of Node.js dependencies
such as V8).
Without further ado, let's jump in and see what Node 21 has in store for us!
Stable Fetch API Status
A browser-compatible implementation of the Fetch API was introduced in Node.js
in v17.5.0 through an --experimental-fetch
flag, which brought the fetch
,
Headers
, Request
, and Response
globals. From v18.x to v20.x, the flag was
no longer required (but the Fetch API continued to be marked as experimental).
With the release of Node.js 21, the Fetch API is finally promoted to stable status. If you've hesitated to use Fetch due to its experimental nature, you can now confidently adopt it in your applications:
const res = await fetch("https://jsonplaceholder.typicode.com/todos/1"); if (res.ok) { const data = await res.json(); console.log(data); }
Web Streams API Is Stable
The Fetch API implementation is dependent on the AbortController
interface
(for aborting fetch requests) and a browser-compatible
Web Streams API, which were both added
in v15.0.0 and v16.5.0, respectively. While AbortController
quickly became
stable in v15.4.0, the Web Streams API has only just been stabilized in v21.
import { TextDecoderStream } from "node:stream/web"; async function streamExample() { const response = await fetch("https://jsonplaceholder.typicode.com/todos/1"); const stream = response.body; const textStream = stream.pipeThrough(new TextDecoderStream()); for await (const chunk of textStream) { console.log(chunk); } } streamExample();
Note that the older Node.js streams API
hasn't been deprecated or removed. It will co-exist with the new API, and it
even provides a way to convert from a web stream and vice versa using the
.fromWeb()
and .toWeb()
methods (both added in
Node 17,
although both methods still retain their experimental status).
A Built-in WebSocket Client
Node.js continues its trend of implementing standard web platform APIs with the
recent addition of the --experimental-websocket
flag, introducing a
WebSocket
global, as
standardized by WHATWG.
This latest effort complements existing web platform APIs such as the
aforementioned Fetch and Web Streams APIs, AbortController
APIs, the
WHATWG URL parser,
EventTarget,
Web Crypto API,
and more.
// index.js const socket = new WebSocket("ws://localhost:8080"); socket.addEventListener("open", (event) => { socket.send("Hello Server!"); }); socket.addEventListener("message", (event) => { console.log("Message from server ", event.data); });
While it's currently not recommended for production use, you can start experimenting with it right away:
node --experimental-websocket index.js
ES Modules Improvements
Node.js 21 introduces a new --experimental-default-type
flag that allows you
to modify the default behavior for input files not explicitly defined as ES
modules or CommonJS. Prior to this update, such input was implicitly interpreted
as CommonJS. With --experimental-default-type=module
, you can enable a
complete ES module implementation in the following scenarios:
- String input provided via
--eval
orSTDIN
, if--input-type
is unspecified. - Files ending in
.js
or with no extension, if there is nopackage.json
or the nearest parentpackage.json
field lacks a type field (except if innode_modules
).
node --experimental-default-type=module index.js
These improvements pave the way to eventually supporting ES module syntax by default with minimal breaking changes.
Test Runner Improvements
Building on its stabilization in Node.js v20, the native test runner undergoes further enhancements in version 21.
It now supports glob expressions, allowing you to easily match multiple test files using custom glob patterns besides the predefined defaults.
node --test **/*.test.js **/*.spec.js
Module Customization Improvements
This release simplifies module customization by removing the confusing
globalPreload
hook in favor of the
register API for sending
data from the application thread to the customization hooks, and the
initialize hook to establish
communication channels between threads.
llhttp v9.1.2 Strict Mode Enforcement
In the llhttp v9.1.2 update for Node.js, strict mode enforcement was introduced as the default setting, enabling previously included strict mode features for enhanced code reliability and security.
Notable changes include a mandatory \r\n
presence after headers and chunks,
ensuring consistent data processing, and disallowing data transmission after a
message with the Connection: close
header, improving protocol adherence and
connection handling.
To maintain backward compatibility with older releases, you can use the
--insecure-http-parser
flag to disable these changes.
Performance Improvements to Key APIs
The Node.js performance team landed a few key improvements in this release:
- The Streams API underwent optimizations, achieving approximately a 10% speedup by eliminating redundant checks, utilizing bitmaps, and scheduling callbacks more efficiently.
- When uncorking a response, splitting chunked responses into multiple parts is avoided, which helps reduce unnecessary overhead on both the client and server side.
V8 Upgraded to v11.8
The V8 engine has been upgraded to v11.8, which brings improved performance and the following JavaScript features:
- Array grouping to combine like data into groups using
Object.groupBy()
andMap.groupBy()
. - A new programmatic API (
ArrayBuffer.prototype.transfer
) for transferring ownership of ArrayBuffers, optimized reallocations, and fixing resizable ArrayBuffers into fixed-length ones. - WebAssembly extended-const expressions.
NPM Upgraded to v10.2.0
Node.js v21 includes
npm v10.2.0, which notably
introduces a new sbom
command that allows you to generate a Software Bill of
Materials (SBOM) for the current project. You can read more about
the changes in recent NPM releases on
GitHub.
Node.js 21 Miscellaneous Updates
Other features and improvements available in this release include the following:
- A partial implementation of the global
navigator
object, allowing access to hardware concurrency information vianavigator.hardwareConcurrency
. - A
flush
option is added to thefs.writeFile()
family of functions to guarantee that data is flushed to disk at the end of a successful write operation. This prevents redundant data from being read.
Should You Use Node.js v21 in Production?
You probably shouldn't use Node.js v21 in production. As an odd-numbered October release, it will only be supported for one year, unlike the April even-numbered releases (16, 18, 20, etc.), which receive long-term updates for up to three years.
Upgrading to Node.js v21
Should you wish to install or upgrade to Node.js v21, use the relevant link for your operating system and architecture on the Node.js download page.
Alternatively, a better way to manage Node.js releases on your machine is to use an environment management tool like Volta that can install and switch between multiple versions seamlessly.
After installing the Volta CLI, run the command below to install the latest version of Node.js:
volta install node@latest success: installed and set node@21.0.0 (with npm@10.2.0) as default
Wrapping Up
Node.js v21 introduces numerous improvements in tooling, language features, standard library additions, and performance optimizations, enhancing its position as a robust JavaScript runtime and aligning it more closely with modern alternatives like Deno and Bun.
You can examine the complete list of bug fixes, new features, and other changes in the official Node.js 21 release notes.
To learn more about the Node.js community and how you can contribute, check out the project's open issues and contribution guidelines on GitHub.
Thanks for reading!
P.S. If you liked this post, subscribe to our JavaScript Sorcery list for a monthly deep dive into more magical JavaScript tips and tricks.
P.P.S. If you need an APM for your Node.js app, go and check out the AppSignal APM for Node.js.