`@variant` が JS プラグイン API でも利用可能に
この PR は、JavaScript ベースのプラグイン API 内で @variant を利用できるようにする回帰テストを追加し、コアロジックを修正して @variant の置換処理を正しく実行すると同時に、AST の走査を二重に行う無駄を排除しました。
背景
Tailwind CSS v4.3.1 で導入された addBase プラグイン API 向けの @variant 対応は、カスタムバリアントが後から追加された場合に早すぎる置換が原因でエラーになるという回帰を引き起こしました。結果として、@variant が CSS 出力に残るか、ビルドが失敗するケースが報告されました。
この問題は PR #20247 によって addBase での置換タイミングが遅延されて修正されたものの、同様の置換ロジックが JavaScript プラグイン API(例: @tailwindcss/typography)でも使用されているため、同様のバグが潜在的に残っていました。
結論として、JS ベースのプラグインでも @variant が安全に使用できることを保証し、将来的な回帰を防ぐ必要がありました。
技術的な変更
テスト側では、@tailwindcss/typography プラグインとカスタムバリアントを組み合わせたシナリオを統合テストとして追加し、ビルド結果に @variant が残らないことを検証します。これにより、実際の利用環境での回帰が自動的に捕捉できるようになります。
test(
'builds the `@tailwindcss/typography` plugin utilities with `@variant` usages',
{
fs: {
'package.json': json`
{
"dependencies": {
"@tailwindcss/typography": "^0.5.14",
"tailwindcss": "workspace:^",
"@tailwindcss/cli": "workspace:^"
}
}
`,
'src/index.css': css`
@import 'tailwindcss/utilities';
@theme { --breakpoint-sm: 640px; }
@plugin '@tailwindcss/typography';
@custom-variant custom (&.custom);
`,
'tailwind.config.js': ts`
module.exports = {
theme: {
typography: ({ theme }) => ({
custom: {
css: {
hr: {
'--x': '1',
'@variant sm:custom': { '--x': '2' },
},
},
},
}),
},
};
`,
},
}
);
このテストは、@variant sm:custom が最終的な CSS に現れないことを期待し、ビルドが成功するかどうかを検証します。テストファイルは既存のテストスイートに統合され、CI で自動的に実行されます。
コアロジックでは、buildDesignSystem 関数内で AST のノード配列を一度だけ生成し、substituteFunctions と substituteAtVariant の両方に同じ配列を渡すように変更しました。これにより、同一ノード集合を二度走査するオーバーヘッドが除去されます。
@@
- substituteFunctions(
- ast.map(({ node }) => node),
- designSystem,
- )
- substituteAtVariant(
- ast.map(({ node }) => node),
- designSystem,
- )
+ let nodes = ast.map((value) => value.node)
+ substituteFunctions(nodes, designSystem)
+ substituteAtVariant(nodes, designSystem)
nodes 変数は ast から抽出した node のみを保持し、以降の置換処理はこの配列に対して行われます。コード量は減少し、意図が明確になると同時に、実行時のメモリ割り当て回数も削減されます。
結論として、テスト追加とコア修正により、JS プラグイン API でも @variant が正しく処理され、ビルド速度の微小な改善も期待できます。
設計判断
今回の実装は、substituteAtVariant を既存の substituteFunctions と同一ノードリストに対して実行するというシンプルな統合戦略を採用しました。ロジックの分割は維持しつつ、共通データ構造を共有することで余分な計算を排除しています。
このアプローチは、コードベースの可読性を保ちつつ、将来的に他の置換処理が追加された場合でも同様にノードリストを再利用できる拡張性を提供します。パフォーマンス向上は限定的ですが、無駄なループを除去したことでメンテナンスコストが低減しました。
結論として、最小限の変更で後方互換性を確保し、@variant の使用範囲を拡大した設計判断は、Tailwind CSS の拡張性と安定性を同時に高める選択と言えます。
まとめ
本 PR は、JavaScript ベースのプラグイン API でも @variant が安全に利用できるように統合テストを導入し、コアの置換ロジックを最適化しました。テスト追加により回帰が防止され、AST の二重走査削減で僅かなビルド効率向上が期待できます。