25
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WordPressAdvent Calendar 2017

Day 9

[WordPress] はじめてのGutenberg Custom Block Type

Last updated at Posted at 2017-12-09

前回の記事で、Gutenbergの開発環境を作り、中心的な概念であるブロック(Block)の仕組みを解説しました。

今回は、独自のブロックを作成する方法を解説します。

なお、本記事のサンプルコードは下記リポジトリで公開しています。
https://github.com/ryo-utsunomiya/my-gutenberg-ext

開発環境セットアップ

手元に手頃なWordPress環境がある方は、これにGutenbergを入れ、さらに適当なプラグインを追加してください。

本記事では、Gutenbergプロジェクトの公式開発環境を利用する方式でセットアップします。

まず、以下の2つのディレクトリを用意します。

my-gutenberg-extはWordPressプラグインとして認識させる必要があるので、my-gutenberg-ext.phpというファイルを配置します。中身は適当で良いです。

<?php
/*
Plugin Name: my-gutenberg-ext
Plugin URI: https://github.com/ryo-utsunomiya
Description: Sample implementation of Gutenberg customize.
Version: 0.1
Author: Ryo Utsunomiya
Author URI: https://ryo511.info
License: GPLv2
*/

2018/2/19追記: Gutenberg 2.2で開発環境セットアップが変わったので、↓の設定だと動かないです。。。

次に、Docker設定を一部変更します。docker/docker-compose.ymlを以下のように変更してください。
ここでは、my-gutenberg-extディレクトリをDockerコンテナ内のWordPressのプラグインとして追加するよう設定しています。

    volumes:
      - ../:/var/www/html/wp-content/plugins/gutenberg
+      - ../../my-gutenberg-ext:/var/www/html/wp-content/plugins/my-gutenberg-ext

↑だけだとボリュームは追加されないので、bin/setup-local-env.shにも変更を加えます。

# Activate Gutenberg
docker run -it --rm --volumes-from wordpress-dev --network container:wordpress-dev wordpress:cli plugin activate gutenberg

+# Activate my-gutenberg-ext
+docker run -it --rm --volumes-from wordpress-dev --network container:wordpress-dev wordpress:cli plugin activate my-gutenberg-ext

この状態でbin/setup-local-env.shを実行すると、my-gutenberg-extディレクトリがDockerにマウントされ、開発環境からプラグインが見えるようになります。

Screen Shot 2017-12-09 at 19.32.15.png

次に、JavaScriptのJSXを使えるようにするため、ビルド環境を作ります。GutenbergでJSXの使用は必須ではないので、ここは飛ばしても構いません。

はじめに、my-gutenberg-extディレクトリの中で、npm initしてpackage.jsonを作成します。次に、以下のコマンドを実行しましょう。

npm i babel-core babel-loader babel-plugin-transform-react-jsx babel-preset-env cross-env webpack

これで、ESNextとJSXのビルドに必要なライブラリが一式入ります。

次はwebpack.config.jsを以下の内容で作成しましょう。

module.exports = {
    entry: './block.js',
    output: {
        path: __dirname,
        filename: 'block.build.js',
    },
    module: {
        loaders: [
            {
                test: /.js$/,
                loader: 'babel-loader',
                exclude: /node_modules/,
            },
        ],
    },
};

ここでは、block.jsというファイルを起点にしてビルドを行い、ビルド結果はblock.build.jsに書き出す、という設定を行っています。

次に、Babelの設定ファイル(.babelrc)を作成します。

{
  "presets": [
    [
      "env",
      {
        "modules": false
      }
    ]
  ],
  "plugins": [
    [
      "transform-react-jsx",
      {
        "pragma": "wp.element.createElement"
      }
    ]
  ]
}

ここでのポイントは、transform-react-jsxプラグインのpragmaにwp.element.createElementを指定していることです。こうすると、JSXのコンパイル時にGutenbergのcreateElementメソッドが使用されるようになります。

最後に、package.jsonにスクリプトを追加します。

  "scripts": {
    "build": "cross-env BABEL_ENV=default NODE_ENV=production webpack"
  },

