WordPressの新しいエディタGutenbergは紆余曲折を経てReactでの開発を続けており、2018年5月ぐらいのリリースを目指しているようだ。新しいAPIも整備されつつあり、カスタムフィールド製造業界を震撼させたメタボックスも新しいAPIが整備されつつある。
さて、いずれにせよ、投稿編集画面に新しい時代が訪れることは間違いないので、それをどのように作っているのかについて知っておくのは悪いことではない。
Reactに関する前提知識
今回の記事ではあまり詳細に立ち入らないが、Reactは昨今のJavascript開発を牽引するライブラリであり、2010年ごろのJavascript開発とは圧倒的に違っている。圧倒的に変わった点として、次のようなものがある。
- npmを使ったパッケージ管理。
npm install
というコマンドをなんでかよくわからないまま打たされている人も多いだろう。基本的には npm にホスティングされているライブラリを管理するコマンドだ。WordPressプラグインの公式リポジトリからプラグインをダウンロードするようなものだと思ってもらっていい。 - Javascriptのトランスパイル。PHPはスクリプト言語なので実行時にソースコードを読み取るが、C言語やJavaはコンパイルを行って、実行形式のバイナリを作成する。最近のJavascriptは言語仕様の変化(ES2015, JSX)、実行環境の多様化(ブラウザ、NodeJSによるサーバサイド)などに対応するため、元のファイルを変換する処理を行うことが増えている。
決定的に異なるのは上記二点である。言語自体の新しい機能(アロー関数、Promise, Async/Await, JSXほか)もあるが、特に触れない。
そして重要なのは「これまでのWordPressはこうしたモダンJS開発の手法を取り入れていなかった」という点である。zipファイルをぽんとアップロードすればレンタルサーバーでも動くので、インストール時になにかコマンドを打ったりする必要もない。コアが利用するライブラリも、wp-includes/js
フォルダ以下に同梱される形だった。
Gurenbergのnpm構成
さて、前述した通り、GutenbergはReactを利用しているため、上記のテクノロジーを取り入れている。ためしにGutenbergのリポジトリでnpmの設定ファイルである package.json を見てみると……
- Reduxを採用しているようだ。となると、このReduxの概念を理解せずに拡張機能を作ることは難しそうである。
- トランスパイルは webpack + babel で行なっている。
興味深いのは、依存するライブラリとして以下の指定があること。
{ "@wordpress/a11y": "0.1.0-beta.1", "@wordpress/hooks": "1.0.1", "@wordpress/url": "0.1.0-beta.1"} }
これらは実際にnpmjs.comにホスティングされており、WordPressの get_query_args
をJSで再実装したものや、アクセシビリティ関連のものがまとまっている。これまで、WordPressではコアのソースを自前のSVNにホストするということにこだわってきたと思うのだが、今後は分散管理になるのだろうか。
Githubにドキュメントがまとまっている
さて、最近Gutenbergのことを心配する人が多いので、Gutenbergについて説明するプロジェクトページが用意されたのだが、実はGithubの各ディレクトリにはreadmeが整理されており、「これはなんなのか」「このコンポーネントはどうなっているのか」といったことについての説明がある。
これらのドキュメントは非常によくできているので、見てみるとよいだろう。
依存関係は名前空間で解決
さて、最近のJavascriptでは依存するライブラリを指定する機能がある。
// NodeJSのrequireで、uniqライブラリを読み込み var unique = require('uniq'); var data = [1,2,3,3,3]; console.log(unique(data)); // -> [1,2,3] // ES6のインポート文 import {unique} from "uniq"; var data = [1,2,3,3,3]; console.log(unique(data)); // -> [1,2,3] // 使われる側 export function unique(data){ // ここで一意にする return data; }
多くの場合、webpackやBrowserifyによるトランスパイルの過程で外部に影響を与えない形で読み込まれ、パッケージングされる。
では、流行りのSPA(シングルページアプリケーション)ではなく、WordPressのように「プラグイン自体があったりなかったりする」「利用するかしないかはページごとにPHPの側で決める」という場合、どんな風に実装しているのだろうか。
これはメディアライブラリと同じく、wp名前空間以下に展開することで利用される。したがって、import文を書いたりするのではなく、wp_enqueue_script
で依存関係を指定し、参照する形になりそうだ。ためしに、新しいカスタムブロックを追加する機能を見てみると……
( function( blocks, element ) { var el = element.createElement, source = blocks.source; blocks.registerBlockType( 'myplugin/random-image', { // ここに設定 } ); })(window.wp.blocks, window.wp.element)
となっており、wp以下の変数を参照することでGutenbergのAPIにアクセスしている。もちろん、モダンなES2015以上やJSXで書きたい人にはそのためのサンプルが用意されている。
となると、あとは「プラグイン同士がバッティングする可能性は?」「プラグインやテーマが特定のライブラリを読み込んでいる場合、それは二重読み込みにならないの?」という疑問が湧いてくるが、これはいまのところ解決する方法は提示されていない。
まとめ
以上、概観ではあるが、Gutenbergがどのように動いているのかについて説明した。WordPressプロジェクトのうち、Gutenbergはもっともモダンなテクノロジーを採用しているものの一つなので、「中身どうなってんだろ」と見てみることは、今後のWordPress開発の行方を占う意味でも役に立つのではないだろうか。
なお、現在Capital Pでは Vue.JS と React によるWordPress開発がどんなものなのかをお見せしようとおもっているので、お楽しみに。
“GutenbergはReactをどのように利用しているか”への5件の反応
Gutenberg の全体像を浮かび上がらせる良い記事でした。特に最初に読者に説明する部分:
>> 2010年ごろのJavascript開発とは圧倒的に違っている。圧倒的に変わった点として、次のようなものがある。
>> npmを使ったパッケージ管理。
>> Javascriptのトランスパイル。
ここらの”流れ”が曖昧だったので、こうしてバシッとまとめていただけると助かります。
最近、仕方なく JavaScript に手を出した人間としては、特に。続編も期待しています。
コメントありがとうございます。続編にご期待ください!
> 「プラグイン同士がバッティングする可能性は?」
> 「プラグインやテーマが特定のライブラリを読み込んでいる場合、それは二重読み込みにならないの?」
– webpackを使っている
– グローバル(windowオブジェクト)に変数やオブジェクトを露出していない
という条件を満たしている限り、自分のプラグインが読み込んだライブラリが別のプラグインに影響を及ぼすことはありません。
また、他のプラグインがグローバルに定義した変数も、ローカル変数でシャドウされるため、外部から影響を受けることはありません。
グローバル汚染の問題が発生しそうなのは、babel-polyfill等のpolyfill系くらいかなと思います。
問題は二重読み込みですね。同じライブラリを複数のプラグインが読み込んだ結果、JavaScriptの読み込み量が増えてしまう可能性があります。
webpackを使ってグローバルを汚染しないのがお作法である、という流れになっていくといいなーと思ってます。
そうですね。二重読み込みはありそうですね。最悪の場合、reactのソースが20回ぐらい読み込まれる可能性がありそう。
ブラウザサイドでのimportモジュール実装が待たれますね(なんかそんなの開発するってニュースありましたよね)
Reactに関しては、wp.elementからReactのラッパー(APIそのまんまで、処理もほぼ丸投げ)にアクセスできます。
https://github.com/WordPress/gutenberg/tree/master/element
さらに、React関係とmoment, TinyMCE, jQueryはグローバルにexportされてるので、プラグインの側で読み込む必要はなかったりします。
https://github.com/WordPress/gutenberg/blob/master/webpack.config.js#L62-L68
lodashも使えるようになってて、babel-runtime-transformも入ってるので、ReactでUI作るときに最低限必要なものは全部Gutenbergがグローバルに展開してくれているみたいです。
多重読み込み問題が生じそうなのは、BootstrapとかのUIライブラリあたりかなーと思います。