“”
What is new in the release of Node.js version 13

Node.js 13 is the new actual version

View more techs

All you need to know about Node 13

 

Guillermo Osores

Guillermo Osores

March 4, 2020

 

In this article we are going to dive into the updates of the latest Node release.

Node.js 13 was released 2020/02/05, and we need to keep in mind that it will not be in Long Term Support (LTS), so using it in production environments is not recommendable. Node.js 12 was promoted to (LTS).

These releases deliver faster startup and better default heap limits, updates to V8, TLS, llhttp, new features including diagnostic report, bundled heap dump capability and updates to Worker Threads, N-API, and more.

V8 Gets an Upgrade to V8 7.8


It brings performance tweaks and improvements:

- Faster object destructuring

- Lazy source positions: source position tables that tie bytecode sequences to character positions within the source code are only generated when a stack trace is actually generated, for instance when calling Error.stack or printing an exception’s stack trace to the console. This brings less memory usage.

- Faster RegExp match failures.

Full ICU (International Components for Unicode) enabled by default

It’s a library which provides Unicode and Globalization support for software applications. It was already supported on previous versions, the thing is that in this version it supports a larger set of languages by default.

Locales string can be found here:
https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry

const january = new Date(9e8);
const english = new Intl.DateTimeFormat('en', { month: 'long' });
const spanish = new Intl.DateTimeFormat('es', { month: 'long' });
const portuguese = new Intl.DateTimeFormat('pt', { month: 'long' });
const japanese = new Intl.DateTimeFormat('ja', { month: 'long' });
const french = new Intl.DateTimeFormat('fr', { month: 'long' });
 
console.log(english.format(january));
console.log(spanish.format(january));
console.log(portuguese.format(january));
console.log(japanese.format(january));
console.log(french.format(january));
$ node testICU.js 
January
enero
janeiro
1月
janvier


ECMAScript

Experimental support for ECMAScript modules is enabled by default, and are the official standard format to package JavaScript code for reuse. Modules are defined using a variety of import and export statements.

.mjs is the extension for these types of modules, they can't be loaded using require. If you are using commonJS use import() and it will return a promise.

To use them in the package.json we have to add:

{
  "type": "module",
}


Module (hi.mjs):

function hi(){ console.log('Hi') }
export default hi;


Usage example:

import hi from './hi.mjs';
hi();


Usage on commonJS:

const hi = import('./hi.mjs');
hi.then( m => m.default() );


WASI (WebAssembly System Interface)

It's an API that provides access to several operating-system-like features, including files and filesystems, Berkeley sockets, clocks, and random numbers, that we'll be proposing for standardization.

It's designed to be independent from browsers, so it doesn't depend on Web APIs or JS, and isn't limited by the need to be compatible with JS. And it has integrated capability-based security, so it extends WebAssembly's characteristic sandboxing to include I/O.

The --experimental-wasi-unstable-preview1 and --experimental-wasm-bigint CLI arguments are needed for it to work.

Stable Workers API

Node.js is still event looping, but now we have the chance to multithread.

In this example we are going to sum numbers from a big range so it will take a lot of time to do on a single thread and we can see how we can improve it to make it faster.

const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');

function addRange (start, end) {
 let total = 0;
 for (let i=start; i<=end; i++) {
   total += i;
 }
 return total;
}

console.time('time');

if (isMainThread) {
 const start = 1;
 const end = 1e8;
 const threadCount = +process.argv[2] || 5;
 let total = 0;

 const threads = new Set();

 for (let i = 0; i < threadCount; i++) {
   const threadStart = i===0 ? start : (Math.floor((end / threadCount)) * i) + 1;
   let threadEnd = i === threadCount - 1 ? end : Math.floor((end / threadCount)) * (i + 1)

   threads.add(new Worker(__filename, { workerData: { start: threadStart, end: threadEnd }}));
 }

 for (let worker of threads) {
   worker.on('error', (err) => { throw err; });
   worker.on('exit', () => {
     threads.delete(worker);
     console.log(`Thread exiting, ${threads.size} running...`);
     if (threads.size === 0) {
       console.log(`Total: ${total}`);
       console.timeEnd('time')
     }
   })
   worker.on('message', (subTotal) => {
     total += subTotal;
   });
 }

} else {
 const total = addRange(workerData.start, workerData.end);
 parentPort.postMessage(total);
}


Using one worker (almost normal Node.js code):

$ node testWorkers.js 1
Thread exiting, 0 running...
Total: 5000000050000000
time: 128.430ms


Using three workers:

$ node testWorkers.js 3
Thread exiting, 2 running...
Thread exiting, 1 running...
Thread exiting, 0 running...
Total: 5000000050000000
time: 82.739ms


Using ten workers:

$ node testWorkers.js 10
Thread exiting, 9 running...
Thread exiting, 8 running...
Thread exiting, 7 running...
Thread exiting, 6 running...
Thread exiting, 5 running...
Thread exiting, 4 running...
Thread exiting, 3 running...
Thread exiting, 2 running...
Thread exiting, 1 running...
Thread exiting, 0 running...
Total: 5000000050000000
time: 182.007ms


- Worker: class that represents an independent JavaScript execution thread. Most Node.js APIs are available inside of it.

- isMainThread: function that only returns true if the code is is not running inside of a Worker thread

- parentPort: If this thread was spawned as a Worker, this will be a MessagePort allowing communication with the parent thread. Messages sent using parentPort.postMessage() will be available in the parent thread using worker.on('message'), and messages sent from the parent thread using worker.postMessage() will be available in this thread using parentPort.on('message').

- workerData: an arbitrary JavaScript value that contains a clone of the data passed to this thread’s Worker constructor.

So as you can see, if we have to process a large amount of data or need to use big calculation power, it will be greatly improved using workers. But it doesn't mean that as more workers are used it will be done faster. Creating workers has its cost so we need to find a balance.

 

Guillermo Osores

Guillermo Osores

Guillermo is a senior full stack developer with more than six years experience in software development. Specialized in React, React Native and Node, he has worked on a wide range of projects for our US clients. Guillermo is passionate about teamwork, adding value to the projects he is entrusted with, and seeing products come to life and evolve.

Contact us

Ready to get started? Use the form below or give us a call to meet our team and discuss your project and business goals.
We can’t wait to meet you!


Follow Us
See our client reviews