Node.js 20: Unleashing New Possibilities

Alex
5 min readJun 26, 2023

--

Welcome to the exciting world of Node.js 20! As a seasoned developer, you know that each new release brings a wave of innovation and possibilities. In this article, we’ll dive into the notable changes introduced in Node.js 20 and explore how you can leverage them to enhance your projects. So fasten your seatbelt and let’s embark on this thrilling journey! 🚀

The Node.js Permission Model

🔒 One of the most significant additions in Node.js 20 is the introduction of the Node.js Permission Model. This experimental feature allows developers to restrict access to specific resources during execution. You now have more control over file system access using the --allow-fs-read and --allow-fs-write flags. Let's take a look at an example:

$ node --experimental-permission --allow-fs-read=* --allow-fs-write=* index.js

With this command, you grant read and write access to the entire file system. You can also specify specific paths for file system access:

$ node --experimental-permission --allow-fs-write=/tmp/ --allow-fs-read=/home/index.js index.js

Additionally, wildcard patterns can be used to allow access to multiple files or folders:

$ node --experimental-permission --allow-fs-read=/home/test* index.js

By enabling the Permission Model, you gain the ability to check permissions at runtime using the process.permission.has() method. Exciting, right? Just remember, these features are still experimental and subject to change in future releases of Node.js.

Custom ESM Loader Hooks Nearing Stable

🔌 Custom ES module (ESM) lifecycle hooks supplied via loaders have received a significant improvement in Node.js 20. These hooks now run in a dedicated thread, isolated from the main thread, ensuring no cross-contamination between loaders and application code. Moreover, the import.meta.resolve() method now returns synchronously, aligning with browser behavior. Let's see an example:

import { test, mock } from 'node:test';
import assert from 'node:assert';
import fs from 'node:fs';

mock.method(fs, 'readFile', async () => "Hello World");
test('synchronous passing test', async (t) => {
assert.strictEqual(await fs.readFile('a.txt'), "Hello World");
});

These improvements pave the way for more widespread adoption of ESM, enabling the development of powerful analytics and reporting libraries.

V8 11.3: Turbocharging Performance

⚡️ Node.js 20 comes bundled with the latest version of the V8 JavaScript engine, version 11.3. This update brings enhanced performance and exciting new language features. Notable improvements include:

  • String.prototype.isWellFormed and toWellFormed: New methods for handling string well-formedness.
  • Array and TypedArray methods that change the original object by copy.
  • Resizable ArrayBuffer and growable SharedArrayBuffer.
  • RegExp v flag with set notation and additional string properties.
  • WebAssembly Tail Call: An optimized mechanism for function calls within WebAssembly modules.

This update, contributed by Michaël Zasso, ensures that your Node.js applications run at blazing speed and benefit from the latest language enhancements.

Stable Test Runner for Hassle-free Testing

🏃‍♂️ Testing is an integral part of software development, and Node.js 20 makes it even easier with the stable test runner module. The test runner includes essential building blocks for authoring and running tests, such as the ability to structure test files using describe, it/test, and hooks, as well as support for mocking, watch mode, and parallel execution of multiple test files using node --test. Let's take a quick look at an example:

import { test, mock } from 'node:test';
import assert from 'node:assert';
import fs from 'node:fs';

mock.method(fs, 'readFile', async () => "Hello World");
test('synchronous passing test', async (t) => {
assert.strictEqual(await fs.readFile('a.txt'), "Hello World");
});

With the stable test runner, you can write reliable tests and ensure the quality of your codebase with ease. Please note that some parts, such as reporters and code coverage, are still under development.

Performance Boost: The Need for Speed

⚡️ With the formation of the Node.js Performance team, Node.js 20 brings a renewed focus on performance enhancements. The fundamental parts of the runtime, including URL, fetch(), and EventTarget, have undergone significant improvements. Let’s take a closer look at some of the advancements:

  • EventTarget: The cost of initializing EventTarget has been cut in half, resulting in faster access to all subsystems utilizing it.
  • V8 Fast API calls: Leveraging V8 Fast API calls has improved performance in APIs like URL.canParse() and timers.
  • Ada 2.0: Node.js 20 incorporates Ada 2.0, an updated and lightning-fast URL parser written in C++.

The Node.js Performance team continues to explore new avenues to enhance performance. They are actively seeking contributors who share a passion for squeezing every bit of performance out of Node.js.

Single Executable Apps Made Easy

📦 Node.js has been working on support for Single Executable Applications (SEA), and Node.js 20 introduces an exciting advancement in this area. Building a single executable app now requires injecting a blob prepared by Node.js from a JSON config instead of injecting the raw JS file. Let’s see an example:

// sea-config.json
{
"main": "hello.js",
"output": "sea-prep.blob"
}

Running the following command generates the blob:

$ node --experimental-sea-config sea-config.json

The injected blob enables the possibility of embedding multiple co-existing resources into SEA, opening up new use cases. This feature, contributed by Joyee Cheung, offers developers more flexibility and control over their applications.

Interoperability with Web Crypto API

🔐 Node.js strives for interoperability with other JavaScript environments, and Node.js 20 takes a significant step in that direction by aligning with the Web Crypto API. The Web Crypto API functions’ arguments are now coerced and validated according to their WebIDL definitions, improving interoperability with other Web Crypto API implementations. This ensures a seamless experience when working with cryptographic operations across different environments.

Official Support for ARM64 Windows

💪 Node.js aims to run everywhere, and it’s now official: Node.js includes binaries for ARM64 Windows! This means you can execute Node.js natively on the ARM64 Windows platform. The availability of MSI, zip/7z packages, and executables on the Node.js download site ensures compatibility and prevents regressions. Thanks to the dedicated efforts of Stefan Stojanovic, ARM64 Windows has been upgraded to tier 2 support, expanding Node.js’s platform reach.

Progress on Web Assembly System Interface (WASI)

🔨 The Node.js project is making steady progress on the Web Assembly System Interface (WASI) implementation. WASI allows running WebAssembly modules outside the browser and provides access to system-level functionality in a secure and portable manner. With the goal of enabling Node.js to become a full-fledged WASI host, work on integrating WASI with Node.js continues, bringing exciting opportunities for developers interested in running WebAssembly modules on the server side.

Conclusion

🎉 Node.js 20 is a game-changer, introducing groundbreaking features and enhancements that empower developers to create faster, more secure, and highly performant applications. From the new Permission Model to the stable test runner, each addition brings us closer to a more efficient and enjoyable development experience.

Don’t miss out on the action! Follow me on Medium for more exciting updates and deep dives into the world of Node.js and JavaScript. Let’s continue this exhilarating journey together!

--

--

Alex

Senior Frontend Engineer 🌟 Proven track record launching web apps 🤖 ChatGPT enthusiast 🚀 React, Next.js, TypeScript 🎨 UI/UX expert 💼 Open to opportunities