Node.js 10.x released - What's NEW?

By: (plus.google.com) +David Herron; Date: April 24, 2018

Tags: Node.JS

After a year of development Node.js 10 has been released. It represents a huge step forward because of some high profile features and fixes. In October Node.js 10 will become the active Long Term Support branch, with 11.x becoming the new experimental branch. Let's take a look at what's been included.

Async/Await functions and ES6 Modules

For me these are the prominent features achieved in Node.js 10. I've spent the last 6+ months updating my book, Node.js Web Development, to the 4th edition, with the primary motivation being these two features. Which means that for the last 6 months I've been explaining to my future readers the importance of these two features. Please be understanding that I'm leading with this.

With the addition of ES6 modules in 9.x and async/await functions in 8.x, the adoption of ES2015/2016 features is pretty much complete. See the full status at (node.green) http://node.green/

The advantage of async functions is turning a "callback hell" situation like this:

router.get('/path/to/something', (req, res, next) => {
    doSomething(arg1, arg2, (err, data1) => {
       if (err) return next(err);
       doAnotherThing(arg3, arg2, data1, (err2, data2) => {
         if (err2) return next(err2);
         somethingCompletelyDifferent(arg1, arg42, (err3, data3) => {
           if (err3) return next(err3);
           doSomethingElse((err4, data4) => {
             if (err4) return next(err4);
             res.render('page', { data });
           });
         });
       });
    });
});

Into this:

router.get('/path/to/something', async (req, res, next) => {
    try {
        let data1 = await doSomething(req.query.arg1, req.query.arg2);
        let data2 = await doAnotherThing(req.query.arg3, req.query.arg2, data1);
        let data3 = await somethingCompletelyDifferent(req.query.arg1, req.query.arg42);
        let data4 = await doSomethingElse();
        res.render('page', { data1, data2, data3, data4 });
    } catch(err) {
        next(err); 
    }
});

Which would you rather maintain and debug?

The try/catch is required here because it is an Express router function, and these functions do not know an async function from a regular function. Instead you inform Express of errors with next(err), so we must use the try/catch block to make it work.

As for ES6 modules, the advantage is that all JavaScript programmers now share the same module format. ES6 modules work in both browsers and on Node.js. Well ...

Whether these modules or any other ES2015/2016/2017 feature works in browsers depends on the newness of the browser. Obviously there are still lots of old computers with old web browsers installed on which ES5 is the supported JavaScript.

In any case, what's an ES6 module look like?

var count = 0;
export function next() { return ++count; }
function squared() { return Math.pow(count, 2); }
export function hello() {
    return "Hello, world!";
}
export default function() { return count; }
export const meaning = 42;
export let nocount = -1;
export { squared };

Node.js has traditionally used CommonJS modules where things are exported by assigning them to the module.exports object. We have nearly 10 years experience with CommonJS modules in Node.js. The code snippet here shows several variations of ES6 module export syntax.

A thing is exported from a ES6 module with the export statement. The export default statement defines the default export from the module, while the others are all named exports.

If that module were named simple2.mjs then it could be used as so:

import * as simple2 from './simple2.mjs';
console.log(simple2.hello());
console.log(`${simple2.next()} ${simple2.squared()}`);
console.log(`${simple2.next()} ${simple2.squared()}`);
console.log(`${simple2.default()} ${simple2.squared()}`);
console.log(`${simple2.next()} ${simple2.squared()}`);
console.log(`${simple2.next()} ${simple2.squared()}`);
console.log(`${simple2.next()} ${simple2.squared()}`);
console.log(simple2.meaning);

And it executes like so:

$ node --experimental-modules simpledemo.mjs
(node:63937) ExperimentalWarning: The ESM module loader is experimental. Hello, world!
11
24
24
39
4 16
5 25
42

See: (nodejs.org) https://nodejs.org/dist/latest-v10.x/docs/api/esm.html

Promise.finally

The Promise object came with Node.js 4.x, and helped us begin our journey out of callback hell.

Initially Promise had two methods, then and catch to deal with whether a Promise resolved to a success state or rejection state. But there are other possible processing patterns that can be implemented on the Promise object. The continued use of the Bluebird library demonstrates that other needs are required. Promise.finally is one such need.

The idea here is a pattern similar to

try {
    some code
} catch (e) {
    handle errors
} finally {
    code that always executes whether or not an error is thrown
}

With Promise.finally we get:

let isLoading = true;

