1. ホーム
  2. WordPress

【WordPress】block.json の editorStyle・style・viewScript の使い方|カスタムブロックのCSSとJSを読み込む方法

Share

カスタムブロックを作っていると、「エディターでは崩れていないのにフロントでスタイルが当たらない」「フロント用に書いた JavaScript がエディター側でも動いてしまう」といった問題にぶつかります。こうした読み込み先の指定は、wp_enqueue_style() を自分で書くのではなく block.json のアセット項目で行うのが現在の作法です。この記事では editorScript / editorStyle / style / viewScript といった項目がそれぞれどの場面で読み込まれるのかを整理し、file: プレフィックスによる指定と @wordpress/scripts のビルド結果との対応まで解説します。

ブロックのアセットは「どこで動くか」で分かれる

カスタムブロックの CSS と JavaScript は、大きく3つの場面に分かれます。1つ目はブロックエディターの中です。registerBlockType() を呼んでブロックを登録するコードや、編集画面でだけ見せたい補助線・プレースホルダーのスタイルがここに当たります。2つ目は公開ページ(フロントエンド)で、訪問者が実際に目にする見た目や、アコーディオンの開閉のような動きです。そして3つ目がその両方で、ブロックの基本的なレイアウトなど、エディターでもフロントでも同じように当てたいスタイルが該当します。

block.json のアセット項目は、この「どこで動くか」にそのまま対応しています。項目を選ぶだけで、WordPress が適切な場面でだけファイルを読み込んでくれます。しかも style や viewScript は、そのブロックがページ内に実際に存在するときだけ読み込まれます。ブロックを使っていないページに余計な CSS・JS が配信されないという利点があり、これは wp_enqueue_scripts フックで自前に書いていた頃には手間のかかっていた部分です。

block.json のアセット項目一覧

指定できる項目と、読み込まれる場面は次のとおりです。

項目種類読み込まれる場面
editorScriptJSブロックエディターのみ
scriptJSエディターとフロントの両方
viewScriptJSフロントのみ(ブロックがページにあるとき)
viewScriptModuleJSフロントのみ。ES モジュールとして読み込む(WordPress 6.5 以降)
editorStyleCSSブロックエディターのみ
styleCSSエディターとフロントの両方
viewStyleCSSフロントのみ(WordPress 6.5 以降)

迷ったときの基本形はシンプルです。ブロックを登録するコードは editorScript、ブロックの見た目は style、編集画面でだけ必要な調整は editorStyle、フロントの動きは viewScript。この4つでほとんどのブロックは足ります。

style と editorStyle の関係

style と editorStyle は排他ではなく、重ねて使うものです。エディターでは style が読み込まれたうえで editorStyle が後から読み込まれるため、共通の見た目を style に書き、編集時だけ必要な差分を editorStyle で上書きする、という組み立てになります。

「編集時だけ必要な差分」とは、たとえば中身が空のときに枠線を見せる、ドラッグ用の余白を足す、フロントでは position: fixed にしている要素を編集しやすいよう static に戻す、といったものです。訪問者には見せないので style に混ぜてはいけません。

file: プレフィックスで相対パスを指定する

各項目には、登録済みのハンドル名か、file: から始まる相対パスを書きます。実務ではほぼ後者です。file: を使うと、block.json のある場所を基点にファイルを探し、WordPress がハンドル名の生成・登録・読み込みまで自動で行ってくれます。wp_register_script() を自分で書く必要はありません。

src/block.json
{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "webool/notice-box",
  "title": "お知らせボックス",
  "category": "widgets",
  "icon": "info",
  "textdomain": "webool",
  "editorScript": "file:./index.js",
  "editorStyle": "file:./index.css",
  "style": "file:./style-index.css",
  "viewScript": "file:./view.js"
}

ここで指定しているパスはビルド後のファイルであることに注意してください。src/block.json に書いていても、wp-scripts build は block.json を build/ にコピーするため、実際に読まれるのは build/block.json です。つまり file:./index.js は build/index.js を指します。

複数のファイルを指定する

WordPress 6.1 以降は、各項目に配列を渡して複数ファイルを読み込めます。自作の CSS に加えて外部ライブラリの CSS も必要、といった場面で使えます。

src/block.json
{
  "style": [ "file:./style-index.css", "file:./slider.css" ],
  "viewScript": [ "file:./view.js", "my-registered-handle" ]
}

配列の中では file: と登録済みハンドル名を混ぜられます。プラグイン側で wp_register_script() したものをハンドル名で参照する、という書き方も可能です。

@wordpress/scripts のビルド結果との対応

@wordpress/scripts は、src/ の中のファイル名を見て出力先を決めます。この対応を覚えておかないと、block.json に書くパスがずれて「ファイルが見つからない」状態になります。

ソースビルド後block.json での指定
src/index.jsbuild/index.jseditorScript
src/editor.scssbuild/index.csseditorStyle
src/style.scssbuild/style-index.cssstyle
src/view.jsbuild/view.jsviewScript

ややこしいのは editor.scss が index.css になり、style.scss が style-index.css になる点です。名前が入れ替わっているように見えますが、これは index.js というエントリーポイントに紐づく CSS が index.css、style という接頭辞が付いたものがフロント用、という命名規則によるものです。

index.asset.php が依存関係を解決している

ビルドすると build/index.asset.php というファイルも一緒に生成されます。中身は、そのスクリプトが必要とする WordPress パッケージのハンドル名一覧と、ファイル内容から計算したバージョン文字列を返す PHP です。

