Node.js version 21 declare a few major updates.

Let's give you an overview of these changes.

1. V8 engine update: The new version 11.8 improve performance and added new language features.

2. Stable fetch and web streams: Now these apis are stable. Grant native http request and data flow handling (streaming).

3. Built-in web socket client: Developmental support for suitable browser websockets by using "--experimental-websocket" flag.

4. --experimental-default-type: Change module default. Make it easy to work with es modules.

5. Node test runner: The latest change in test runner is now support glob expressions. This change make it easy test execution.

6. Performance increase: Revision in streams, fs and http.

7. Deprecation: In node 21 punycode and promisify'ing functions are no longer.

Explain latest features with code example. Are you ready.? no hihihi. okay lets start:

Stable fetch and webstreams:

In v21 fetch api and webstreams apis making easy and smooth communication in web environment.

Example fetch api in node 21:

const fetchData = async () => {
    const response = await fetch("localhost:3000"); // put example url
    const result = await response.json();
    console.log(result);
};
fetchData();

in node 20 or earlier we need to import in project "fetch-node" to use fetch method for calling api/url.

webstreams example:

const { ReadableStream } = require("stream/web"); // if you want to use es module like import then you need to set type: moduel n package.json file. or use new esm feature
const stream = new ReadableStream({
    start(controller) {
        controller.enqueue("Hi professor, welcome to node.js stream");
        controller.close();
    }
});


const streamFn = async () => {
    const reader = stream.getReader();
    const result = await reader.read();
    console.log(result.value); // Output: Hi professor, welcome to node.js stream
};
streamFn();

Buil-in websocket client in node v21:

In latest change in node.js the websocket are embeded as a developmental support. so we dont need to install third-party lib ws by using nmp i.

Programming example:

const ws = new WebSocket("ws://localhost:3000");
ws.onopen = () => {
    console.info("websocket is open now");
    ws.send("hi usama");
};
ws.onmessage = (message) => {
    console.info(`a message recevie: ${message}`);
};
ws.onerror = (error) => {
    console.error(`Error occur: ${error}`);
};
ws.onclose = () => {
    console.warn("Connections closed.");
};

In node.js 20 or early versions, we need to install socket library tool manually.

V8 engine new update:

The most important and valuable change in node 21 is that the new version of nodejs has comes with upgraded v8 engine 11.8. This version v8 engine announce new javascript language features like "array grouping" and "ArrayBuffer.prototype.transfer".

lets explore example about array grouping and array buffer:

// Array Grouping
const array_list = [
    { name: "Usama Amjid", language: "node.js"},
    { name: "Hassan Raza", language: "node.js"},
    { name: "Fariha", language: "python"},
    { name: "Maryam", language: "Cpp"}
];
const group_data = Object.groupBy(array_list, (lang) => {
    return JSON.stringify(lang.language)
})
const plain_data = Object.assign({}, group_data);
console.log(plain_data);
/* Ouput:
{
  '"node.js"': [
    { name: 'Usama Amjid', language: 'node.js' },
    { name: 'Hassan Raza', language: 'node.js' }
  ],
  '"python"': [ { name: 'Fariha', language: 'python' } ],
  '"Cpp"': [ { name: 'Maryam', language: 'Cpp' } ]
}
*/

//Array Buffer transfer
const buffer = new ArrayBuffer(8);
const transferred = buffer.transfer(16);
console.log(transferred.byteLength); // Output: 16

Globs in node v21:

The nodejs v21 add a support for test runner glob expressions. This support making it easy to run individual test cases beyond multiple folders.

Example globe expression:

node --test **/*.test.js
This command run all .test.js files in the project.

ECMAScript modules (ESM) flag:

In node v21 esm flag "--experimental-default-type" enable to make the default module system without specifying the type=module in package.json file or .js extention. lets i give you an example. for instance, you have a script file without package.json file. and you use import statement for importing the modules, when you run the script using this command 'node index.js', you got an error like this.

The error is:

(node:36722) Warning: To load an ES module, set "type": "module" in the package.json or use the .mjs extension.
(Use `node --trace-warnings ...` to show where the warning was created)
/home/professor/professor/node-updates/node21/index.js:110
import fs from "fs";
^^^^^^
SyntaxError: Cannot use import statement outside a module
    at internalCompileFunction (node:internal/vm:128:18)
    at wrapSafe (node:internal/modules/cjs/loader:1279:20)
    at Module._compile (node:internal/modules/cjs/loader:1331:27)
    at Module._extensions..js (node:internal/modules/cjs/loader:1426:10)
    at Module.load (node:internal/modules/cjs/loader:1205:32)
    at Module._load (node:internal/modules/cjs/loader:1021:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:142:12)
    at node:internal/main/run_main_module:28:49


Node.js v21.7.3

this error tells us we are not able to use em module system without having a package.json file. and if we want to use es module then we need to create or initialize a project using npm init, then we set the type: module or use .mjs extenstion. and this thing is painful, because if we want to run a single .js file for a piece of code and test it then we need to use type module. thats why this new feature esm flag comes. let explore this command.

Command:

node --experimental-default-type=module index.js
when you run this command you did not get any kind or error or warning. and your index.js file able to use import statement.

In early node versions, the developers needs .mjs or use type=module in package.json file to declare a es module. Developers thankful to the node team. :)

flush option in fs.writeFile:

This is another big and important feature in node v21 that the flush option added in fs.writeFile function. This new optoin ensure that the data is flushed after writing file.

Example code:

import fs from "fs"; // use node --experimental-default-type=module index.js command if run single script file
fs.writeFile("myfile.txt", "This is new feature", { flush: true}, (error) => {
    if(error) {
        throw error;
    };
    console.log("file has been saved and flush.");
});

in the past node.js versions, programmers needs to manually manage flushing.

Node Performance improvement:

Node performance team improve performance in many tools like streams and http. In streams node team optimise writeable and readable streams and in http reduce redundant chunk response.

Example about Http chunk response optimisation:

import http from "http";
http.createServer((req, res) => {
    // Cork the writable stream (in this case, the response stream)
    res.cork();
    res.write("Hi, Usama\n");
    res.write("Developer\n");
    // Uncork the stream to flush everything in one go
    res.uncork();
    res.end();
}).listen(3000, () => {
    console.log("Server is listening on port 3000");
});

in past, each call to write a stream create a separte chunk.

Integrate Navigator object in node:

Node team introduce a new global object called navigator. Now javascript/node developers can get the hardware information by using navigator.hardwareConcurrency

console.log(navigator.hardwareConcurrency); // Output: Number of CPU cores.

A comparison b/w latest node.js v21 and earlier versions such as node 20 or node 18:

Conclusion:

Hope you must have read about new features and learn something new. As a developers we are thankful to the node team who are working hard. Just try it node v21, try new highlighted features in your applications and give feedback to the node team and they deserve it.

Last and most important note is that node.js v16 lts end of life. So I strongly recommend, upgrade your node v18 or v20 LTS.