What's New in Node.js 19

Yuval Hazaz
Yuval Hazaz
Mar 16, 2023
What's New in Node.js 19What's New in Node.js 19

On October 18, 2022, the Node.js core team announced version 19 of the most popular JavaScript runtime for the backend. You can read the announcement if you haven’t already. But in this article we’re going to review the entire list and dig deep into the details of each update of Node.js 19.

There are many hidden gems in this version.

Node.js 19 Major Updates

Let’s take a look at the most relevant updates from this new version of Node and how they impact you—as both a developer and direct user of the runtime.

Instantly generate
production-ready backend
Never waste time on repetitive coding again.
Try Now

Addition of the Experimental --watch Flag

This one is probably the easiest to understand; after all, we’ve all probably used node-mon or some similar tool in the past. Most modern frameworks make use of these tools when they run in dev mode.

That said, the fact that the Node team decided to incorporate this functionality into the CLI—when there are other options available—is interesting. Especially if you consider how Deno has been doing something similar as well.

Until now, the philosophy behind Node has been: We’ll give you the building blocks, and you build whatever you want with them. But now, they’re starting to add these tools themselves. Will these alternative options be up to par with the existing tools and standards established by the community until now? Or will they at least be good enough?We’ll have to wait and see. As of now, all we’ve seen is an experimental version of one of these tools: the file watcher.

With but a simple flag, -–watch, you can restart your Node.js process now whenever your main file or any of its required dependencies are changed.

That last part is key because unless you’re directly (or indirectly) interacting with the changed file, nothing will happen to the process. If instead, you want the Node process to restart even when you change an external file (like a config file), you’ll have to use the --watch-path flag. This is only available for macOS and Windows platforms though, meaning Linux users will have to wait a bit longer. The --watch-path flag was also added on this release and it's also in the “experimental” stage, so be careful how you use it, as it might not be ready for production just yet.

Change of the Keep-Alive to True by Default

Before version 19, Node.js was not relying on the “Keep-Alive” header returned by the server and it was creating a new TCP connection for every HTTP request. This process of creating a new connection on every request means there is overhead that adds extra time to every new request. If in your application, you’re only sending requests every once in a while, this change will not make a dent in your performance; but if you rely on outgoing connections, then the impact is going to be considerable.

Take a look at the results from this simple script:

const http = require('https');

var i = 0;

function request() { console.log(${++i} - making a request); let start = (new Date()).getTime() const req = http.request("https://www.google.com/", {}, (res) => { console.log(STATUS: ${res.statusCode}); res.setEncoding('utf8');

res.on('end', () => {
 let end = (new Date()).getTime()
 console.log("Time (", i, "): ", end - start)
});
});

req.on('error', (e) => {
console.error(`problem with request: ${e.message}`);
});

req.end();

}

setInterval(function(){ request(); }, 1000); // send a request every 1 seconds

The code is sending one request to Google’s homepage every second. Now, if I use Node.js 18, I get results like this:

1 - making a request
STATUS: 200
Time ( 1 ):  573

2 - making a request
STATUS: 200
Time ( 2 ):  549

3 - making a request
STATUS: 200
Time ( 3 ):  579

4 - making a request
STATUS: 200
Time ( 4 ):  568

As you can see, the results are always somewhat consistent around 550 ms. But if I switch to version 19, these are the results I get:

1 - making a request
STATUS: 200
Time ( 1 ):  576

2 - making a request
STATUS: 200
Time ( 2 ):  219

3 - making a request
STATUS: 200
Time ( 3 ):  200

4 - making a request
STATUS: 200
Time ( 4 ):  195

There’s at least 300 ms (or more) shaved off every request simply because I’m reusing existing connections instead of creating a new one every time. Granted, you could get the same results with prior versions of Node by manually creating a new HTTP(S) agent and making sure the “Keep-Alive” option was set to true, but now you don’t need that extra boilerplate code.

The Crypto API is Stable in Node.js 19

This one is pretty self-explanatory, to be honest. The API is pretty much stable at the time of this release with the exception of some algorithms specified on the release notes; just make sure not to use those algorithms if you rely on the Crypto API and you’re good.

