Exploring competitive features in Node.js v18 and v19
Tags: node, webdev
Published: 2022-12-06 20:23:17

**Written by [Stanley Ulili](https://blog.logrocket.com/author/stanleyulili/)✏️**


Node.js has been a popular JavaScript runtime since its release in 2009\. But the advent of two new runtimes, [Deno](https://deno.land/) and [Bun](https://bun.sh/), has brought a lot of hype for the new features they present in contrast to Node. 

From afar, it may seem like Node.js is stagnating and nothing exciting is happening — but the reality is different. Two recent Node.js releases, v18 and v19, came with a lot of significant features:

*   Experimental support for browser APIs, such as [Fetch](https://blog.logrocket.com/fetch-api-node-js/) and the web streams API
*   An experimental, inbuilt test runner
*   Support for the recent version of Chromium's V8 engine
*   Experimental support for `watch` mode, which replaces a tool like [nodemon](https://www.npmjs.com/package/nodemon)

In this tutorial, we will explore the following cool new features in Node.js v18 and v19:

*   [Node.js v18 features](#node-js-v18-features)
    *   [Inbuilt Fetch API](#inbuilt-fetch-api)
    *   [Inbuilt test runner mode](#inbuilt-test-runner-mode)
    *   [Web Streams API support](#web-streams-api-support)
    *   [Building binaries with the snapshot feature](#building-binaries-snapshot-feature)
    *   [V8 engine upgraded to v10.1](#v8-engine-upgraded-v10-1)
*   [`watch` mode and other Node.js v19 features](#watch-mode-node-js-v19-features)
    *   [HTTP(S)/1.1 KeepAliveby default](#KeepAliveby-default)

## Node.js v18 features <a name="node-js-v18-features">

Node.js v18 was released on April 19, 2022, and became a current release through October 2022, when Node.js v19 was released. A current release means that the version gains non-breaking features from a newer version of Node.js. 

Node.js v18 gained the `watch` mode feature, which was backported in Node v18 when v19 was released. On October 25, 2022, Node.js v18 was promoted to LTS (long-term support) and will continue receiving support until 2025. 

The following are some of the features that are available in Node.js v18.

### Inbuilt Fetch API

Before Node.js v18, you had to install [node-fetch](https://github.com/node-fetch/node-fetch) or [Axios](https://axios-http.com/) to request a resource from a server. With Node.js v18, you no longer need to install either package thanks to v18’s experimental Fetch API, which is available globally. 

Let's look at how to use the Fetch API in Node.js v18\. First, create a `getData.js` file and add the following function that sends a request to an API:

```javascript
async function fetchData() {
  const response = await fetch(
    "https://random-data-api.com/api/name/random_name"
  );
  if (response.ok) {
    const data = await response.json();
    console.log(data);
  }
}

fetchData();
```

Save the file contents, then run the file with the `node` command:

```bash
node getData.js
```

When the command runs, the output will look like the following:

```plaintext
(node:29835) ExperimentalWarning: The Fetch API is an experimental feature. This feature could change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
{
  id: 6638,
  uid: '75026571-e272-4298-b2c0-c3e9e6363437',
  name: 'Candy Kane',
  ...
  prefix: 'Rep.',
  initials: 'LBS'
}
```

In the output, Node.js logs a warning that the Fetch API is experimental. After the warning, we see the JSON data that the API returned.

### Inbuilt test runner module <a name="inbuilt-test-runner-mode">

Developers typically use unit testing to test software components. From the early releases of Node.js, we could write simple tests with the [`assert` library](https://nodejs.org/api/assert.html). But as our tests grew larger, so did our need to organize tests and write descriptive messages. 

As a solution, test runners such as [Jest](https://jestjs.io/), [Jasmine](https://jasmine.github.io/), and [Mocha](https://mochajs.org/) emerged, and have been the go-to tools for unit testing. 

With the release of Node.js v18, a test runner is now included in Node.js and can be accessed with:

```javascript
import test from 'node:test';
```

Note that we are using the `node:` scheme to import the module. You can also use CommonJS:

```javascript
const test = require('node:test')
```

Let's learn how to use it. First, initialize npm with the following:

```bash
npm init -y
```

In your `package.json` file, enable the ES modules:

```json
{
  ...
  "license": "ISC"
  "type": "module",
}
```

Next, create a `math.js` file and add a function that returns the result of adding two numbers:

```javascript
const sum = (a, b) => {
  return a + b;
};

export default sum;
```

To test the function with the Node.js test runner, create a `test.js` file with the following content:

```javascript
import test from "node:test";
import assert from "assert/strict";
import sum from "./math.js";

test("Sum function", async (t) => {
  await t.test("It should add two numbers", () => {
    assert.equal(sum(2, 2), 4);
  });
  await t.test("It should not subtract numbers", () => {
    assert.notEqual(sum(3, 2), 1);
  });
});
```

In the first line, we import the test runner. In the second line, we import the `assert` library, and subsequently, the `sum()` function in the `math.js` file. 

After that, we create a test case that has two subtests, which test if the `sum()` function works properly. 

Now, run the tests:

```bash
node test.js
```

Your output will look like the following:

```plaintext
TAP version 13
# Subtest: Sum function
    # Subtest: It should add two numbers
    ok 1 - It should add two numbers
      ---
      duration_ms: 1.171389
      ...
    # Subtest: It should not subtract numbers
    ok 2 - It should not subtract numbers
      ---
      duration_ms: 0.279246
      ...
    1..2
ok 1 - Sum function
  ---
  duration_ms: 5.522232
  ...
1..1
# tests 1
# pass 1
# fail 0
# cancelled 0
# skipped 0
# todo 0
```

In the output, we can see that Node.js has description messages of the tests that run.

### Web Streams API support <a name="web-streams-api-support">

The Web Streams API is an experimental feature in Node.js that lets you break a large file, like a video or text file, into smaller chunks that can be consumed gradually. This helps avoid memory issues. In older versions of Node.js, you could use [Node.js streams](https://blog.logrocket.com/working-node-js-streams/) to consume large files. But this functionality wasn't available for JavaScript apps in the browser. Later, [WHATWG](https://streams.spec.whatwg.org/) defined the Web Streams API, which has now become the standard for streaming data in JavaScript apps. 

Node.js didn't support this API until v18\. With v18, all of the Streams API objects, such as `ReadableStream`, `WritableStream`, and `TransformStream`, are available. To learn more about how to use the Streams API, check out [the documentation](https://nodejs.org/api/webstreams.html).

### Building binaries with the snapshot feature <a name="building-binaries-snapshot-feature">

Another exciting feature is the ability to build a single-executable Node.js binary. Before Node.js v18, the only way to build a Node.js binary was to use a third-party package, like [pkg](https://github.com/vercel/pkg). 

But now, you can make use of the experimental snapshot flag `--node-snapshot-main` to build a binary. For more details on how this feature works, see [this tutorial](https://blog.logrocket.com/snapshot-flags-node-js-v18-8/).

### V8 engine upgraded to v10.1 <a name="v8-engine-upgraded-v10-1">

Node.js is built on top of the V8 engine, created by Google and maintained for Chromium to execute JavaScript. With each release, it introduces new features and some performance improvements, which end up in Node.js. 

Google released V8 10.1, which introduced some new array methods, such as `findLast()` and `findLastIndex()`, as well as [`Intl.supportedValuesOf(code)`](https://v8.dev/blog/v8-release-99#intl-enumeration). The V8 engine also added new methods to the [`Intl.Locale` API](https://v8.dev/blog/v8-release-99#intl.locale-extensions), and optimized the [class fields and private methods](https://v8.dev/blog/faster-class-features).

## `watch` mode and other Node.js v19 features <a name="watch-mode-node-js-v19-features">

Node.js v19 was released on October 18, 2022\. Since 19 is an odd number, it will never be promoted to LTS, but will continue receiving support until April 2023, when a new, even-numbered Node.js version is released. 

While Node.js v19 has not released a lot of features in comparison to Node.js v18, it has shipped one of the most requested features to past Node versions as well: `watch` mode. 

When you create and start a server in Node.js, then later make changes to the file, Node.js doesn't pick up the new changes automatically. You either need to restart the server or use a tool like [nodemon](https://blog.logrocket.com/configuring-nodemon-with-typescript/), which automatically reruns a file when it detects new changes. 

With the release of Node.js v19, this is no longer necessary. Node v19, as well as Node ≥ v 18.11.0, is now able to automatically restart a process when it detects new changes using the `node --watch` feature, which is currently experimental. 

To run a file in watch mode, use the `--watch` flag:

```bash
node --watch index.js
```

When you edit the `index.js` file, you will see that the process automatically restarts and the new changes are reflected without stopping the server. As mentioned, this feature has also been backported to Node.js ≥ v18.11.0, which means you don't have to use Node.js v19 if this is the only feature you need.

### HTTP(S)/1.1 `KeepAlive`by default <a name="KeepAliveby-default">

Node.js uses an [`http.globalAgent`](https://nodejs.org/api/http.html#class-httpagent) for outgoing HTTP connections and [`https.globalAgent`](https://nodejs.org/api/https.html#class-httpsagent) for outgoing HTTPS connections. These agents ensure TCP connection persistence as well as that HTTP clients can reuse the connections for multiple requests. 

You can configure the agents to reuse connections by setting the HTTP 1.1 [`keepAlive`](https://en.wikipedia.org/wiki/Keepalive) option to `true`; otherwise, set it to `false` to avoid reusing connections, which makes things slower. 

For Node.js version ≤18, outgoing connections for HTTP/HTTPS have the `keepAlive` option set to `fal``se`, so connections are not reused for multiple requests, leading to slower performance. With Node.js v19, the `keepAlive` option is now set to `true`, which means your outgoing connections will be faster without doing any configurations. 

Let's verify this. Assuming you are using [nvm](https://github.com/nvm-sh/nvm), you can install Node.js ≤ v18 and temporarily switch to it:

```bash
nvm install v18.12.1
node -v
// Output
// v18.12.1
```

Create a `checkHttpAlive.js` file and add the following code to inspect the `http.globalAgent`:

```javascript
const http = require('node:http');
console.log(http.globalAgent);
```

Your output will look as follows:

```plaintext
// Output
Agent {
  ...
  keepAliveMsecs: 1000,
  keepAlive: false,  // this is the keepAlive option
  ...
}
```

In the output, you will notice that `keepAlive` is set to `false` by default on Node v18. 

Let's compare it with Node.js v19\. Switch the Node.js version to v19 with nvm:

```bash
nvm install v19.0.1
node -v
// output:
// v19.0.1
```

Run the `checkHttpAlive.js` file again:

```bash
node checkHttpAlive.js
```

The output will match the following:

```plaintext
// output
Agent {
  ...
  keepAliveMsecs: 1000,
  keepAlive: true,
  ...
}
```

In the output, you can see the `keepAlive` option is set to `true` by default in Node.js v19.

### V8 engine upgrade to 10.7

The V8 Engine for Node.js v19 has been upgraded to version 10.7\. It did not ship with a lot of features — it only added the `Intl.NumberFormat` feature to the JavaScript API. 

The `Intl.NumberFormat` internationalizes a number as a currency. An example:

```plaintext
> new Intl.NumberFormat('en-US', { style: 'currency', currency: 'GBP' }).format(3392.10)
'£3,392.10'     // output
```

## Conclusion

In this article, we explored cool features in Node.js v18 and v19\. First, we looked at the new features in v18, which include the inbuilt Fetch API, a new test runner and snapshot feature, `watch` mode, and support for the Web Streams API. We then looked at new features in Node v19, which includes `watch` mode, and the HTTP 1.1 `keepAlive` feature. 

As exciting as the new Node.js features are, most of these features already exist in Bun and Deno. The runtimes also include useful features, such as native TypeScript support, web sockets API, and execute faster than Node.js. 

If you are not sure which Node.js version to use, I would recommend v18\. Its support will last until 2025, unlike Node v19, whose support will end next year. If you want to learn about these features in more depth, refer to [the documentation page](https://nodejs.org/en/docs/).

---

## 200’s only ✔️ Monitor failed and slow network requests in production

Deploying a Node-based web app or website is the easy part. Making sure your Node instance continues to serve resources to your app is where things get tougher. If you’re interested in ensuring requests to the backend or third party services are successful, [try LogRocket] (https://logrocket.com/signup/). 

[![LogRocket Network Request Monitoring](https://blog.logrocket.com/wp-content/uploads/2019/12/network-request-filter-2-1.png)](https://lp.logrocket.com/blg/signup) 

[LogRocket] (https://lp.logrocket.com/blg/signup) is like a DVR for web apps, recording literally everything that happens on your site. Instead of guessing why problems happen, you can aggregate and report on problematic network requests to quickly understand the root cause.

LogRocket instruments your app to record baseline performance timings such as page load time, time to first byte, slow network requests, and also logs Redux, NgRx, and Vuex actions/state. [Start monitoring for free] (https://lp.logrocket.com/blg/signup).