What Is New in Node.js 18?
| Category | Change |
|---|---|
| New Features | fetch() API enabled globally (experimental, no flag needed) |
| New Features | node:test built-in test runner module |
| New Features | Web Streams API (ReadableStream, WritableStream, TransformStream) |
| New Features | Blob URL support via URL.createObjectURL(blob) |
| Improvements | V8 10.2 -- class static blocks, Array.findLast, Error.cause |
| Improvements | --experimental-fetch officially named and included |
| Improvements | OpenSSL 3.0 LTS bundled |
| Security | npm 8.6.0 |
| Deprecated | url.parse() documented as legacy |
Global fetch() -- HTTP Requests Without npm install
Node.js 18 includes fetch() in the global scope without any import. Under the hood it uses the undici library. You can make HTTP/HTTPS requests from server-side code using the exact same API as browsers.
const res = await fetch('https://api.example.com/data');
const json = await res.json();
console.log(json);
This marks a shift in Node.js philosophy -- instead of npm packages filling browser API gaps, Node itself ships those APIs. The node-fetch package remains relevant for older versions but is no longer needed in v18+.
Built-in Test Runner -- node:test
The node:test module provides a native test runner with TAP output, subtests, and async support. No Jest, Mocha, or Tap install required for simple test suites.
import test from 'node:test';
import assert from 'node:assert';
test('adds correctly', () => {
assert.strictEqual(1 + 1, 2);
});
test('async test', async () => {
const result = await Promise.resolve(42);
assert.strictEqual(result, 42);
});
For v18 this is experimental, but the API is stable enough to use for new projects. The runner integrates with node:assert and produces TAP output readable by most CI systems.
Web Streams API in Node.js Core
WHATWG Streams (ReadableStream, WritableStream, TransformStream) are available as globals in Node.js 18. These are the same streaming primitives used in browsers, enabling isomorphic streaming code.
The connection between Node.js stream.Readable/stream.Writable and the WHATWG streams is handled via stream.Readable.toWeb() and stream.Readable.fromWeb().
New JavaScript Features via V8 10.2
Class static initialization blocks let you run setup code inside a class body. Array.prototype.findLast() and findLastIndex() search from the end of an array. Error.cause lets you chain error context without losing the original error.
const arr = [1, 2, 3, 4];
console.log(arr.findLast(x => x % 2 === 0)); // 4
try { /* ... */ } catch (err) {
throw new Error('DB query failed', { cause: err });
}
FAQ
Is fetch() in Node.js 18 fully compatible with browser fetch?
Mostly, but there are known gaps -- for example, no support for credentials in the cookie jar or service workers. For most API calls it works identically to browser fetch.
Should I switch from Jest to node:test in Node.js 18?
Not necessarily. For v18, node:test is still experimental and lacks mocking, snapshot testing, and rich matchers. Jest and Vitest remain better choices for complex test suites.
Does OpenSSL 3.0 in Node.js 18 break any cipher compatibility?
Yes -- some older, legacy ciphers (MD4, some 3DES modes) are disabled by default in OpenSSL 3.0. If your app depends on these for TLS or hashing, you may need to update your crypto configuration.
Is Node.js 18 an LTS version?
Yes. Node.js 18 is an LTS release (codename "Hydrogen") with active support until April 2025 and security updates until April 2027.
Can I stream a fetch() response directly to a file?
Yes. Use response.body (a ReadableStream) and pipe it through stream.Readable.fromWeb() into a fs.createWriteStream().