Node.js 14が本日リリース！V8のアップグレードにより「オプショナルチェイニング」「Null合体演算子」等が利用可能に

この投稿では、Node.jsバージョン14の新機能を紹介します。

## Node.js 14

* 本日、2020年4月22日にリリースされた:tada:
* v14はLTS(long term support)という3年間の保守が約束されたバージョン。

## Node.js 14の今後の予定

* Current期間: 2020年4月22日〜2020年10月19日
    * 互換性が保たれる範囲で新機能が追加される。
    * 企業ユーザとしては、アップグレードに備えて、この6ヶ月間にv14でのテストを実施すると良い。
* Active LTSの期間: 2020年10月20日〜2021年10月18日
    * リリースラインに適切な範囲での新機能の追加、バグ修正と保守。
    * 企業ユーザが、本番環境をアップグレードするのに最適な時期。
* メンテナンス期間: 2021年10月19日〜2023年4月
    * 重要なバグ修正とセキュリティ更新。


ちなみに、過去のLTSの終了時期は下記の通り:

* Node.js 12: 2022年4月
* Node.js 10: 2021年4月

![](https://github.com/nodejs/Release/raw/master/schedule.svg?sanitize=true)


## Node.js 14の新機能

* 診断レポート機能がstableに
* V8のアップグレード
* 非同期ローカルストレージAPI
* ストリームAPIを大きく変更
* ES Moduleの警告削除
* 非推奨APIの削除

### 診断レポート機能がstableに

* 診断レポートがNode.js 14でstableになった。
    * Node.js 12でexperimentalとして導入されていたもの。
* 診断レポートは、問題特定のために、スタックトレースやヒープの統計情報、プラットフォームの情報、リソースの仕様状況、クラッシュ、メモリリーク、パフォーマンスの低下などをレポートとして収集できる機能。
* [Diagnostic Report | Node.js v14.0.0 Documentation](https://nodejs.org/api/report.html)

### V8のアップグレード

* V8をv8.1にアップグレードした。
* 「V8 of V8」(V8のバージョン8)というユーモアがある。
* V8 of V8の情報
    * [V8 release v8.0 · V8](https://v8.dev/blog/v8-release-80)
    * [V8 release v8.1 · V8](https://v8.dev/blog/v8-release-81)

#### V8アップグレードにより使えるようになったJavaScriptの新機能

##### Optional Chaining - オプショナルチェイニング

* `?.`演算子を使うことで、ネストされたオブジェクトで、プロパティのnullチェックをいちいちせずに、プロパティを深くまでたどって行ける機能。

```javascript
// before
let nameLength;
if (db && db.user && db.user.name)
  nameLength = db.user.name.length;

// Optional Chaining
const nameLength = db?.user?.name?.length;
```

* [Optional chaining - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining)

##### Nullish Coalescing - Null合体演算子

* `??`: 左辺が`null`か`undefined`の場合に右の値を返し、それ以外の場合は左の値を返す演算子。

```javascript
const foo = null ?? 'default string';
console.log(foo);
// expected output: "default string"

const baz = 0 ?? 42;
console.log(baz);
// expected output: 0
```

* [Nullish coalescing operator - JavaScript | MDN](https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_Coalescing_Operator)

##### `Intl.DisplayNames`

* 言語、地域、文字体系の表示名の一貫した翻訳を可能にするオブジェクト。

```javascript
// 国/地域コードから国名/地域名を出力する例
let regionNames = new Intl.DisplayNames(['en'], {type: 'region'});
console.log(regionNames.of('US')); //=> "United States"
console.log(regionNames.of('JP')); //=> "Japan"

regionNames = new Intl.DisplayNames(['ja'], {type: 'region'});
console.log(regionNames.of('US')); //=> "アメリカ合衆国"
console.log(regionNames.of('JP')); //=> "日本"
```

* [Intl.DisplayNames - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl/DisplayNames)

##### `Intl.DateTimeFormat`の`calendar`オプションと`numberingSystem`オプションの有効化

* `Intl.DateTimeFormat`の`options`引数にて、`calendar`と`numberingSystem`が使えるようになった。

```javascript
const today = new Date('2019-05-10');

console.log(new Intl.DateTimeFormat('ja', { calendar: 'japanese' }).format(today));
//=> R1/5/10

console.log(new Intl.DateTimeFormat('ja', { calendar: 'japanese',  numberingSystem: 'jpan' }).format(today));
//=> R一/五/十

console.log(new Intl.DateTimeFormat('ja', { calendar: 'japanese',  numberingSystem: 'jpanfin' }).format(today));
//=> R壱/伍/拾

console.log(new Intl.DateTimeFormat('ja', { calendar: 'japanese',  numberingSystem: 'jpanyear' }).format(today));
//=> R元/5/10

console.log(new Intl.DateTimeFormat('ja', { calendar: 'japanese',  numberingSystem: 'jpan', era: 'long' }).format(today));
//=> 令和元年五月十日

console.log(new Intl.DateTimeFormat('ja', { calendar: 'japanese',  numberingSystem: 'jpanfin', era: 'long' }).format(today));
//=> 令和元年伍月拾日

console.log(new Intl.DateTimeFormat('ja', { calendar: 'japanese',  numberingSystem: 'jpanyear', era: 'long' }).format(today));
//=> 令和元年5月10日
```

* [Intl.DateTimeFormat - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat)
* [Intl.Locale.prototype.calendar - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/calendar)
* [Intl.Locale.prototype.numberingSystem - JavaScript | MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/Locale/numberingSystem)

### 非同期ローカルストレージAPIの実験導入

* 実験的に非同期ローカルストレージAPIが導入された。
* [Async Hooks | Node.js v14.0.0 Documentation](https://nodejs.org/api/async_hooks.html#async_hooks_class_asynclocalstorage)

### ストリームAPIを大きく変更

* ストリームAPI全体の一貫性を改善した。
    * `http.OutgoingMessage`は`stream.Writable`と一貫するように、
    * `net.Socket`は`stream.Duplex`と一貫するように変更された。
* 大きな変更だが、ほとんどのアプリケーションに影響はないと思われる。
    * エッジケースのみが変更されているため。
    * ただし、ストリームに大きく依存している場合は、Node.js 14のCurrent期間にしっかりテストしたほうがいい。

### ES Moduleの警告削除

* Node.jsでは、ECMAScript Modules(ESM)が使える。
    * ESM = `require()`や`module.exports`の代わりに、`import`や`export`を使うアレのこと。
* Node.js 13では`--experimental-modules`フラグなしにES Modulesが使えるようになった。
    * しかし、それでも「ExperimentalWarning: The ESM module loader is experimental.」という警告は出し続けていた。
* Node.js 14では、上記の警告を出さないようにした。
* ただし、ESMはNode.js14でも「実験的機能」扱い。
    * 実験的=将来的に互換性のない変更や削除があるかもしれない、ということ。
    * 本番環境でESMを使う場合は要注意。

## 参考文献

* [Node.js version 14 available now - Node.js - Medium](https://medium.com/@nodejs/node-js-version-14-available-now-8170d384567e)

---

最後までお読みくださりありがとうございました。Twitterでは、Qiitaに書かない技術ネタなどもツイートしているので、よかったらフォローお願いします:relieved:→[Twitter@suin](https://twitter.com/suin)