ナビゲーション

Directives

ネイティブ CSS のプルーニング

各スタイルシート内で、ネイティブクラスの不要な定義の除去と、必要に応じて生成するキーフレームを制御します。

このページの内容

ネイティブ CSS のプルーニングは未使用のクラスセレクター分岐を除き、キーフレームをオンデマンドで利用可能にします。ユーティリティクラスの生成とは別のスタイルシート方針です。有効化の判断は CSS 配信の最適化、ソースと候補のフィルターはスキャンディレクティブを参照してください。

プルーニングの指示はファイル境界まで

このコンパイルで使うのは local だけです。app.css は有効、cards.css は無効で、インポートしても指示は伝わりません。

テキストによる説明
  1. app.css は @prune native、cards.css のインポート、.local と .unused-local の定義を持ちます。使用クラスは local だけです。
  2. 出力は .local を保持し .unused-local を除きます。
  3. cards.css はプルーニングも保持も宣言しません。両クラスとも未使用ですが、既定方針で .card と .unused-card を保持します。
  4. プロジェクト全体の pruneNativeCSS オプションはプロジェクトファイルを別途対象にできます。@preserve native は自身のファイルで優先します。この例は明示的なファイル別方針だけを示します。

クラスリストを渡しても、ネイティブ CSS は既定で保持します。統合やスタイルシート API で pruneNativeCSS: true を設定すると、プロジェクト所有のソースをプルーニングできます。パッケージ CSS は自身のソースが明示的に有効化しない限り保持します。

@prune native

@prune native;.used {  color: red;}.unused {  color: blue;}

このディレクティブは宣言ファイルだけでプルーニングを有効にし、インポート先には伝わりません。統合がプロジェクト全体で有効化していても、同じファイルの @preserve native; が優先します。ネイティブ出力のスイッチ preserveNativeCSS: false は別で、両ディレクティブに関係なくネイティブ出力を抑制します。

@preserve native

Master 管理のスタイルシートに、ネイティブ CSS のプルーニングで除去してはいけないネイティブクラス規則がある場合は @preserve native; を使います。

@import "@master/css";@preserve native;.injected-by-payment-widget {  color: blue;}

スタイルシートは引き続き Master CSS で処理します。スキャン元がクラスを使わなくてもネイティブクラス規則を保持し、通常のコンパイラー正規化は適用します。この方針は未使用の管理クラスを生成出力に強制せず、元の CSS のバイト列を保つという意味でもありません。

同一ファイルでは preserve が prune に優先

両ケースでネイティブ配信は有効です。この方針はネイティブ CSS を保持するもので、未使用の管理ユーティリティをセーフリストには入れません。

テキストによる説明
  1. 同じファイルに @preserve native と @prune native があれば、どちらの順でも保持が優先します。
  2. そのためスキャンした widget クラスがなくてもネイティブの .widget 規則を保持します。
  3. preserveNativeCSS: false は別の出力スイッチで、両ディレクティブに関係なくネイティブ配信を抑制できます。

インポートグラフ

解決した CSS インポートは各ソース境界を保ち、各ファイルの方針はそのファイルだけに適用します。読み込み元は依存先のプルーニングを有効にできません。pruneNativeCSS: true では、@preserve native; を宣言しないプロジェクト所有の依存先が対象です。パッケージやリモートのスタイルは、プロジェクトが読み込むだけで所有対象にはなりません。修飾付きインポートは media、supports、layer のラッパーを保ちます。

src/style.css
@prune native;@import "@master/css";@import "./cards.css";
src/cards.css
@prune native;.card {  border: 1px solid rgb(0 0 0 / 12%);}.unused-card {  color: red;}

スキャン元に card があれば、出力は .card を保持し .unused-card を除きます。cards.css にディレクティブがなければ両方残ります。

起点のスコープ

有効化は各ソースファイルに属し、フィルターはそれを読み込む起点の使用スコープを使います。そのため有効化した同じ共有ファイルも、起点ごとに別のクラスを保持できます。JavaScript やフレームワークのルートが直接読み込むファイルは、そのインポートが Master CSS のパイプラインに入った場合だけ自身の起点になります。

