Node.js 22の新機能を紹介

Node.js 22が2024年4月24日にリリースされました。今回のリリースには多くの新機能や改善が含まれています。この記事では、Node.js 22の主な変更点を見ていきます。

https://nodejs.org/en/blog/announcements/v22-release-announce

### ネイティブWebSocketクライアント

Node.js 22では、ネイティブのWebSocketクライアントがデフォルトで有効になりました。これにより、サードパーティのライブラリを使用せずにWebSocketを簡単に利用できるようになります。

### 新しいJavaScriptメソッド

`Array.fromAsync`やSetメソッドの強化など、いくつかの新しいJavaScriptメソッドが追加されました。

`Array.fromAsync`の使い方例:

```javascript
async function* getStream() {
	yield 1;
	yield 2;
	yield 3;
}

// 従来
{
	const values = [];
	for await (const value of getStream()) {
		values.push(value);
	}
	console.log(values);
	// => [1, 2, 3]
}

// Array.fromAsync (NEW)
{
	const values = await Array.fromAsync(getStream());
	console.log(values);
	// => [1, 2, 3]
}
```

非同期イテレーターから配列にするとき、だいぶスッキリ書けるようになっていいかんじです。

`Set`にも新たなメソッドが追加されました。

- `union`: 和集合を返す
- `intersection`: 共通項目を返す 
- `difference`: 差集合を返す
- `symmetricDifference`: 対称差集合を返す
- `isSubsetOf`: あるセットが他のセットの部分集合であるかどうかを返す
- `isSupersetOf`: あるセットが別のセットのスーパーセットであるかどうかを返す
- `isDisjointFrom`: 二つのセットが互いに素であるかどうかを判断する

集合関係の処理が強化されたようです。

### Iterator Helpers

`Iterator`に新たなヘルパーメソッドが追加されました。

- `map`: 各要素に関数を適用した新しいIteratorを返す
- `filter`:  条件に一致する要素だけを含む新しいIteratorを返す
- `take`: 指定された数の要素を含む新しいIteratorを返す
- `drop`:  指定された数の要素をスキップした新しいIteratorを返す
- `flatMap`:  各要素にマッピング関数を適用し、結果を平坦化した新しいIteratorを返す
- `reduce`:  Iteratorの要素を単一の値にまとめる
- `toArray`:  Iteratorの要素から新しい配列を作成する
- `forEach`: 各要素に対して関数を実行する
- `some`: いずれかの要素が条件を満たすかどうかをテストする
- `every`:  すべての要素が条件を満たすかどうかをテストする
- `find`:  条件を満たす最初の要素を返す

`Array`にある`map`などが`Iterator`にはなくて、一旦`Array`に変換するといった手間やオーバーヘッドがありましたが、これからはそういったことなく`Iterator`を直に操作できるようになりました。

また、`toArray`など`Array`への変換もイディオムに頼る従来の方式ではなく、ちゃんと`toArray`と明示的に書けるようになっていていい感じです。

```jsx
const map = new Map([
	["key1", 1],
	["key2", 2],
	["key3", 3],
]);

// 従来
const mappedValues = [...map.values()];
console.log(mappedValues);
//=> [ 1, 2, 3 ]

// Iterator.prototype.toArray (NEW)
const mappedValues2 = map.values().toArray();
console.log(mappedValues2);
//=> [ 1, 2, 3 ]
```

### ESMのrequire

Node.js 22では、`require()`を使ってESモジュールをインポートできるようになりました。

例:

```javascript:esm.mjs
export const hello = "Hello, world!";
```


```javascript:commonjs.cjs
const { hello } = require("./esm.mjs");
console.log(hello);
//=> Hello, world!
```

```bash:実行方法
node --experimental-require-module commonjs.cjs
```

現状は`--experimental-require-module`フラグが必要なものの、順当にいけばこのフラグも不要になるはずで、これまでデアルパッケージなどでCommonJSとESMどちらも提供していたライブラリ作者はだいぶ楽になるのではなでしょうか。また、ESMしか提供されていないライブラリをCommonJSプロジェクトで諦めていた人もいるはずなので、今後の展開が楽しみです。

### globとglobSync

Node.js 22では、`glob`と`globSync`が標準で利用可能になりました。これにより、npmでglobパッケージをインストールせずにファイルのパターンマッチングができるようになります。便利ですね！

```javascript
import { globSync } from 'node:fs';

console.log(globSync('**/*.js'));
```

```txt:出力結果例
(node:74956) ExperimentalWarning: glob is an experimental feature and might change at any time
(Use `node --trace-warnings ...` to show where the warning was created)
async.js
glob.js
map.js
set.js
watch-test.js
```

### WebSocket

Node.js v21で実験的に導入されたブラウザー互換のWebSocketが、Node.js 22でデフォルトで使えるようになりました。`--experimental-websocket`オプションを渡す必要がなくなります。

## nodeコマンドの機能追加

### ウォッチモード

`--watch`オプションが追加され、ファイル変更を検知するとNode.jsのプロセスが自動的に再起動されるようになりました。

![CleanShot 2024-05-02 at 08.34.05.png.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/889/8cc1e267-7e7f-b884-0406-05f0d503d15a.gif)


### package.jsonスクリプトの実行

`--run`オプションが追加され、package.jsonのスクリプトをnodeコマンドから直接実行できるようになりました。

例:

```json:package.json
{
	"scripts": {
		"hello": "echo 'Hello, world!'"
	}
}
```

```bash:実行方法
node --run hello
```

## まとめ

Node.js 22には、JavaScriptエンジンの改善、新しいJavaScriptメソッド、Iterator Helpers、ESMのrequireサポート、標準のglobサポート、WebSocketのデフォルト有効化、nodeコマンドの機能追加など、多くの新機能と改善が含まれています。

Node.js 22は偶数バージョンなので、2024年10月に長期サポート(LTS)に入り、2027年10月までサポートされる予定です。