metro-file-map gives up on a fallback watcher that is still starting after a fixed 240 s, and leaves it running

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

メンテナーはふだん 2 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
48/100
issue の種類
バグ
明瞭さ
おおむね明確
活発さ
活発
技術スタック
javascript, node.js
領域
tooling

調査の方向性

Start with packages/metro-file-map/src/Watcher.js and trace how createWatcherBackend applies its startup timeout; then read FallbackWatcher.startWatching() to understand the crawl. Use the linked reproduction to compare startup with and without a large tree. Done means a progressing crawl does not fail solely because it exceeds a fixed timeout, and a backend that does time out is stopped.

索引モデルが issue の本文から書いたものです。

説明

Reproduction: https://github.com/YevheniiKotyrlo/metro-file-map-watcher-start-timeout

Without Watchman, metro-file-map starts FallbackWatcher (Windows and Linux; macOS takes NativeWatcher), whose startWatching() walks every entry of the watch root and opens one fs.watch per folder, so how long it takes grows with the tree and with the machine's load. Watcher.js gives that start a fixed MAX_WAIT_TIME of 240 s and then rejects with Failed to start watch mode., so the file map's build fails, Metro never becomes ready, and every bundle request fails with that error for as long as the server runs, although the watcher was still making progress.

I hit it with a workspace install of about 29,000 folders: one Metro on main started its fallback watcher over it in 68 s, and six dev servers started together over the same install each failed with Failed to start watch mode. at 240 s.

Steps (metro 0.87.2 with every package replaced by its build from main at b8ac7a77a114ce1199c5e2b3ef2cca0a5b3d0aa8; Node 26.12.1, npm 12.2.1, Windows 11, the clone on a ReFS Dev Drive, no Watchman):

  1. Clone the reproduction and npm install. It is a plain Metro project with resolver.useWatchman: false.
  2. node start-servers.js 1, which runs metro serve, requests /index.bundle?platform=android&dev=true and prints how the request ended. This is the control, with no tree yet.
  3. node make-tree.js 30000, which lays out 30,000 small packages under tree/ (60,300 folders, 150,000 files), the shape of a large node_modules.
  4. node start-servers.js 1 again.

For main: between steps 1 and 2, yarn install --frozen-lockfile and node scripts/build.js in a react/metro checkout, then node use-metro-main.js <the checkout>, which puts each package's build in place of the installed src.

Expected: at step 4 the bundle is served, later than at step 2.

Seen:

== step 2: node start-servers.js 1 (no tree)
server 8081: HTTP 200 after 4.8 s
== step 3: node make-tree.js 30000
D:\Temp\metro-file-map-watcher-start-timeout-1793463524\tree holds 30000 packages
== step 4: node start-servers.js 1
server 8081: HTTP 500 after 240.4 s, and Metro printed "Failed to start watch mode."

The response body starts with Metro has encountered an error: Failed to start watch mode.

In packages/metro-file-map/src/Watcher.js at b8ac7a77, createWatcherBackend starts the backend under a timer:

const rejectTimeout = setTimeout(
  () => reject(new Error('Failed to start watch mode.')),
  MAX_WAIT_TIME,
);
...
await watcher.startWatching();
clearTimeout(rejectTimeout);
resolve(watcher);

Two things follow:

  • The limit is the same whatever the size of the tree, though FallbackWatcher.startWatching() is a full walk (recReaddir lstats every entry and calls #watchdir on every folder), so a large enough tree or a busy enough machine fails the start every time, with nothing in the config to raise it.
  • When the timer fires, nothing stops the backend: startWatching() goes on walking and opening watches, and the FallbackWatcher is never closed, since it is neither resolved into #backends nor stopped.

A limit that only fires when the walk stops making progress, or none for a backend whose start is a crawl, would keep the guard for a backend that hangs; and on a timeout the backend that was starting should be stopped.

主要言語
JavaScript
スター
5.7k
フォーク
711
平均マージ
2日 18時間
マージ済み PR(30日)
66

環境構築

はじめの一歩

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

react/metro のほかの issue

react/metro の issue をすべて見る

似ている issue

JavaScript の issue をもっと見る

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

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