The next major release of Node.js is now available. So far in the series of Node.js 15 releases, we’ve seen several improvements, some new JavaScript language features, and even some breaking changes.
Some of these improvements, like the new version of NPM, are substantial and dramatically improve the developer experience. Other changes, like the new version of the N-API or experimental support for the QUIC protocol, may not appeal to the masses but are just as important to ensure that Node.js continues to be extensible and prepared for the future of the web.
Let’s take a look at what is new and why you should care.
Tip: Node.js 15 is not a long-term support (LTS) release. Support for this release is slated to end in June 2021, shortly after the first Node.js 16 release comes out. You may want to consider keeping your production applications on Node.js 14 for the time being.
NPM 7
The inclusion of NPM 7 is likely the biggest headliner of this release, thanks to a bevy of new features. The biggest feature is NPM workspaces, which is the start of built-in support for creating and managing multiple NPM packages in a single file system. Developers who are already actively using the Yarn package manager or Lerna should see similarities with NPM’s workspace implementation.
It is relatively easy to get started with NPM workspaces. First, arrange all your NPM package folders on the file system, create a top-level package.json that refers to each of these folders, and start running commands across all NPM packages.
NPM7 workspaces
Here’s an NPM workspace example.
Keep in mind that this is the initial implementation of workspaces in NPM. If you are seasoned Yarn or Lerna user, you will notice that many table-stakes capabilities are still missing. For example, being able to execute scripts within specific packages in the workspace is not yet possible using the NPM CLI. I’m sure we’ll see workspace capabilities expand swiftly.
Tip: You can run a script in a specific package in a workspace using the --prefix argument. For example, npm run --``prefix recipe-generator test will run the test script in the recipe-generator package in the current workspace.
In addition to workspaces, there are several other major changes introduced in NPM 7.
Peer dependencies were essentially ignored in NPM 6. In NPM 7, they are installed by default. You can read more about this change in NPM RFC0025. Interestingly enough, the React developer community may have influenced this change.
Running NPM packages without installing them first has become part of core NPM with the new npm exec command. This new command replaces npx but also behaves slightly differently. npx was rewritten to use npm exec but the same CLI for backward compatibility. You can read more about this in the NPM documentation.
NPM now supports yarn.lock files. If present, this file will be used by NPM to determine where to fetch packages from. NPM will even update it as packages are added or removed. There is no plan to replace package-lock.json with yarn.lock. In fact, a package-lock.json file is still generated and maintained as the authoritative source of package version metadata.
NPM has a new package-lock.json format that now supports deterministic builds. In simple terms, this means that NPM ensures that versions of installed packages remain the same across builds if the package-lock.json file has not changed. Deterministic builds have been a feature of Yarn for quite some time.
This only scratches the surface of NPM 7. You can read more about what is new in NPM 7 here.
V8 8.6
Node.js 15 bumps the version of the V8 engine it uses from 8.4 to 8.6. V8 is the underlying JavaScript engine that Node.js runs atop.
So why should you care? Because V8 defines the JavaScript language features that are available to developers. While this version bump is small, there are a few new language features that will reduce the amount of code you need to write and potentially make your code more readable.
First off, there are some new logical assignment operators to allow you to assign a value to a variable conditionally: