WordPress のブロックエディター(Gutenberg)や FSE (フルサイト編集) 機能の登場によって、様々なコンテンツを記事もサイトも「ブロック」単位で自由に組み立てて構築できるようになりました。
さらにコンテンツの構成単位である「ブロック」は、プラグインやテーマの開発者がオリジナルのものをいくつでも組み込めます。
また、WordPress 標準のコアブロックに対しても開発者は必要に応じて独自の CSS を適用できます。
しかし、対象とする全てのブロックの CSS や JavaScript のファイルを1つにまとめてしまうと、拡張する標準ブロックや提供する独自ブロックが多くなるほど不要なリソースを消費させ、レスポンス低下の原因になってしまいます。
そこで、対象のブロックごとに必要な CSS や JavaScript を細分化し、さらに「ページ内に対象のブロックが存在する場合のみ必要な CSS や JavaScript を読み込ませる」ようにする必要があります。
ブロックテーマの場合、wp_enqueue_block_style
という便利な関数が提供されており、この関数でブロックごとに CSS を登録すれば、対象ブロックがレンダリングされるときのみ必要な CSS を head セクション内にインラインで読み込ませることができます。
function custom_enqueue_block_style() { wp_enqueue_block_style( // 対象とするブロック名(スラッグ) 'core/paragraph', array( // 登録する CSS のハンドル名(識別ID) 'handle' => 'extended-paragraph', // 読み込ませたい CSS ファイルのパス (テーマの場合は get_theme_file_uri )。 'src' => plugins_url( 'css/core-paragraph.css' ), // path を指定しておくと、スタイルシートの内容が一定量以下ならばインライン化する?(テーマの場合は get_theme_file_path ) 'path' => plugin_dir_path( __FILE__ ) . 'css/core-paragraph.css', // 依存関係にある(先に読み込ませておくべき) CSS のハンドル名 'deps' => array() ) ); } add_filter( 'after_setup_theme', 'custom_enqueue_block_style' );
wp_enqueue_block_style
の第2パラメータ(array)に src
とは別に path
というキーで CSS ファイルのパスを指定しておくと、対象の CSS ファイルが一定のサイズ以下であれば、CSS ファイルの内容をインラインで出力します。
(逆に、スタイルシートのコード量が多すぎる場合はインラインでなく link
要素になる?)
その他のパラメータや詳細について公式ドキュメントを参照してください。
テーマがクラシックテーマの場合、プラグイン側で wp_enqueue_block_style
を利用してパフォーマンスの向上を図っても、wp_enqueue_block_style
で登録された CSS は対象ブロックの存在有無は関係なくすべて読みこんでしまいます。
従来の wp_enqueue_style
で読み込む場合の違いは、link
要素でファイルとして読み込まれるか style
要素でインライン化されるかだけの違いになります。
また、クラシックテーマの場合は、WordPress 5.8 にて実装されたshould_load_separate_core_block_assets
フィルターフックを利用すればブロックの種類ごとに CSS を読み込ませることが可能になりますが、head セクションではなく、body 要素内に CSS が読み込まれてしまうことと、CSS の読み込み順序が変わってしまうため、今まで上書きしていたスタイルが反映されなくなるなど、色々と影響があります。
add_filter( 'should_load_separate_core_block_assets', '__return_true' );
そこで、今回は別の方法でクラシックテーマも考慮したブロック単位での CSS と JavaScript のキューへの追加方法を考えてみます。
フィルターフックを使い分ける
wp_enqueue_block_style
関数は、通常 after_setup_theme
フィルターフックのタイミングで利用されることが多いようですが、ブロックがレンダリングされる直前に処理を挟むことができる render_block
フィルターでも利用できます。
ブロックの種類ごとでフックできる render_block_{block_name}
をトリガーとすることで、クラシックテーマであっても対象ブロックが実際にレンダリングされるときのみ、専用の CSS や JavaScript を読み込ませることができそうです。
例えば、見出しブロック(core/heading)のレンダリング時に処理をしたい場合は、render_block_core/heading
となります。
フィルターフックの使い分け
使用するフック名 | 役割 |
---|---|
after_setup_theme | ・ブロックテーマ用のカスタム CSS の登録 |
render_block_{block_name} | ・クラシックテーマ用のカスタム CSS の登録 ・特定のブロック用の JavaScript の登録(共通) |
ブロックテーマ用のカスタム CSS の登録(キュー追加)
ブロックテーマの場合は、シンプルに wp_enqueue_block_style
のみで特定のブロックがレンダリングされるときのみ、インラインスタイルを挿入できるので、ブロックテーマの場合のみ実行させます。
function additional_after_setup_theme(){ // クラシックテーマの場合はスルー if ( ! wp_is_block_theme() ) return; // 対象のブロック(ここに必要なだけ追加) $blocks = [ 'core/heading', // 見出し 'core/paragraph', // 段落 'core/button' // ボタン ]; foreach( $blocks as $block ) { $args = array( 'handle' => 'custom-' . esc_attr( str_replace( '/', '-', $block ) ), // テーマの場合は get_theme_file_uri( css/' . $block . '/style.css' ) 'src' => plugins_url( 'css/' . $block . '/style.css', __FILE__ ), // テーマの場合は get_theme_file_path( css/' . $block . '/style.css' ) 'path' => plugin_dir_path( __FILE__ ) . 'css/' . $block . '/style.css' ); wp_enqueue_block_style( $block, $args ); } } add_filter( 'after_setup_theme', 'additional_after_setup_theme' );
このサンプルでは、{plugin_dir}/css/{block_name}/style.css
に CSS ファイルがある環境を前提にしています。
例 : https://mydomain.com/wp-content/plugins/my-plugin/css/core/heading/style.css
クラシックテーマ用のカスタム CSS の登録
クラシックテーマの場合は、render_block_{block_name}
フックを利用して、クラシックテーマの場合のみ、wp_enqueue_block_style
でカスタム CSS をインライン出力させます。
// 対象のブロック(ここに必要なだけ追加) $blocks = [ 'core/heading', 'core/paragraph', 'core/button' ]; function additional_render_block( $block_content, $block ){ // ブロックテーマの場合はスルー if ( wp_is_block_theme() ) return; $args = array( 'handle' => 'custom-' . esc_attr( str_replace( '/', '-', $block['blockName'] ) ), 'src' => plugins_url( 'css/' . $block['blockName'] . '/style.css', __FILE__ ), 'path' => plugin_dir_path( __FILE__ ) . 'css/' . $block['blockName'] . '/style.css', ); wp_enqueue_block_style( $block['blockName'], $args ); return $block_content; } foreach( $blocks as $block ) { // 3番目のパラメータ{ 2 }は関数に渡す引数の数($block_content, $block) add_filter( 'render_block_' . $block, 'additional_render_block', 10, 2 ); }
JavaScript の登録
JavaScript に関しては CSS のwp_enqueue_block_style
のような関数はないため、先述の render_block_{block_name}
フックを利用した関数内でキューに追加します。
この処理は、ブロックテーマ、クラシックテーマ共に実行されます。
// 対象のブロック(ここに必要なだけ追加) $blocks = [ 'core/heading', 'core/paragraph', 'core/button' ]; function additional_render_block( $block_content, $block ){ // クラシックテーマの場合のみ if ( ! wp_is_block_theme() ) { $args = array( 'handle' => 'custom-' . esc_attr( str_replace( '/', '-', $block['blockName'] ) ), 'src' => plugins_url( 'css/' . $block['blockName'] . '/style.css', __FILE__ ), 'path' => plugin_dir_path( __FILE__ ) . 'css/' . $block['blockName'] . '/style.css', ); // カスタム CSS の登録 wp_enqueue_block_style( $block['blockName'], $args ); } // script.js ファイルがあるときのみ if ( file_exists( plugin_dir_path( __FILE__ ) . 'js/' . $block['blockName'] . '/script.js' ) ) { // JavaScript の登録(キュー追加) wp_enqueue_script( 'custom-' . esc_attr( str_replace( '/', '-', $block['blockName'] ) ), plugins_url( 'js/' . $block['blockName'] . '/script.js', __FILE__ ), array(), false, true ); } return $block_content; } foreach( $blocks as $block ) { add_filter( 'render_block_' . $block, 'additional_render_block', 10, 2 ); }
このサンプルでは、{plugin_dir}/js/{block_name}/script.js
にファイルがある環境を前提にしています。
例 : https://mydomain.com/wp-content/plugins/my-plugin/js/core/heading/script.js
まとめる(クラス化)
以上の処理をまとめると、クラス化したほうが効率的なのでクラス化しておきます。
class My_Custom_Block_Style { // 対象のブロック public static $blocks = [ 'core/heading', 'core/paragraph', 'core/button' ]; function __construct() { add_filter( 'after_setup_theme', array( __CLASS__, 'additional_after_setup_theme' ) ); foreach( self::$blocks as $block ) { add_filter( 'render_block_' . $block, array( __CLASS__, 'additional_render_block' ), 10, 2 ); } } public static function additional_after_setup_theme(){ if ( ! wp_is_block_theme() ) return; foreach( self::$blocks as $block ) { $args = array( 'handle' => 'custom-' . esc_attr( str_replace( '/', '-', $block ) ), 'src' => plugins_url( 'css/' . $block . '/style.css', __FILE__ ), 'path' => plugin_dir_path( __FILE__ ) . 'css/' . $block . '/style.css' ); wp_enqueue_block_style( $block, $args ); } } public static function additional_render_block( $block_content, $block ){ if ( ! wp_is_block_theme() ) { $args = array( 'handle' => 'custom-' . esc_attr( str_replace( '/', '-', $block['blockName'] ) ), 'src' => plugins_url( 'css/' . $block['blockName'] . '/style.css', __FILE__ ), 'path' => plugin_dir_path( __FILE__ ) . 'css/' . $block['blockName'] . '/style.css', ); wp_enqueue_block_style( $block['blockName'], $args ); } if ( file_exists( plugin_dir_path( __FILE__ ) . 'js/' . $block['blockName'] . '/script.js' ) ) { wp_enqueue_script( 'custom-' . esc_attr( str_replace( '/', '-', $block['blockName'] ) ), plugins_url( 'js/' . $block['blockName'] . '/script.js', __FILE__ ), array(), false, true ); } return $block_content; } } new My_Custom_Block_Style();
このクラスをプラグイン化したり、テーマの function.php に組み込むことで、ブロックテーマ、クラシックテーマのどちらであっても、ページ内に特定のブロックがある場合のみ独自の CSS を head
セクション内にインライン出力し、</body>
の前に任意の JavaScript を読み込ませることができます。