WordPressブロック開発 画像ブロックにフェードイン表示機能を実装する

画面をスクロールすると、画像がフェードインで表示するようにカスタマイズします。フェードイン用のスクリプトとスタイルは画像ブロックがない場合はフロントに読み込ませないようにし軽量化を図ります。

JavaScriptとCSSファイルを「登録」する

JavaScriptとCSSファイルを任意のタイミングで利用できるように、準備段階として「登録」します。

namespace BlockDevelopersCookbook;

add_action('wp_enqueue_scripts', __NAMESPACE__ . '\register_custom_js_script');

function register_custom_js_script() {
    $js_file = plugin_dir_path(__FILE__) . '/build/index.asset.php';

    if (file_exists($js_file)) {

        $js_assets = include $js_file;

        wp_register_script(
            'custom-script-for-code-block',
            plugin_dir_url(__FILE__) . '/build/index.js',
            $js_assets['dependencies'],
            $js_assets['version'],
            true
        );

        wp_register_style(
            'test-styles',
            plugin_dir_url(__FILE__) . '/build/index.css',
            array(),
            $js_assets['version'],
        );
    }

具体的にはwp_register_script()wp_enqueue_script()を使用してあとで呼び出すファイルの内容を準備し、wp_enqueue_scriptsにフックします。

wp_enqueue_scripts フックに関数を登録しても、その関数の中で wp_enqueue_script() または wp_enqueue_style() を呼ばなければ、スクリプトやCSSは読み込まれない。

wp_enqueue_scriptsフックの中で呼べる関数

JavaScript も CSS も、「登録」や「読み込み」に使うフックは wp_enqueue_scriptsになる。

ステップ関数目的
登録wp_register_script
wp_register_style
あとで使うために準備する
読み込みwp_enqueue_script
wp_enqueue_style
実際にブラウザでスクリプトを読み込む

特定のブロックがページ上に存在するときだけJavaScriptとCSSファイルを読み込む

add_filter('render_block', __NAMESPACE__ . '\enqueue_files_for_core_blocks', 10, 2);

function enqueue_files_for_core_blocks($block_content, $block) {

    if ('core/cover' === $block['blockName'] || 'core/image' === $block['blockName']) {
        $tag = new \WP_HTML_Tag_Processor($block_content);
        if ($tag->next_tag()) {
            $tag->add_class('fader');
        }
        $block_content = $tag->get_updated_html();

        wp_enqueue_script('custom-script-for-code-block');
        wp_enqueue_style('test-styles');
    }
    return $block_content;
}

特定のブロックが使われているかどうかを確認し、そのブロックが使われているページだけにスクリプトを読み込むため、render_block フィルターを使う。

render_block フィルター

  • ブロックが レンダリングされるたびに実行されるフィルター
  • 第1引数にブロックのHTML、第2引数にブロック情報の配列が渡される
  • 各ブロックごとに呼び出されるため、その場でスクリプトを読み込ませる判断ができる
add_filter( 'render_block', __NAMESPACE__ . '\enqueue_files_for_core_blocks', 10, 2 );

処理の流れ

1. 関数定義

function enqueue_files_for_core_blocks( $block_content, $block ) {
  • $block_content: ブロックのHTML(文字列)
  • $block: ブロックの情報(連想配列)→ ['blockName' => 'core/image', ...] など

2.ブロックタイプをチェック

if ( 'core/cover' === $block['blockName'] || 'core/image' === $block['blockName'] ) {
  • core/covercore/image ブロックがあればスクリプトとCSSを読み込む

3.HTML にクラスを追加(オプションの演出)

$tag = new \WP_HTML_Tag_Processor( $block_content );
if ( $tag->next_tag() ) {
    $tag->add_class( 'fader' );
}
$block_content = $tag->get_updated_html();
  • WordPress 6.2 以降で使える WP_HTML_Tag_Processor クラスを使って、
  • ブロックのHTMLに fader クラスを付加
  • これは、アニメーションやCSSの指定に使う想定

4.スクリプトとスタイルを読み込み

wp_enqueue_script( 'custom-script-for-core-block' );
wp_enqueue_style( 'test-styles' );
  • あらかじめ wp_register_script() などで登録しておいたスクリプトを読み込む
  • 読み込みは このブロックがあったページだけ になる

5.最後に、変更後のHTMLを返す

return $block_content;
  • フィルターは常に内容を返す必要がある
  • これを忘れるとブロックの出力が消える

各ブロックに専用のフィルターを使用する

render_blockフックの代わりに、render_block_coreフックを使用することもできる

add_filter('render_block_core/cover', __NAMESPACE__ . '\enqueue_files_for_core_blocks', 10, 2);
add_filter('render_block_core/image', __NAMESPACE__ . '\enqueue_files_for_core_blocks', 10, 2);

function enqueue_files_for_core_blocks($block_content, $block) {
    $tag = new \WP_HTML_Tag_Processor($block_content);
    if ($tag->next_tag()) {
        $tag->add_class('fader');
    }
    $block_content = $tag->get_updated_html();

    wp_enqueue_script('custom-script-for-code-block');
    wp_enqueue_style('test-styles');
    return $block_content;
}

render_block は 各ブロックごとに複数回呼ばれる

render_block は 各ブロックごとに複数回呼ばれる ので、無駄な enqueue_* 呼び出しが発生している。まず確認してみよう

add_filter('render_block', __NAMESPACE__ . '\enqueue_files_for_core_blocks', 10, 2);

function enqueue_files_for_core_blocks($block_content, $block) {

    // 追記
    if (isset($block['blockName'])) {
        echo '<!-- Rendering block: ' . esc_html($block['blockName']) . ' -->';
    }

    if ('core/cover' === $block['blockName'] || 'core/image' === $block['blockName']) {

        $tag = new \WP_HTML_Tag_Processor($block_content);
        if ($tag->next_tag()) {
            $tag->add_class('fader');
        }
        $block_content = $tag->get_updated_html();

        wp_enqueue_script('custom-script-for-code-block');
        wp_enqueue_style('test-styles');
    }
    return $block_content;
}

その結果、開発者ツールにコメントが表示される。

<!-- Rendering block: core/image -->

また、別の方法では、デバッグモードを活用するため、wp-config.phpでデバッグモードを有効にし、エラーログをファイルに出力する設定にする。wp-content/debug.logが自動生成されログが記録されていく。

define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false ); // ← これで画面には何も出ない

完成形

namespace BlockDevelopersCookbook;

add_action('wp_enqueue_scripts', __NAMESPACE__ . '\register_custom_js_script');

function register_custom_js_script() {
    $js_file = plugin_dir_path(__FILE__) . '/build/index.asset.php';

    if (file_exists($js_file)) {

        $js_assets = include $js_file;

        wp_register_script(
            'custom-script-for-code-block',
            plugin_dir_url(__FILE__) . '/build/index.js',
            $js_assets['dependencies'],
            $js_assets['version'],
            true
        );

        wp_register_style(
            'test-styles',
            plugin_dir_url(__FILE__) . '/build/index.css',
            array(),
            $js_assets['version'],
        );
    }
}

add_filter('render_block_core/cover', __NAMESPACE__ . '\enqueue_files_for_core_blocks', 10, 2);
add_filter('render_block_core/image', __NAMESPACE__ . '\enqueue_files_for_core_blocks', 10, 2);

function enqueue_files_for_core_blocks($block_content, $block) {
    $tag = new \WP_HTML_Tag_Processor($block_content);
    if ($tag->next_tag()) {
        $tag->add_class('fader');
    }
    $block_content = $tag->get_updated_html();

    wp_enqueue_script('custom-script-for-code-block');
    wp_enqueue_style('test-styles');
    return $block_content;
}