Lightning CSS 1.32.0 へのバージョンアップと`detect-libc@2`対応パッチの更新

tailwindlabs/tailwindcss

Lightning CSS を 1.31.1 から 1.32.0 へバージョンアップし、detect-libc@2 への移行に伴うネイティブバイナリ解決ロジックのパッチを更新しました。CSS 出力における var() のフォールバック値の空白正規化や、:autofill セレクタの分離など、生成 CSS に複数の変更が生じています。

背景

Lightning CSS 1.32.0 では node/index.js のネイティブバイナリ選択ロジックが変更され、detect-libc@2 を同梱するようになりました。Tailwind CSS はネイティブバイナリ解決時に process.env.PLATFORM_LIBC 環境変数を考慮する必要があり、また Bun のバンドラが require(…) 呼び出しを静的解析できるようにする制約もあるため、アップストリームの変更をそのまま使用できず、独自のパッチを維持しています。

@parcel/watcher@2.5.1 も同様に detect-libc@2 を同梱するようになり、こちらのパッチも合わせて更新が必要になりました。

技術的な変更

detect-libc@2 対応:familySync の無条件呼び出しへの変更

両パッチの最も重要な変更は、detect-libc の API 利用方法の統一です。旧パッチでは detect-libc@1family(非同期)と detect-libc@2familySync の両方に対応するため、typeof familySync === 'function' による条件分岐を設けていました。新パッチでは detect-libc@2 が確定的に使われる前提で、familySync を直接呼び出す形に簡略化されています。

変更前(旧パッチ):

let { MUSL, GLIBC, family, familySync } = require('detect-libc')

// Bun polyfills `detect-libc` in compiled binaries. We rely on
// detect-libc@1.0.3 but the polyfilled version is 2.x. In detect-libc@2x
// there is a `familySync` function that we can use instead.
if (typeof familySync === 'function') family = familySync()

変更後(新パッチ):

let { MUSL, GLIBC, familySync } = require('detect-libc')
let family = familySync()

同様の変更が @parcel/watcher のパッチにも適用されています。

loadPackage() 関数の導入とコメントの整理

両パッチで、プラットフォーム別のバイナリ選択ロジックが loadPackage() 関数に整理されています。各パッチのコード先頭には以下のコメントが統一的に追加されており、パッチが必要な理由が明示されています。

// We need to take the `process.env.PLATFORM_LIBC` into account, and we also
// need static analysis, so we can't make use of the `parts.push(…)` approach.
function loadPackage() {
  if (process.platform === 'linux') {
    if (process.env.PLATFORM_LIBC === 'musl') {
      return require(`lightningcss-${process.platform}-${process.arch}-musl`)
    } else if (process.env.PLATFORM_LIBC === 'glibc') {
      return require(`lightningcss-${process.platform}-${process.arch}-gnu`)
    } else {
      let { MUSL, GLIBC, familySync } = require('detect-libc')
      let family = familySync()
      // ...
    }
  }
  // ...
}

アップストリームが採用している parts.push(…) による動的な require 文字列の組み立ては、Bun の静的解析を通過できないため使用できません。require() の引数を文字列リテラルで固定する必要があり、プラットフォームごとに require を明示的に記述する構造が維持されています。

生成 CSS の変化:var() フォールバック値の空白正規化

Lightning CSS 1.32.0 は、var() のフォールバック値に含まれる余分な空白を除去するようになりました。transform プロパティに使われるカスタムプロパティのフォールバック値が影響を受け、テストスナップショットが大量に更新されています。

変更前:

transform: var(--tw-rotate-x,  ) var(--tw-rotate-y,  ) var(--tw-rotate-z,  ) var(--tw-skew-x,  ) var(--tw-skew-y,  );

変更後:

transform: var(--tw-rotate-x, ) var(--tw-rotate-y, ) var(--tw-rotate-z, ) var(--tw-skew-x, ) var(--tw-skew-y, );

フォールバック値のスペースが2文字から1文字に正規化されています。この変更は rotate-xrotate-yrotate-zskew-xskew-y など多数のユーティリティに影響し、utilities.test.ts で 160 箇所以上のスナップショット更新が発生しています。

セレクタのグルーピング変化::autofill の分離

