世界を動かす技術を、日本語で。

モダンなNode.jsパターン

概要

  • Node.jsは コールバック中心 ・CommonJS主流の時代から、 標準準拠 の開発体験へ進化
  • ES Modulesnode:プレフィックス の導入でモジュール管理が明確化
  • Fetch APIAbortController など、 Web標準API の組み込みで依存削減
  • 組み込みテストランナー など、外部ライブラリ不要な 開発体験の向上
  • 非同期処理・ストリーム・ワーカースレッド の発展によるパフォーマンスと保守性向上

Node.js最新進化の全貌:2025年開発者必見ポイント

  • Node.js は、従来の コールバック多用・CommonJS支配 の時代から大きく進化
  • Web標準 に準拠したAPIやモジュールシステムの導入で、より直感的かつ堅牢な開発体験
  • 依存パッケージの削減テスト統合非同期パターンの洗練 により、保守性と効率性が大幅向上

1. モジュールシステム:ESMの標準化

  • ES Modules(ESM) が標準となり、 CommonJS からの移行が加速
    • import/export構文 による静的解析・ツリーシェイキング対応
    • node:プレフィックス で組み込みモジュールとnpm依存の明確化
  • トップレベルawait の導入で、モジュール初期化がよりシンプルに
    • 即時async関数 不要、コードの直線性向上

2. Web標準APIの組み込み:依存パッケージ不要

  • Fetch API が組み込まれ、 axios/node-fetch 等の外部HTTPライブラリ不要
    • AbortSignal.timeout() によるタイムアウト制御、統一的なエラーハンドリング
  • AbortController で、HTTP通信以外にも ファイル操作・DBクエリ など広範な非同期キャンセルに対応

3. 組み込みテストランナー:プロフェッショナルなテスト体験

  • node:test モジュールによる標準テストランナーの提供
    • describe/test構文assert で、Jest/Mochaライクな記述を実現
    • --test --watch で自動テスト、 カバレッジ計測 も標準対応
  • 外部テストフレームワーク不要、Node.jsのみで完結するテスト環境

4. 洗練された非同期パターン

  • async/awaitPromise.all による並列処理と強力なエラーハンドリング
    • try/catch で一元的なエラーログ・再スロー
  • AsyncIterator によるイベント駆動処理の進化
    • for await...of でイベントストリームを逐次処理・中断も容易

5. Web標準対応ストリームと高度なパイプライン

  • pipeline関数 による自動クリーンアップ・エラー伝播
  • Web Streams API との相互変換で、 ブラウザ・エッジ環境 との互換性向上

6. Worker ThreadsによるCPU並列処理

  • worker_threads モジュールで、 CPU負荷の高い処理 をメインスレッドから分離
    • 親子間メッセージ通信 で結果受け渡し
    • Promise/async と組み合わせて、非同期かつノンブロッキングな設計

7. 開発体験の向上

  • ホットリロード・ウォッチモード など、開発効率を高める機能の標準化
  • エラー出力・デバッグ支援 の強化で、トラブルシュート容易化

まとめ:2025年のNode.js開発の意義

  • Web標準準拠組み込みAPI拡充外部依存削減 の流れは今後も加速
  • 高い保守性・移植性 を持つアプリケーション開発基盤としてNode.jsは最適解
  • 最新Node.js の特徴を活かすことで、 堅牢かつ効率的なサーバーサイドJavaScript開発 を実現

Hackerたちの意見

これ、めっちゃいいね!読んでていくつかのことを学んだし、すぐに自分の小さなプロジェクトに活かせそう。1. Nodeにテストサポートが内蔵されたから、jestはもういらないかも! 2. Nodeにウォッチサポートも内蔵されたから、nodemonもいらないかも!

やっぱりjestが好きだな。jest-extendedが使えるからってのもあるけど。

えー、Nodeのテスト関連はかなりクソだし、Nodeの人たちは改善する気ないみたい。数週間試してみてから本格的に取り組んでみて。そうすれば、俺が言ってることが分かると思うよ(で、問題を報告しようとすると、Nodeチームが全然気にしないのも見えるし)。

TypeScriptを使ってる人には、ネイティブのTypeScriptトランスパイラーがあって、複雑さがかなり減るから忘れないでね。

その通り。もう--experimental-strip-typesも必要ないよね。

ここでの大きなアップグレードはESMじゃないよ。NodeがfetchとAbortControllerをコアに組み込んだことだね。axios/node-fetchを使わなくなったら、Lambdaのバンドルが軽くなって、コールドスタートのレイテンシが約100ms短縮されたよ。まだ習慣でnpm i axiosしてるなら、2025年のNodeはお前に補助輪を外す合図だよ。