起点は既定でグローバルなスキャナースコープを使います。インポートグラフ内のどこにある @source、@source not、@safelist、@blocklist でも範囲を狭めたり広げたりできます。インポート先のディレクティブは、それを読み込む全起点に結合し、相対パターンは宣言ファイルを基準に解決します。

app/a/a.css
@prune native;@import "@master/css";@source "./page.html";@import "../shared.css";
app/shared.css
@prune native;@blocklist "debug-*";.shared-card {  border: 1px solid rgb(0 0 0 / 12%);}.only-used-in-b {  color: blue;}.debug-outline {  outline: 1px solid red;}

app/a/page.html が shared-card だけを使う場合、a.css の出力は .shared-card を残し、.only-used-in-b と .debug-outline を除きます。別の起点 b.css のページが only-used-in-b を使えば、同じファイルからその規則を保持します。

規則のフィルター

クラスセレクター規則は、分岐内のいずれかのクラスを使えば保持し、未使用の分岐はリストから除きます。検査は DOM 関係ではなくクラス名によります。.card .title なら card か title のどちらかがあれば分岐を保持するため、保持された規則がどの要素にも一致しない場合もあります。

@prune native;body {  margin: 0;}.card,.unused:hover {  border: 1px solid rgb(0 0 0 / 12%);}@media (width >= 48rem) {  .card .title {    font-weight: 700;  }  .debug-card {    outline: 1px solid red;  }}

card と title を使うと、出力は body、.card、.card .title を残し、.unused:hover と .debug-card を除きます。body、html、:root のようなクラスセレクターのない規則は常に保持します。プルーニングで空になった at-rule ブロックは除きます。

プルーニングはクラス使用で分岐を保持

保持の強調はセレクターの分岐単位です。プルーニングは使用クラス名を調べ、完全なセレクターが現在要素に一致するかは調べません。

テキストによる説明
  1. @prune native を有効にして card を使うと、.card, .unused:hover は .card 分岐だけを保持します。
  2. 別の .card .title 分岐は使用集合に card があるため保持し、title を見つける必要はありません。
  3. 保持は DOM に title の子孫がある証明ではありません。クラスセレクターのない規則も引き続き保持します。

manifest の参照

保持されたネイティブ規則が var(--*) を読むか manifest のアニメーションを指定すると、プロジェクトのエントリーグラフ内の対応するテーマ変数とキーフレームを保持します。除去した規則は何も保持しません。