fetch(myRequest).then(function(response) {
    var contentType = response.headers.get("content-type");
    if(contentType && contentType.includes("application/json")) {
      return response.json();
    }
    throw new TypeError("Oops, we haven't got JSON!");
  })
  .then(function(json) { /* process your JSON further */ })
  .catch(function(error) { console.log(error); })
  .finally(function() { isLoading = false; });

In other words, you have code executing in then and catch as we expect currently, and the code in finally is then executed irregardless of errors.

Experimental promisified fs functions

Until now if you wanted sanity with fs module functions you had to use the fs-extra package. That 3rd party package offered a superset of the fs functions, and all its functions returned Promises rather than forcing you to use Callbacks.

We all want the convenience of async functions, which in turn requires widespread conversion from the Callback paradigm to the return-a-Promise paradigm. The Node.js baked-in modules include lots of functions using the Callback paradigm. Switching over to async functions requires switching all the backed-in modules to support returning Promises.

Included in the util module is a util.promisify function that aids with converting functions to return Promises.

Instead of require('fs') you use require('fs/promises'). From there you have the same API as the fs module, but the functions return Promises rather than forcing you to use Callbacks.

See: (nodejs.org) https://nodejs.org/dist/latest-v10.x/docs/api/fs.html#fs_fs_promises_api

HTTP/2 is now stable

HTTP/2 was developed from the earlier SPDY protocol. It supports a large number of improvements like pipelining of requests, compressing headers, multiplexing multiple requests over a single connection, and so on.

See: (nodejs.org) https://nodejs.org/api/http2.html

Improved cryptography

Node.js 10 includes an update to OpenSSL 1.1.0. This lets Node.js support more cipers and authenticators than before. The team expects to update to OpenSSL 1.1.1 before October, which will bring in support for TLS 1.3.

N-API eases burden on native code modules

An issue with native code Node.js modules has been API breakage between Node.js versions. With N-API, which is now non-experimental, that's a thing of the past. The ABI, Application Binary Interface, will remain the same from release to release.

One impact has been that running npm install resulted in a node_modules directory that worked only with a specific Node.js release. With N-API one could presumably use different platform releases on the same node_modules directory.

The N-API support is being back-ported to Node.js 6.x and 8.x release trains as well.

See: (nodejs.org) https://nodejs.org/dist/latest-v10.x/docs/api/n-api.html

Improved error messages

Currently the only way to distinguish one thrown Error from another is to inspect the strings. That leads to situations like:

try {
    execute buggy code
} catch (err) {
    if (err.message === 'This is th message') {
        do something
    } else {
        co something else
    }
}

In other words, we're matching strings, including typos, to distinguish errors. That's bad.

With the new error support we'd instead write:

try {
    execute buggy code
} catch (err) {
    if (err.code === 'ERR_INVALID_URL_SCHEME') {
        do something
    } else {
        co something else
    }
}

This is far more consistent and expressive.

See: (medium.com) https://medium.com/the-node-js-collection/node-js-errors-changes-you-need-to-know-about-dc8c82417f65

See: (nodejs.org) https://nodejs.org/dist/latest-v10.x/docs/api/errors.html

A new npm is promised soon

While Node.js 10.0 ships with npm 5.6.x, the team is promising npm 6.x to arrive soon.

This npm release includes a bunch of improvements.

A new command, npm audit, will incorporate checks for packages with known security problems.

Performance improvements are claimed.

See: (medium.com) https://medium.com/npm-inc/announcing-npm-6-5d0b1799a905

Node.js performance improvements

As always, Node.js releases include updates to the V8 engine, and Google is constantly moving it forward.

This time around they're working to improve performance of async functions and promises.

