Node.js 18 was first released back in April this year and it’s becoming the Active LTS (Long Term Support) version on 25th October 2022.
At NearForm we have settled on a policy which recommends using the Active LTS for new development, so we’re getting ready to migrate our active internal projects and start new ones on Node 18.
You can learn more about the Node.js release schedule here
Node 18 comes with lots of internal improvements and a few user facing new features, which we’re going to cover in this article.
Global browser APIs
As language and APIs evolve, there has also been an ongoing effort to standardize the ways similar operations are done in code running in a browser environment and in a Node.js application. Typical examples of that are sending HTTP requests and streaming data.
Node 18 improves this by introducing support for global browser APIs, meaning that nearly-identical code can now be used for certain activities regardless of whether it’s running in the server or the client, and that these APIs are accessible globally, without importing any modules.
Experimental support for global fetch
Node 18 introduces support for the global fetch API, the familiar feature we’ve come to love in the browser, which avoids using the low-level XMLHttpRequest object or external libraries such as axios.
The built-in Node.js HTTP client isn’t very user-friendly and a common option was to rely on external libraries such as node-fetch.
Node 18 introduces experimental support for a global fetch function, which is built on top of undici and aims at being compliant with the Fetch standard.
Experimental support for global Web Streams
Streams existed in Node.js long before they were introduced in browsers. Unfortunately the browser’s Stream API is considerably different, so Node.js tried to fill the gaps by providing a browser-compatible Web Streams API. Web Streams were already available in Node.js, but version 18 makes them accessible in the global namespace.
Here’s a fairly convoluted way of turning a string to upper case using Web Streams.
Experimental test runner module
Similar to the fragmentation of APIs for sending HTTP requests, testing tooling is also a rich part of the Node.js ecosystem, which comes with advantages and disadvantages.
Many testing frameworks are available and many have seen a rise and fall in adoption over the years. These days our general approach at NearForm is to test purely Node.js code using tap and purely frontend code using Jest.
We’re never too prescriptive and we trust our teams to choose what works best for them. As an example, it’s very common to see a monorepo containing both frontend and backend code using a single testing framework, because consistency is also an important quality in a codebase.
Node.js 18 introduces a novelty, a new node:test module inspired by tap.
A quick digression on module prefixes is in order.
The node:test module is only available with the node: prefix, and it’s the first-ever Node.js module to exhibit this behavior.
Prefixes were introduced to remove ambiguity and risk of loading unintended, possibly malicious, modules.
Using the testing module
The API of the testing module is largely similar to that of tap, although many advanced features are still missing, for example module mocks and fixtures.
What else is there?
Node.js 18 comes with a long list of other improvements, although most of them are not immediately relevant for end users. Check them out in the official announcement.