node fetchはaxiosよりも遥かに良いよ(使いやすいし、理解しやすい)。まだaxiosを使ってる人がいるとは知らなかったな。

ライブラリの作者としては逆で、fetch()は素晴らしいけど、ESMは痛みを伴ったけど確実に価値のあるアップグレードだったよ。作者が説明していることは全部揃ってる。

Undiciは組み込みのリクエストライブラリとして特にワクワクするよね。https://undici.nodejs.org

プラットフォームが一級のネイティブ「HTTPクライアント」サポートを持っていないことにはいつも驚かされる。過去20年間、ほぼすべてのプロジェクトがそんなものを必要としていたのにね。それに、「fetch」って名前も微妙だと思う。ほとんどのAPI呼び出しがPOSTなのに。

ちょっと脱線するけど、バリデーションとAPI呼び出しは切っても切れない関係だからシェアしたい。個人的には、ts-restを使って全スタックを構築するのが好きなんだ。これが一番軽量で、コンパイルとランタイムのzod/jsonスキーマベースのバリデーションライブラリの中で一番だと思う。好きなHTTPクライアントを自由に使えるのもいいし(私はbunか、Node環境ではfastifyを使ってる)。追加のオーバーヘッドは、基本的にすべての型安全性をコンパイル時に移行するために十分に価値があると思う(私にとってはね)。他の人たちがどう思っているのか、他に選択肢があるのか気になるな。かなり徹底的に探したつもりだけど、軽量で型安全性がしっかりしているのはこれだけだった。

axiosはNodeとブラウザの両方でプロダクションコードで動くけど、ブラウザでfetchがaxiosと同じことができるかはわからないな。

fetchの構文があまり好きじゃなくて、response.jsonを待つ必要があるのが面倒だと思う。追加のエラーハンドリングも実装しなきゃいけないし。

async function fetchDataWithAxios() {
    try {
        const response = await axios.get('https://jsonplaceholder.typicode.com/posts/1');
        console.log('Axios Data:', response.data);
    } catch (error) {
        console.error('Axios Error:', error);
    }
}

async function fetchDataWithFetch() {
    try {
        const response = await fetch('https://jsonplaceholder.typicode.com/posts/1');
        if (!response.ok) {
            // HTTPステータスが200-299の範囲か確認
            throw new Error(`HTTP error! status: ${response.status}`);
        }
        const data = await response.json(); // JSONレスポンスをパース
        console.log('Fetch Data:', data);
    } catch (error) {
        console.error('Fetch Error:', error);
    }
}

ゆっくりだけど、NodeはBun.jsやDenoなどに強力な競争相手を提供しつつあると思う。もう切り替える理由がほとんどないね。相互の競争はJSランタイムの継続的な開発にとって良いことだよ。

ゆっくりだけど、確実に歓迎すべき変化だね。ただ、Bunの$シェル関数がまだ恋しいな。JSをスクリプト言語として使うのはすごく便利だし、サーバーで2つのランタイムを動かしたくないんだよね。

新しい機能は二つのクラスに分けられると思う。ブラウザと同じようにね。1. 新技術 2. 既存の機能のための見栄えの良いレイヤー その二つのセグメントを考えると、みんながどこに優先順位を置いているのかを見るのが面白い。

バックエンドにNode(Typescript)を使ってるなら、私の拡張機能を強くおすすめするよ。https://marketplace.visualstudio.com/items?itemName=StanNthe... 非同期呼び出しをオートコンプリートするときに「await」キーワードを自動で追加してくれるんだ。

もうchalkやpicocolorsをインストールする必要もないよ。自分でテキストをスタイルできるようになったからね:const { styleText } = require('node:util'); ドキュメントはこちら: https://nodejs.org/api/util.html#utilstyletextformat-text-op...

こういうことって偶然見つけることが多いよね。他の人はいつ機能が追加されたかなんて全然知らないけど、「これがモダンだな」ってぼんやり思う感じ。C#だけやってた時とは違って、新しい言語の機能を読んでワクワクすることもなくなった。多言語の世界では、個々の言語が進化するスピードについていくのが難しいよ!俺は大体、浸透学習かこういうブログ記事で学ぶことが多いけど(でもそれはランダムな学びだよね)。

NodeJSの扱いが変わってない限り、Promise.all()は使わない方がいいよ。もし複数のプロミスが拒否されたら、2つ目の拒否でunhandledRejectionイベントが発生して、デフォルトだとサーバーがクラッシュしちゃうから。代わりにPromise.allSettled()を使おう。