« Avoid killing performance with asynchronous ES7 JavaScript async/await functions Use Bash-like command-line environment variables on Windows in Node.js npm scripts »
2016 Election Acer C720 Ad block AkashaCMS Amazon Amazon Kindle Amazon Web Services America Amiga Android Anti-Fascism AntiVirus Software Apple Apple Hardware History Apple iPhone Apple iPhone Hardware April 1st Arduino ARM Compilation Artificial Intelligence Astronomy Astrophotography Asynchronous Programming Authoritarianism Automated Social Posting AWS DynamoDB AWS Lambda Ayo.JS Bells Law Big Brother Big Finish Bitcoin Mining Black Holes Blade Runner Blockchain Blogger Blogging Books Botnet Botnets Cassette Tapes Cellphones China China Manufacturing Christopher Eccleston Chrome Chrome Apps Chromebook Chromebox ChromeOS CIA CitiCards Citizen Journalism Civil Liberties Clinton Cluster Computing Command Line Tools Comment Systems Computer Accessories Computer Hardware Computer Repair Computers Cross Compilation Crouton Cryptocurrency Curiosity Rover Currencies Cyber Security Cybermen Daleks Darth Vader Data backup Data Storage Database Database Backup Databases David Tenant DDoS Botnet Detect Adblocker Developers Editors Digital Photography Diskless Booting Disqus DIY DIY Repair DNP3 Do it yourself Docker Docker MAMP Docker Swarm Doctor Who Doctor Who Paradox Doctor Who Review Drobo Drupal Drupal Themes DVD E-Books E-Readers Early Computers Election Hacks Electric Bicycles Electric Vehicles Electron Emdebian Encabulators Energy Efficiency Enterprise Node EPUB ESP8266 Ethical Curation Eurovision Event Driven Asynchronous Express Face Recognition Facebook Fake News Fedora VirtualBox File transfer without iTunes FireFly Flickr Fraud Freedom of Speech Gallifrey git Github GitKraken Gitlab GMAIL Google Google Chrome Google Gnome Google+ Government Spying Great Britain Heat Loss Hibernate Hoax Science Home Automation HTTP Security HTTPS Human ID I2C Protocol Image Analysis Image Conversion Image Processing ImageMagick In-memory Computing InfluxDB Infrared Thermometers Insulation Internet Internet Advertising Internet Law Internet of Things Internet Policy Internet Privacy iOS Devices iPad iPhone iPhone hacking Iron Man iTunes Java JavaScript JavaScript Injection JDBC John Simms Journalism Joyent Kaspersky Labs Kindle Kindle Marketplace Lets Encrypt LibreOffice Linux Linux Hints Linux Single Board Computers Logging Mac Mini Mac OS Mac OS X Machine Learning Machine Readable ID macOS MacOS X setup Make Money Online March For Our Lives MariaDB Mars Mass Violence Matt Lucas MEADS Anti-Missile Mercurial MERN Stack Michele Gomez Micro Apartments Microsoft Military AI Military Hardware Minification Minimized CSS Minimized HTML Minimized JavaScript Missy Mobile Applications Mobile Computers MODBUS Mondas Monetary System MongoDB Mongoose Monty Python MQTT Music Player Music Streaming MySQL NanoPi Nardole NASA Net Neutrality Node Web Development Node.js Node.js Database Node.js Testing Node.JS Web Development Node.x North Korea npm NVIDIA NY Times Online advertising Online Community Online Fraud Online Journalism Online Photography Online Video Open Media Vault Open Source Open Source Governance Open Source Licenses Open Source Software OpenAPI OpenVPN Palmtop PDA Paywalls Personal Flight Peter Capaldi Photography PHP Plex Plex Media Server Political Protest Postal Service Power Control Privacy Production use Public Violence Raspberry Pi Raspberry Pi 3 Raspberry Pi Zero ReactJS Recaptcha Recycling Refurbished Computers Remote Desktop Removable Storage Republicans Retro Computing Retro-Technology Reviews RFID Right to Repair River Song Robotics Rocket Ships RSS News Readers rsync Russia Russia Troll Factory Russian Hacking Rust SCADA Scheme Science Fiction SD Cards Search Engine Ranking Season 1 Season 10 Season 11 Security Security Cameras Server-side JavaScript Serverless Framework Servers Shell Scripts Silence Simsimi Skype SmugMug Social Media Social Media Warfare Social Networks Software Development Space Flight Space Ship Reuse Space Ships SpaceX Spear Phishing Spring Spring Boot Spy Satellites SQLite3 SSD Drives SSD upgrade SSH SSH Key SSL Stand For Truth Strange Parts Swagger Synchronizing Files Telescopes Terrorism The Cybermen The Daleks The Master Time-Series Database Torchwood Total Information Awareness Trump Trump Administration Trump Campaign Ubuntu Udemy UDOO US Department of Defense Virtual Private Networks VirtualBox VLC VNC VOIP Vue.js Web Applications Web Developer Resources Web Development Web Development Tools Web Marketing Website Advertising Weeping Angels WhatsApp William Hartnell Window Insulation Windows Windows Alternatives Wordpress World Wide Web Yahoo YouTube YouTube Monetization