これで、npm run buildコマンドでビルドが行われるようになります。
ためしに、以下のコードをビルドしてみましょう。

block.js
const hw = <h1>Hello World</h1>;

ビルド後のjsファイルには以下のようなコードが含まれるはずです。

block.build.js
var hw = wp.element.createElement(
  "h1",
  null,
  "Hello World"
);

これでJSXのビルド環境は完成です。

BlockとBlock Type

Gutenbergにはブロック(Block)の他に、ブロック型(Block Type)という概念があります。Block Typeを元にBlockが作成されるイメージです。Block Typeの定訳があるかは不明ですが、個人的には「ブロック型」と訳すのが良いのでは、と思ってます。

独自のブロック型を登録すると、Gutenbergエディタでそのブロックを利用できるようになります。

ブロック型を登録するには、(1) registerBlockType関数を使ってブロック型を定義するJavaScriptを書く (2) (1)のスクリプトをenqueするPHPコードを書く の2ステップが必要です。

まずは(1)からいきましょう。以下のように記述した上で、npm run buildでビルドを行います。

block.js
const { registerBlockType } = wp.blocks;
const blockStyle = { backgroundColor: '#900', color: '#fff', padding: '20px' };

registerBlockType('my-gutenberg-ext/hello-world', {
    title: 'Hello World',
    icon: 'universal-access-alt',
    category: 'layout',
    edit: () => <p style={ blockStyle }>Hello editor.</p>,
    save: () => <p style={ blockStyle }>Hello saved content.</p>,
});

Gutenbergはwpというグローバル変数を通して様々な機能を利用可能にしています。wp.blocksregisterBlockType関数があるので、これを利用しましょう。

registerBlockType関数の第1引数はブロックの名前です。'namespace/block-name'というフォーマットになっています。第2引数はブロック型の定義です。titleとcategoryが必須で、他にも重要なオプションがいくつかあります。

titleはGutenbergのUI上での表示名、categoryはUI上の分類です。edit関数はエディタの編集時の動作、save関数には記事を保存する際の動作を記述します。

ブロック型の定義はできたので、次にblock.build.jsをenqueしましょう。
以下のコードを追加します。

my-gutenberg-ext.php
function my_gutenberg_ext_enqueue_block_editor_assets()
{
    wp_enqueue_script(
        'my-gutenberg-ext',
        plugins_url('block.build.js', __FILE__),
        array('wp-blocks', 'wp-element')
    );
}

add_action('enqueue_block_editor_assets', 'my_gutenberg_ext_enqueue_block_editor_assets');

この状態でエディタを開くと、以下のようにLayout Blocksの中に先ほど定義したブロック「Hello World」が表示されます。

Screen Shot 2017-12-09 at 20.42.41.png

このブロックを追加すると、以下のようにedit関数の中で定義した文字列が表示されます。

Screen Shot 2017-12-09 at 20.43.46.png

この状態で記事を保存して公開すると、以下のようになります。

Screen Shot 2017-12-09 at 20.45.01.png

編集中の画面で出ていた文言(Hello editor.)ではない点に注目してください。最終的に記事として公開されるデータは、save関数によって決まります。今回は、save関数で「Hello saved content.」という文字列を静的に指定していました。

post_contentの中も見てみましょう。gutenbergのDockerを使っているなら、以下のコマンドでMySQLにログインできます。

docker exec -it docker_mysql_1 mysql -u root -pexample wordpress

最新記事のpost_contentがほしいので以下のクエリを実行します。

select post_content from wp_posts order by id desc limit 1;

post_contentは以下のようになっていました。

<!-- wp:my-gutenberg-ext/hello-world -->
<p style="background-color:#900;color:#fff;padding:20px" class="wp-block-my-gutenberg-ext-hello-world">Hello saved content.</p>
<!-- /wp:my-gutenberg-ext/hello-world -->

このように、GutenbergのCustom Block Typeは、通常のWordPressプラグインと同様の枠組みで開発を進めることができます。

本記事ではセットアップに多くの分量を割いてしまったため、本格的なCustom Block Typeの作り方については別の記事に書こうと思います。

25
23
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?