@prune native;@import "@master/css";@theme {  --color-primary: #175cff;}.notice {  color: var(--color-primary);}.unused-notice {  color: var(--color-primary);}

notice だけを使うと、.notice を保持するため --color-primary を出力し、.unused-notice は除きます。

含めるクラス

@safelist は範囲が限定された外部ソースのネイティブクラスを使用済みとし、プルーニングで規則を保持します。スキャン元に書いたアプリのクラスを置き換えるものではありません。

@prune native;@safelist "dialog-open dialog-closing";.dialog-open {  overflow: hidden;}.dialog-closing {  pointer-events: none;}

ネイティブキーフレーム

ネイティブ CSS でキーフレームを宣言し、所有ファイルで使用状況に応じた出力を有効にします。

@prune native;@theme {  --animate-reveal: reveal .2s ease-out both;}@keyframes reveal {  from {    opacity: 0;  }  to {    opacity: 1;  }}@safelist keyframes "external-enter" "external-exit";@keyframes external-enter {  from {    opacity: 0;  }  to {    opacity: 1;  }}@keyframes external-exit {  from {    opacity: 1;  }  to {    opacity: 0;  }}

キーフレームはネイティブクラス規則と同じファイル方針に従います。既定ではネイティブ CSS として元の位置にそのまま残り、Master CSS が再出力することはありません。@prune native; はそのファイルのキーフレームをトークンのようなオンデマンド定義にします。ネイティブ出力から外れ、使用する出力が生成 CSS とともに出力します。両ディレクティブがあれば @preserve native; が優先します。方針は宣言ファイルだけに適用し、インポートでは伝わりません。pruneNativeCSS はプロジェクト所有ファイルの範囲を保ちます。パッケージ CSS は明示的にプルーニングを有効にしない限り保持します。preserveNativeCSS: false はネイティブ配信を抑制しますが、オンデマンド定義は使用箇所で出力します。

キーフレーム使用の起点

アニメーションのユーティリティ、ネイティブ宣言、静的アニメーショントークン、キーフレームのセーフリストが対応する定義を使います。解析は一括指定値、animation-name のリスト、入れ子の変数、代替値、スコープ付き上書き、推移的なトークン依存を追います。使用する定義はフレームが読むトークンも使います。ネイティブ定義は、フレームをスタイルシート自身が配信するため、そのトークンだけを供給します。未解決の動的な名前は保守的にコンパイルグラフ内の全候補定義を使い、情報診断を出します。

クラスがなくてもアニメーション名で定義を保持

ファイルは @prune native を有効にしています。キーフレームのセーフリストはリソースを保持し、アニメーションは開始しません。

テキストによる説明
  1. @prune native のあるファイルでは @safelist keyframes "reveal" が対応する @keyframes reveal 定義を保持します。
  2. 出力はキーフレーム定義を含みますが、このセーフリストだけでクラスやアニメーション宣言は生成しません。
  3. アニメーションの選択には別のネイティブ宣言やスクリプトが必要です。使わなければ定義を保持するだけで見えるアニメーション効果はありません。

キーフレームの条件と制約

出力するオンデマンド定義は、修飾付きインポートのレイヤーを含め、宣言時の条件とレイヤー規則で包み、生成レイヤーの後に置きます。同じコンテナー内の定義はラッパーを共有します。同名の定義も宣言順に別々に保ち、どれが勝つかはブラウザーが決めます。名前はデコードし、大文字小文字を区別します。匿名レイヤーには再入できないため、その中にある、またはそこへ読み込むオンデマンドキーフレームはコンパイルエラーです。レイヤーに名前を付けるかファイルを保持してください。フレームは元のスタイルシートから離して出力するため、内部の相対 url() もエラーです。絶対 URL を使うかファイルを保持します。定義 ID は宣言ファイルに最も近い名前付き package.json とパッケージ相対パスから作るため、同じプロジェクトはチェックアウト先やインストール先によらず同一の CSS を出力します。パッケージ名を変えると ID が変わり、名前付きパッケージ外のファイルは絶対パスを代わりに使います。

キーフレームリソースの所有権

フレームにはネイティブ宣言を含め、フレーム内の入れ子ディレクティブと @apply は未対応です。未使用のユーティリティと ミックスイン、除去したネイティブ規則、未配信の参照スタイルは使用の起点になりません。@reference は保持方針やセーフリストを読み込まず、定義をオンデマンドで利用可能にします。相対 URL を持つネイティブキーフレームは元のスタイルシートとともに残ります。プロジェクトやベース manifest のネイティブキーフレームも、それを配信しないスタイルシートではオンデマンドです。emitted globals は出力がネイティブまたはオンデマンドで配信するキーフレームを列挙し、他の出力の重複を防ぎます。JavaScript だけで導入するアニメーション名には @safelist keyframes "reveal"; を使います。

ランタイムのキーフレーム寿命

ランタイムは定義 ID と名前を別に追跡し、オンデマンド定義を自身のスタイルシートに挿入します。DOM の削除で定義を解放するのは、ネイティブの使用、静的トークン、セーフリストのどれも使用しなくなった場合だけです。HMR は定義と emitted globals を一緒に置き換え、SSR ハイドレーションは同じ ID とリソース順を使います。リンクされたスタイルシートは通常の CSS のままで、付随ファイルやマーカーはありません。

Native keyframes

@keyframes fade-in { to { opacity: 1; } }
生成された CSS
@keyframes fade-in {  to {    opacity: 1;  }}