build/index.asset.php
<?php return array(
    'dependencies' => array( 'wp-block-editor', 'wp-blocks', 'wp-element', 'wp-i18n' ),
    'version'      => 'a1b2c3d4e5f6',
);

file: でスクリプトを指定すると、WordPress は同じディレクトリにある同名の .asset.php を自動で読み、依存関係とバージョンに反映します。wp-blocks や wp-i18n を自分で列挙する必要はなく、ファイルを変更すればバージョン文字列も変わるのでキャッシュも自然に切り替わります。このファイルは消さずに、ビルド成果物ごとデプロイしてください。

プラグイン側の登録は register_block_type だけでよい

PHP 側で書くのは、block.json のあるディレクトリを register_block_type() に渡す数行だけです。アセットの登録はこの中で行われます。

webool-blocks.php
function webool_register_blocks() {
    // build ディレクトリ(block.json がコピーされている場所)を渡す
    register_block_type( __DIR__ . '/build' );
}
add_action( 'init', 'webool_register_blocks' );

ブロックが複数あって build/notice-box/、build/price-table/ のようにディレクトリを分けている場合は、それぞれのパスを register_block_type() に渡します。WordPress 6.8 以降であれば wp_register_block_types_from_metadata_collection() でまとめて登録する方法もありますが、まずは上の形で十分です。

viewScript でフロントに動きをつける

viewScript に指定した JavaScript は、そのブロックが含まれるページのフロントエンドでだけ読み込まれます。エディター側では実行されないので、編集中にアコーディオンが勝手に閉じたり、スライダーが動き出したりする心配がありません。

src/view.js
// フロントでだけ読み込まれる。ブロックのルート要素を探して動きをつける
document.addEventListener( 'DOMContentLoaded', () => {
	const boxes = document.querySelectorAll( '.wp-block-webool-notice-box' );

	boxes.forEach( ( box ) => {
		const button = box.querySelector( '.notice-box__close' );
		if ( ! button ) {
			return;
		}
		button.addEventListener( 'click', () => {
			box.hidden = true;
		} );
	} );
} );

viewScript のスクリプトは defer 付きで出力されるため、フッターでの読み込み指定を自分で気にする必要はありません。ただし挿入位置の都合で実行タイミングが前後することもあるので、DOM を触るときは上のように読み込み完了を待つか、document.currentScript に頼らない書き方にしておくと安全です。

viewScriptModule で ES モジュールとして読み込む

WordPress 6.5 以降では viewScriptModule が使えます。こちらは <script type="module"> として出力されるため、import 文をそのまま書けます。Interactivity API を使うブロックはこの項目を使います。ビルド時は wp-scripts build --experimental-modules のようにモジュール向けのビルドが必要になるので、既存のブロックを無理に移す必要はありません。

スタイルやスクリプトが反映されないとき

パスが src を指したままになっている

いちばん多いのが、file:./style.scss のようにビルド前のファイル名を書いてしまうケースです。ブラウザーは .scss を解釈できませんし、そもそも build/ にそのファイルは存在しません。build/ の中身を実際に ls で確認し、そこにあるファイル名をそのまま書くのが確実です。

フロントだけスタイルが当たらない

エディターでは正しく見えるのにフロントで崩れるときは、必要なスタイルを editorStyle に書いてしまっている可能性が高いです。editorStyle は編集画面専用なので、公開ページには一切出力されません。共通の見た目は style に移してください。

もうひとつの原因は、ブロックがページ内に存在すると WordPress が判定できていないことです。style や viewScript は本文の解析結果をもとに読み込まれるので、ショートコードや PHP のテンプレートから render_block() を直接呼んで出力しているような場合は、判定から漏れることがあります。そのときは wp_enqueue_style( 'webool-notice-box-style' ) のように、生成されたハンドル名を自分で読み込みます。ハンドル名は wp-block-{名前空間}-{ブロック名} の形(style は接尾辞なし、editorStyle は -editor 付き)で生成されます。

block.json を編集したのに変わらない

src/block.json を書き換えただけでは、build/block.json は古いままです。wp-scripts start を動かしている最中なら自動でコピーされますが、止めているなら npm run build を実行し直してください。また、ブロックの登録内容はエディターの起動時に読み込まれるため、ブラウザーのリロードも必要です。

まとめ

カスタムブロックのアセットは、block.json の項目を選ぶだけで読み込み先を制御できます。ブロックの登録コードは editorScript、共通の見た目は style、編集画面だけの調整は editorStyle、フロントの動きは viewScript。この4つを押さえれば、エディターとフロントで読み込みが混ざる問題はほぼ起きません。

パスは file: プレフィックスでビルド後のファイルを指定します。editor.scss は index.css に、style.scss は style-index.css になるという @wordpress/scripts の命名規則を覚えておくと、パスのずれで悩む時間が減ります。依存関係とバージョンは index.asset.php が肩代わりしてくれるので、PHP 側は register_block_type( __DIR__ . '/build' ) の一行で済みます。

そして style と viewScript は、ブロックが使われているページでだけ読み込まれます。サイト全体に CSS と JS を配る作りから、必要なページにだけ届ける作りへ。block.json に項目を移すだけでその恩恵が受けられるので、まだ wp_enqueue_scripts で手書きしているブロックがあれば、ぜひ移行してみてください。

参考ページ