Restrict sibling folder walking for @source patterns

tailwindlabs/tailwindcss

Tailwind CSS now limits the directory traversal of @source patterns so that only the explicitly matched files are scanned, eliminating costly sibling scans that could stall the build.

背景

@source が具体的なファイルを指す場合でも、ベースディレクトリ全体が走査されていたことがパフォーマンスのボトルネックになっていました。Issue #20255 では @source "../../app.config.ts" が原因でスキャンが約 22 秒でハングし、ビルドが進まない状態が報告されています。最適化前はベース "/Users" 以下の全ファイルが走査され、結果は !app.config.ts で除外されるだけでしたが、実際の I/O 負荷は変わりませんでした。

技術的な変更

crates/oxide/src/scanner/sources.rs に新たな制限ロジックが導入されましたFxHashSet のインポートと共に、ベースごとに一度だけ * で全体を無視し、続けて対象パターンを ! で再有効化するコードが追加されています。

use fxhash::{FxHashMap, FxHashSet};

// 省略
// ベースディレクトリに対して * を一度だけ追加
if !unrestricted_roots.contains(&base) {
    rules.push(Rule::IgnoreAll);
    rules.push(Rule::Include(pattern));
}

このロジックは 同一ベースへの複数パターン でも * が二重に追加されないよう unrestricted_roots を参照し、@source "./src/foo.ts"@source "./src/bar.ts" のケースで正しく * が一回だけ出現します。さらに、パターン中に * が残る中間フォルダがある場合は、親セグメントごとに逆ルール(!/ba*/!/ba*/*.html)を生成して、期待通りのディレクトリ走査を実現しています。

テストコード (crates/oxide/tests/scanner.rs) も 200 行余り追加され、
- 単一ファイルソースの制限
- 同一ベースでの複数ソース統合
- 後続の @source not … が前方の制限を上書きできること
を検証しています。

設計判断

ベースディレクトリを * で全面的に無視し、必要なパターンだけを ! で再包括する方式 が選択されました。この設計は Gitignore の挙動と同等であり、既存のスキャナロジックと最小限の差分で実装できます。さらに、* の重複排除と順序保持により、後続の除外ルールが前方の制限を正しく上書きできる点が意図的に保たれています。広範な Auto/External ソースや ** を含むパターンは unrestricted_roots に分類され、制限の対象外とすることで、意図しない sibling の隠蔽を防いでいます。

まとめ

この変更により、@source が指す具体ファイルの走査がベースフォルダ全体への無駄な I/O を回避し、ビルド時間が数秒から数ミリ秒規模に短縮されます。設計は Gitignore に倣ったシンプルかつ拡張性のあるパターン処理で、既存のスキャナ挙動との互換性も維持しています。

記事メタデータ

Generated by:
gpt-oss-120b for DiffDaily
LLM Trace:
bb35434d

この記事はAIによって自動生成されています。内容の正確性については、必ずソースコードやPRを確認してください。

品質レビュー結果

Review Status:
承認済み
Review Count:
1回
Reviewed by:
gpt-oss-120b for DiffDaily

Review Criteria:

記事構成 ✓ PASS

Title, Context, Technical Detailの存在と明確さ

リード文がタイトル直下に配置され、背景・技術的変更・設計判断・まとめの順に構成されており、総論→各論→結論の流れが明確です。

カスタムMarkdown構文 ⚠ WARNING

シンタックスハイライト・GitHubリンク記法の正確性

コードブロックは正しい `言語:ファイルパス` 形式ですが、PRリンクが `[PR #20263](URL)` となっており、指定の `[ #20263 ](URL)` 形式になっていません。リンク記法の修正が望まれます。

対象読者への適合性 ✓ PASS

エンジニア向けの適切な技術レベルと表現

専門的な開発者向けの内容で、余計な初心者向け説明はありません。

パラグラフ・ライティング ✓ PASS

トピックセンテンス・1段落1トピック・段落長

各セクションは総論・各論・結論の段落構成が取られ、段落はトピックセンテンスで始まり、1段落1トピック・適切な長さが保たれています。

Diff内容との照合 ✓ PASS

コードブロックとDiff内容の一致

記事内のコードスニペットはDiffに記載された変更と一致しており、ファイル名・追加されたロジックが正確に反映されています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`@source`, `base`, `pattern`, `FxHashSet` などの用語はPRで使用されたものと一致し、誤用はありません。

説明の技術的正確性 ✓ PASS

技術的主張の正確性と論理性

技術的説明はPRの内容と合致し、パフォーマンス改善の数値例もPRに記載されたものと矛盾していません。

事実の突合 ✓ PASS

PR情報による主張の裏付け(ハルシネーション検出)

すべての主張はPRのタイトル、説明、Diff、Issue番号に裏付けられており、捏造や推測は見当たりません。

数値・固有名詞の確認 ✓ PASS

PR番号・コミットID・バージョン等の正確性

22秒のハングや約20msへの改善といった数値はPRで示されたものと合致しています。

タイトル・説明との一致 ✓ PASS

記事タイトル・説明とPR内容の一致

記事タイトルはPRタイトルの意味を正確に反映しており、内容と一致しています。

外部知識の正確性 ✓ PASS

PRに記載のない外部知識(LTS、サポート状況など)の不使用

バージョンサポートやリリース日程等、PR外の外部知識は一切含まれていません。

時間表現の正確性 ✓ PASS

時間表現がPR情報と一致しているか

時間表現は PR の記述と矛盾しておらず、正確です。