Removal of --experimental-specifier-resolution Flag for Module Resolution

This update is probably the most underrated one of this entire release. Because at first glance, it doesn’t look like anything important if you’re not part of the Node.js core team.

However, if you dig a bit deeper, you’ll find it means you can now import files using the ECMAScript Module (ESM) system without an extension or even import folders that contain an index.js file—as was common when using CommonJS (i.e., using require instead of import).

When Node.js added support for ESM, they never allowed for that behavior by default, you had to use the --experimental-specifier-resolution flag set to “node” to be able to support this “extra” behavior.

Now you can start doing import myFile from `./folder/myFile, and it’ll work as long as the file in question has one of the allowed extensions (i.e., “.js” or “.mjs”).

Removal of DTrace/SystemTap/ETW Support

This one is not about a new feature, but the loss of one. DTrace/SystemTap/ETW references different OS-specific tools used to profile applications from the outside. These applications need to provide internal support for those protocols to get performance metrics out of them without having to edit their code (i.e., to capture those metrics internally). In prior versions of Node, you were able to add support for these protocols inside your applications, thus allowing others to profile your app from the outside.

However, from the look of it, keeping up with the standards was too big an effort for the little value it added. Instead, the core team decided to do away with them rather than have a feature without full compatibility.

So unless you were using these tools before, this part of the announcement really has no impact on you.

Updated Dependencies in Node.js 19

It’s normal that to keep your project current and avoid falling behind on important improvements, you’ll want to try to keep your dependencies as updated as possible. This is why for this release, we have new versions of V8, llhttp, and NPM. The new version of V8 (10.7 to be exact) brings a new Stage 3 proposal into Node.js 19, in particular, the updates to the Intl.numberFormat V3 API.

If your application handles big numbers or has to format them differently based on the language you choose, this update might be interesting to you, so make sure to check it out.

As for llhttp, it’s a TypeScript port of http_parser, a C implementation of an HTTP parser no longer being maintained. This project is an attempt to improve the ported one and extend it without the hustle the original one presented. This particular update is not that big, with only two changes, so you’re safe ignoring it.

And finally, this new version of Node ships with version 8.19.2 of NPM, which has been available since September. This means two things:

  1. Node isn’t using the latest version of NPM by default (version 9 has already been released).
  2. Node is using a tried and tested version of NPM, which if you think about it, makes a lot of sense.

So all in all, it’s a good thing that we’re dealing with stable dependencies, even if some of them aren’t the latest version.

##Should You Update Your Node.js Version Right Away?

Now that we understand what’s up with this release, the question is: Should you try to update your Node version right away? The answer is pretty straightforward: Unless some of the updates I mentioned above directly affect you, no, there is no reason for you to update if you’re already on Node version 18.

This is because while 19 is now the “current” version of Node, 18 is now considered LTS (or Long Term Support), meaning that it’ll be maintained until 2025, so bug fixes and security updates will still be added.

You can see the current release plan in the following image (Source: Node’s support group GitHub page):

You can see the full support plan for current, previous, and future versions of Node.

So if you’re already on Version 18, I would recommend you stay there for a while, unless you really need some of the new features. Version 19’s new updates (especially the new features) might have some unforeseen bugs that will be ironed out in coming updates; just give it a few months.

If on the other hand, you’re behind, like on version 16 (which will no longer be maintained after Sept 2023) or even older, I would definitely consider upgrading, either to Node.js 19 or at least to 18, to make sure you don’t miss any updates to those older versions.

Conclusion

With Node.js 19, we got some interesting updates that for some developers who actively use those features will definitely impact their performance. I’m of course talking about the new default “Keep-Alive” value and the new loader specification allowing you to import files like you used to with CommonJS.

We also got a glimpse at a potential new trend from the Node core team to start adding features to the main CLI that until now were the responsibility of external tools (like the --watch flag). Will this be a one-off? Or will they continue adding new ones? We’ll have to wait until April 2023, when version 20 is released, to see about that.

In the meantime, enjoy the new version!