nodejs / nodejs/node

module: CJS loader re-stats the same missing paths within one require tree

オープン
#64,681 コメント 1 件 リアクション 0 件 担当者 1 名 GitHub で見る

@maxday がすでに取り組んでいます。

2026年7月22日 から。

module
主要言語
JavaScript
スター
122k
フォーク
37.3k
平均マージ
4日 2時間
マージ済み PR(30日)
283

説明

The CommonJS loader keeps a per-require-tree statCache (in lib/internal/modules/cjs/loader.js) to avoid re-stat-ing the same path while resolving a module tree. Today it only caches successful stats. Negative results (e.g. -ENOENT) fall through the cache and are re-probed every time the same missing path is looked up again within the same top-level require.

// lib/internal/modules/cjs/loader.js — stat()
const result = internalFsBinding.internalModuleStat(filename);
if (statCache !== null && result >= 0) {
  // Only set cache when `internalModuleStat(filename)` succeeds.
  statCache.set(filename, result);
}

Failed probes are extremely common during resolution, and the same misses recur across sibling and descendant modules:

  • tryExtensions resolves an extensionless specifier (e.g. require('./helper')) by stat-ing each candidate in order: ./helper.js, then ./helper.json, then ./helper.node until one exists. Every extension tried before the real one is a miss.
  • Bare specifiers (require('foo')) walk the node_modules chain upward: …/a/b/node_modules, …/a/node_modules, …/node_modules. Most of those parent directories don't exist, so each is a negative stat, and every bare require in the tree re-walks the same non-existent ancestors.

Because negatives aren't cached, these misses are re-stat-ed repeatedly within a single resolution pass.

コントリビューションガイド

コントリビューションガイドを開く

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。