Gutenberg
解体新書(初稿)
Ryo Utsunomiya(@ryo511)
WordCamp Tokyo 2018
2018-09-15
自己紹介
- 宇都宮 諒(うつのみや りょう)
- 株式会社 一休 宿泊事業本部
- 職種は「フロントエンドエンジニア」
- 主なお仕事
-
WordPress歴
- ユーザとして4年くらい
- 開発者として1年くらい
- Twitter: @ryo511
- 個人ブログ( https://ryo511.info/ )
Agenda
-
Gutenbergはどういう技術で成り立っているのか
- Gutenbergを拡張する(プラグインを作る)ためにはどういう技術が必要か
第1部
Gutenbergの
技術的な成り立ち
Gutenbergの成分表示
-
GutenbergはWordPressプラグイン
-
主要成分はJavaScript
- PHPもそれなりに
JavaScript
-
Webブラウザ上で動作するプログラミング言語
- JavaScriptの仕様はECMA Internationalという団体で策定されている
- この仕様をECMAScriptと呼ぶ
- 従来はES 3、ES 5のようなバージョン番号が使われていた
- 2015年のES 6以降は毎年新バージョンが出るようになったため、発表年で呼ばれるように
- 最新の仕様はES2018
ECMAScriptのブラウザ対応
-
ECMAScriptの仕様化には、ブラウザでの実装状況も考慮される
- ES2018の主要機能は、現在の主要なブラウザの最新版では動作する
- ただし、IE11はES 5で更新が止まっている
JavaScriptライブラリとnpm
-
Gutenbergでは、JavaScriptのライブラリ管理にはnpm(Node Package Manager)を使用している
- npmはJavaScriptライブラリ管理のデファクトスタンダード
- npmでは、依存しているライブラリをpackage.jsonというファイルに列挙する
- package.jsonを見ることで、Gutenbergがどのようなライブラリを使っているかわかる
Gutenbergのpackage.json
-
dependencies(動作に必要なライブラリ)と、devDependencies(開発に必要なライブラリ)に分かれる
- dependencies
- React.js
- jQuery
- その他、@wordpress 系のライブラリ群も
- devDependencies
- Babel
- webpack
- その他沢山
React.js
-
Gutenbergの中心を成すライブラリ
- Facebookが開発した、リッチなUIを開発するためのJavaScriptライブラリ
- 現在最も人気のあるJavaScriptライブラリの1つ
- npmでは2017年に5900万回ダウンロードされた
- 参考値:jQuery 4600万、Angular 1100万、Vue.js 800万
React.jsはコンポーネント指向
-
React.jsは、リッチな=複雑なUIを、効率よく開発するためのライブラリ
- Reactでは、コードを「コンポーネント」という単位で管理する
- コンポーネントは、振る舞いと見た目を併せ持つ
- Gutenbergでは、それぞれの「ブロック」が、Reactコンポーネントとして実装されている
React.jsのサンプルコード
// ES2015のclass構文
class HelloMessage extends React.Component {
render() {
return (
// JavaScriptの中にHTMLを書く(JSX)
<div>
Hello {this.props.name}
</div>
);
}
}
// #app というidを持つ要素にReactアプリケーションを描画
ReactDOM.render(
<HelloMessage name="Taylor" />,
document.getElementById("app")
);
最大の特徴は、JavaScriptの中にHTMLを書くこと
JSX
// JavaScript関数の戻り値にHTMLを書く
function Hello() {
return <div>Hello World</div>
}
// HTMLの中にJavaScriptの変数を埋め込むことができる
function Hello(name) {
return <div>Hello {name}</div>
}
// 関数呼び出しも可能
function Hello(name) {
return <div>{greeting(name)}</div>
}
-
React.jsは、JSXによって、高い表現力を実現している
- しかし、JSXはブラウザでそのまま実行できるコードではない…
Babel
-
JavaScriptトランスパイラ
- JSX => JavaScriptの変換のほか、新しいバージョンのJavaScript(ES2018等)を、古いバージョンのJavaScript(ES5)に変換することもできる
- React.jsを使った開発では、ほぼ必須のソフトウェア
- もちろん、Gutenbergでも使っている
JSXトランスパイル
// ESNext + JSX
const hw = <h1>Hello World</h1>;
// ES5(React)
var hw = React.createElement("h1", null, "Hello World");
// ES5(Gutenberg)
var hw = wp.element.createElement("h1", null, "Hello World");
- BabelはJSXをES5に変換する
- JSXのHTMLタグは、React.createElement() の呼び出しと同じ
- GutenbergはReact.createElement() をラップした独自メソッドを用意している
createElementを手書きする
// JSX
<div className="container">
<h1>Header1</h1>
<p>Paragraph</p>
</div>
// ES5
var el = wp.element.createElement;
el(
'div',
{ className: 'container' },
[
el( 'h1', null, 'Header1' ),
el( 'p', null, 'Paragraph' ),
],
);
- JSXなしのReact開発も可能
- ただし、記法が煩雑なので非推奨
Babelとセットで使う、
webpackというものがあると
聞いたんだけど… 🤔
webpack
-
webpackは、ES2015のモジュールシステムを、レガシーブラウザ(IE11等)でも動くようにするためのツール
- Babelのようなトランスパイラとセットで使うことが多い
- Gutenbergでもwebpackを使っている
モジュールシステム
-
jsファイルの外側から、ライブラリ等を読み込んで使用できるようにするための構文
- import/exportというキーワードを使う
- PHPのrequire/includeとだいたい同じ
- モダンブラウザ(Chrome, Safari, Firefox, Edge等)では動く
- IE11では動かないので、webpackを使って動作する形に変換する必要がある
ここまでのおさらい
-
GutenbergはWordPressプラグインとして実装され、
- npmを使ってライブラリを管理している
- React.jsを使ってリッチなUIを実現している
- Babelを使ってReactのJSXをブラウザで動くコードに変換している
- webpackを使ってモジュールシステムがIE11でも動くようにしている
ところで、
Babelとかwebpackとか、
絶対に覚えないとダメ? 😨
最低限必要なのはReactだけ
-
webpack + Babelのビルドの仕組み作りはそれなりに複雑で、学習コストがかかる
- しかし、開発効率のためにはJSXを使えた方がよい…
- create-guten-block等、Gutenbergの開発環境をセットアップしてくれるツールが出てきている。初めはツールの助けを借りて、徐々に自分でも設定できるようにしておけばOK
第2部
Gutenbergのプラグイン開発
Gutenbergの基本はブロック
-
記事の編集に使用する、再利用可能な部品
GutenbergのブロックAPI
-
自分で定義したブロックを登録し、Gutenberg で利用可能にできる
- 段落(paragraph)や画像(image)のようなコアブロックも、ブロックAPIを利用している
- コアブロックは packages/block-library の下にあるので、一度は覗いてみるのをおすすめ
ブロックの登録
import HelloBlock from './HelloBlock';
wp.blocks.registerBlockType( 'my-block/hello', {
title: 'Greeting',
icon: 'cart',
category: 'common',
// ブロックがもつメタデータを定義
attributes: {
// 省略
},
// ブロックの初回表示・編集時の動作を定義
edit( { attributes, setAttributes } ) {
return (
<HelloBlock
attributes={ attributes }
setAttributes={ setAttributes }
/>
);
},
// ブロックを保存する際の動作を定義
save( { attributes } ) {
// 省略
},
} );
ブロックはReactで作る
/* global React */
export default class HelloBlock extends React.Component {
render() {
const { name } = this.props.attributes;
return <div>{ name }</div>;
}
}
-
たとえば、コアの段落ブロックはParagraphBlockというReactコンポーネントとして実装されている
記事データの保存形式(1)
-
WordPressの記事データはwp_postsテーブルのpost_contentというカラムに保存される
- クラシックエディタでは、保存されるのはHTML文字列
- Gutenbergでも、保存先や保存形式は同じ
- ただし、Gutenbergの場合、メタデータをコメントに埋め込む
記事データの保存形式(2)
<!-- wp:core/heading -->
<h2>What is Gutenberg?</h2>
<!-- /wp:core/heading -->
<!-- wp:core/cover-image {"url":"http://localhost:8888/wp-content/uploads/2017/12/Screen-Shot-2017-12-06-at-23.34.27.png","id":45} -->
<section class="wp-block-cover-image has-background-dim" style="background-image:url(http://localhost:8888/wp-content/uploads/2017/12/Screen-Shot-2017-12-06-at-23.34.27.png)">
</section>
<!-- /wp:core/cover-image -->
<!-- wp:core/paragraph -->
<p>Gutenberg is a new UX of WordPress editor.</p>
<!-- /wp:core/paragraph -->
Gutenbergブロックのメタデータは
HTMLコメントの中にJSON形式で埋め込まれる
記事データの保存形式(3)
<h2>What is Gutenberg?</h2>
<section class="wp-block-cover-image has-background-dim" style="background-image:url(http://localhost:8888/wp-content/uploads/2017/12/Screen-Shot-2017-12-06-at-23.34.27.png)">
</section>
<p>Gutenberg is a new UX of WordPress editor.</p>
- 記事データとして(the_post()などで)出力されるHTMLからは、メタデータ(コメント)は取り除かれる
- 記事のレンダリングはサーバサイド(PHP)で行われる。Reactは記事のレンダリングには使わない。
ブロックのライフサイクル
-
edit() で初期状態を出力(保存されたコンテンツを編集する際は、以前の状態の復元)
- ユーザがコンテンツを編集する
- save() の結果をpost_contentに保存
Attributes API
- Gutenbergのブロックのメタデータのことをattributesと呼ぶ
- 例:段落ブロックの文字サイズ等
- ユーザがブロックに行った設定を反映するには、edit()の中でsetAttributes()メソッドを使用する
- save() の中でattributesを参照して、最終的に保存するコンテンツを決定する
- どのようなattributesを定義して、保存するか、がGutenbergのブロック開発のキモ
Gutenbergプラグインの構造
-
通常のWordPressプラグインと変わらない
- enque_block_editor_assets アクションでブロックのJSを読み込む
<?php
// index.php
/**
* Register Block JavaScript file.
*/
add_action( 'enqueue_block_editor_assets', function () {
wp_enqueue_script(
'my-block',
plugins_url( 'build/index.js', __FILE__ ),
array( 'wp-blocks', 'wp-element' )
);
} );
まとめ
-
Gutenbergは様々なJavaScriptライブラリによって成り立っている
- React.jsを作った、モダンなJavaScriptアプリケーションとして実装されている
- モダンなWebフロントエンドの技術を身につけることが、Gutenberg対応プラグイン開発の基盤になる
参考文献
-
Gutenberg Handbook
- React.js公式ドキュメント
- Babel公式ドキュメント
- webpack公式ドキュメント
【初稿】Gutenberg解体新書
By Ryo Utsunomiya
【初稿】Gutenberg解体新書
WordCamp Tokyo 2018セッションスライド初稿
- 2,277