Lightning CSS 1.32.0 では、:autofill 疑似クラスを含むセレクタが他のセレクタと同一ルールにまとめられなくなりました。この変更により、:autofill を使用するルールは独立したブロックとして出力されます。

変更前:

.group-autofill\:flex:is(:where(.group):autofill *), .peer-autofill\:flex:is(:where(.peer):autofill ~ *), .autofill\:flex:autofill {
  display: flex;
}

変更後:

.group-autofill\:flex:is(:where(.group):autofill *), .peer-autofill\:flex:is(:where(.peer):autofill ~ *) {
  display: flex;
}

.autofill\:flex:autofill {
  display: flex;
}

同様の分離は variant order テストの :autofillnot バリアントの :not(:autofill) でも発生しており、variants.test.ts のスナップショットが更新されています。

設計判断

アップストリームのコード構造に追従しつつ、独自パッチを最小限に維持する方針が一貫して取られています。

アップストリームが parts.push(…) というエレガントな動的文字列構築を採用したとしても、Bun の静的解析要件と PLATFORM_LIBC 環境変数のサポートという2つの制約から、Tailwind CSS 側では require() 引数をリテラルで記述するアプローチを維持せざるを得ません。この判断はパッチのコメントに明示されており、将来のメンテナンス性を考慮した透明性のある記述といえます。

また、detect-libc@2 が確定的に使用される状況になったことで、バージョン互換のための typeof familySync === 'function' 分岐が不要になり、パッチのコードが簡潔になっています。依存側のバージョン移行が完了したことで、互換レイヤーを削除できたという好例です。

まとめ

本 PR は Lightning CSS 1.32.0 へのバージョンアップに伴い、detect-libc@2 対応のパッチ更新と生成 CSS の出力変化をセットで取り込んだ変更です。パッチの維持が必要な理由(Bun の静的解析要件と PLATFORM_LIBC 対応)をコード内コメントで明示することで、今後の同様の変更に対してメンテナンス指針を残している点が注目されます。

記事メタデータ

Generated by:
Claude Sonnet 4.6 for DiffDaily
LLM Trace:
a2f2312a

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

品質レビュー結果

Review Status:
リトライ後承認
Review Count:
2回 (改善を経て承認)
Reviewed by:
Gemini 2.5 Pro for DiffDaily

Review Criteria:

記事構成 ✓ PASS

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

リード文(総論)→背景・技術詳細(各論)→まとめ(結論)の3部構成が明確に守られており、理想的な記事構成です。

カスタムMarkdown構文 ✓ PASS

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

ファイル名付きシンタックスハイライトやPR番号のリンク記法が正しく使用されています。

対象読者への適合性 ✓ PASS

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

ライブラリのパッチ管理やネイティブバイナリの依存関係といった専門的なトピックを、専門知識を持つエンジニア向けに適切に解説しています。

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

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

各セクション、各パラグラフが「総論→各論」の構成で書かれ、トピックセンテンスが明確です。段落の長さも適切で非常に読みやすいです。

Diff内容との照合 ✓ PASS

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

パッチファイルやテストスナップショットの変更点を、記事内のコードブロックで正確に引用・解説できています。

技術用語の正確性 ✓ PASS

技術用語の正確な使用

`detect-libc`, `familySync`, `Bunの静的解析`などの技術用語を文脈に沿って正確に使用しています。

説明の技術的正確性 ✓ PASS

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

パッチの更新理由や、Lightning CSSのバージョンアップによるCSS出力の変化についての説明が、PR情報とDiffによって完全に裏付けられており、技術的に正確です。

事実の突合 ✓ PASS

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

記事内のすべての主張が、PRのDescriptionやDiff内のコードで裏付けられており、ハルシネーションは一切見られません。

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

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

PR番号、ライブラリのバージョン番号、ファイルパスなどの数値・固有名詞がすべて正確に記載されています。

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

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

記事のタイトルは、PRの主題である「Lightning CSSのバージョンアップ」とそれに伴う主要な作業内容を的確に要約しており、内容と一致しています。

外部知識の正確性 ✓ PASS

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

PR情報に含まれない外部の知識(LTS情報、リリース予定など)の持ち込みはなく、提供された情報源に忠実です。

時間表現の正確性 ✓ PASS

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

「〜するようになりました」「〜が変更され」といった時間表現は、PRで実施された変更を正確に反映しています。