記事の背景
2023年8月に、Gutenberg プロジェクトにおいて「Gutenberg as a framework: streamline the experience」という issue が立ち上がりました。
自分には非常に難解な内容ですが、多くの議論が交わされており、現在も進行中の issue のようです。その一方、フレームワークとして ブロックエディターを動作させるためのドキュメントの整備も進められており、今回は、このドキュメントに従って環境構築に挑戦し、現時点でどこまで/どのような事が出来るのかを確認してみようと思います。
使用技術
環境構築にあたって、今回は Bun と Vite を使用してみます。どちらも初めて使用するため、もし間違い等ありましたらぜひご指摘ください。
開発環境の初期構築
とりあえず Bun のトップページにあるコマンドを使ってインストールする
$curl -fsSL https://bun.sh/install | bash
######################################################################### 100.0%
bun was installed successfully to ~/.bun/bin/bun
Run 'bun --help' to get started
入ったっぽい
$bun --version
1.0.0
Vite テンプレートを作成。フレームワークはもちろん React。Gutenberg の各種パッケージに対して最新の型定義が全てあるか不明なので、variant
は JavaScript を選択。
s$ bun create vite block-editor-platform
✔ Select a framework: › React
✔ Select a variant: › JavaScript
Scaffolding project in /home/wildworks/projects/block-editor-platform...
Done. Now run:
cd block-editor-platform
bun install
bun run dev
こんなファイルが生成されました
$ tree
.
├── index.html
├── package.json
├── public
│ └── vite.svg
├── README.md
├── src
│ ├── App.css
│ ├── App.jsx
│ ├── assets
│ │ └── react.svg
│ ├── index.css
│ └── main.jsx
└── vite.config.js
3 directories, 10 files
ライブラリをインストールして起動してみる
$ bun install
bun install v1.0.0 (822a00c4)
+ @types/react@18.2.45
+ @types/react-dom@18.2.18
+ @vitejs/plugin-react@4.2.1
+ eslint@8.56.0
+ eslint-plugin-react@7.33.2
+ eslint-plugin-react-hooks@4.6.0
+ eslint-plugin-react-refresh@0.4.5
+ vite@5.0.10
+ react@18.2.0
+ react-dom@18.2.0
270 packages installed [13.59s]
$ bun dev
$ vite
VITE v5.0.10 ready in 315 ms
➜ Local: http://localhost:5173/
➜ Network: use --host to expose
➜ press h + enter to show help
起動しました。中央あたりのボタンをクリックすると、数字がカウントアップされる模様
Gutenberg ドキュメントの確認
ここからブロックエディターを組み込んでいくことになりますが、そのドキュメントは Gutenberg のGitHub リポジトリにあります。この README を直接見ても良いのですが、このドキュメントには Docusaurus 2 が使われているとの事なので、せっかくなのでビルドしてみます。
README に従ってコマンドを実行します (Gutenberg リポジトリはローカルにクローン済で、プロジェクトルートにいるとします)。
$ cd ./platform-docs/
$ npm install
up to date, audited 1145 packages in 19s
215 packages are looking for funding
run `npm fund` for details
26 vulnerabilities (14 moderate, 11 high, 1 critical)
To address issues that do not require attention, run:
npm audit fix
To address all issues (including breaking changes), run:
npm audit fix --force
Run `npm audit` for details.
検証時点では、broken links があるとの事で npm run build
が失敗したので、代わりに npm run start
を実行
$ npm run start
> platform-docs@0.0.1 start
> docusaurus start
(中略)
✔ Client
Compiled successfully in 3.84s
[WARNING] Docs markdown link couldn't be resolved: (/docs/reference-guides/block-api/block-attributes.md) in "/home/wildworks/projects/gutenberg/platform-docs/docs/basic-concepts/data.md" for version current
client (webpack 5.88.2) compiled successfully
ドキュメントサイトが立ち上がりました !
ドキュメントの Getting Started を見ると、まずは依存関係をインストールする必要があるとの事
$bun i -D @wordpress/block-editor @wordpress/block-library @wordpress/components
ブロックエディターの組み込み
いよいよブロックエディターの組み込みを試してみます。
まずは、アプリを CSS も適用されていないとにかくフラットな状態にしてみます。
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.jsx'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
function App() {
return (
<div>Hello World!</div>
)
}
export default App
ここに、ドキュメントに記載されている通りブロックエディターを組み込んでみます。開発環境の構成に合わせて、一部調整しています。
import { useState } from "react";
import {
BlockEditorProvider,
BlockCanvas,
} from "@wordpress/block-editor";
import { registerCoreBlocks } from "@wordpress/block-library";
import "@wordpress/components/build-style/style.css";
import "@wordpress/block-editor/build-style/style.css";
import "@wordpress/block-library/build-style/common.css";
import "@wordpress/block-library/build-style/style.css";
import "@wordpress/block-library/build-style/editor.css";
registerCoreBlocks();
function App() {
const [blocks, setBlocks] = useState([]);
return (
<BlockEditorProvider
value={blocks}
onChange={setBlocks}
onInput={setBlocks}
>
<BlockCanvas height="500px" />
</BlockEditorProvider>
);
}
export default App
以下のようなエラーがブラウザコンソールに記録され、何も表示されず。。
@wordpress_block-library.js?v=3a76d5ae:64859 Uncaught ReferenceError: process is not defined at @wordpress_block-library.js?v=3a76d5ae:64859:52
エラーが起こっている行を見てみると、確かに processs.env.IS_GUTENBERG_PLUGIN
を読み取っているっぽいですが、そもそも process
が undefined
であるのが問題
この記事によると、Vite では「process.env.HOGE
をimport.meta.env.VITE_HOGE
に書き換える」とありますが、そもそも外部ライブラリなので書き換える事が出来ない。。
Gutenberg プロジェクトでも似た問題が報告されていた
https://github.com/WordPress/gutenberg/issues/48949
issue のこのコメントによると、@rollup.plugin-replace
を使用して置き換える事でも解決出来るらしいですが、Vite のドキュメントによると、define
プロパティでグローバル定数の置換 ? を定義出来るらしいので試してみる
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
// これを追加
define: {
'process.env': {}
},
})
ブロックエディターが動いた !
WordPress の中の場合の見た目・動作と違う部分は多くありますが、基本的な機能は動作するようです。
せっかくなので、ブロックサイドバーも追加してみます。Gutenberg で公開されている Storybook にはブロックエディターもあり、サイドバー付きのストーリーも存在します。
該当ファイルを見てみると、BlockInspector
コンポーネントを使用すればよいようです。エディターキャンバス (BlockCanvas
コンポーネント) の高さも 100%
に変更しておきます。
import { useState } from "react";
import {
BlockEditorProvider,
BlockCanvas,
BlockInspector,
} from "@wordpress/block-editor";
import { registerCoreBlocks } from "@wordpress/block-library";
import "@wordpress/components/build-style/style.css";
import "@wordpress/block-editor/build-style/style.css";
import "@wordpress/block-library/build-style/common.css";
import "@wordpress/block-library/build-style/style.css";
import "@wordpress/block-library/build-style/editor.css";
import './App.scss';
registerCoreBlocks();
function App() {
const [blocks, setBlocks] = useState([]);
return (
<div className="playground">
<BlockEditorProvider
value={blocks}
onChange={setBlocks}
onInput={setBlocks}
>
<div className="playground__sidebar">
<BlockInspector />
</div>
<div className="playground__content">
<BlockCanvas height="100%" />
</div>
</BlockEditorProvider>
</div>
);
}
export default App
さらに、エディターキャンバスとブロックサイドバーをレイアウトするために、Storybook のスタイルを参考に追加してみます。
このスタイルは Sass で記述されているので、sass
をインストールする必要があります。さらに、Gutenberg の @wordpress/base-styles
パッケージをインポートしているので、これもインストールしておきます。
$ bun i -D sass @wordpress/base-styles
最低限のスタイルとして、以下のように記述しました。CSS 変数は、@wordpres/base-styles
の variables に定義されているものを使用しています。
@import "@wordpress/base-styles/colors";
@import "@wordpress/base-styles/variables";
@import "@wordpress/base-styles/mixins";
@import "@wordpress/base-styles/breakpoints";
@import "@wordpress/base-styles/animations";
@import "@wordpress/base-styles/z-index";
.playground {
iframe {
width: 100%;
}
}
.playground__content {
position: fixed;
top: 0;
right: $sidebar-width;
bottom: 0;
left: 0;
padding: 0 $grid-unit-20;
}
.playground__sidebar {
position: fixed;
top: 0;
right: 0;
bottom: 0;
width: $sidebar-width;
border-left: $border-width solid $gray-300;
height: auto;
overflow: auto;
}
サイドバーにはタイポグラフィパネル (フォントサイズのみ) と Advanced パネルしかありませんが、それっぽくなりました !
State について
ここで、useState
を介してコントロールされている blocks
にどのような情報が入っているかを確認してみます。
WordPress のブロックエディター上でブロックの Edit
コンポーネントが持つものと似ているようですが、RichText データの持ち方 (attributes.content
等) が異なるようです。
まとめ
過去にも、WordPress 外でブロックエディターを構築する事を試みた事はありますが、情報も少なく挫折してしまいました。今回、つまづきポイントは多少ありましたが、かなりシンプルな方法で構築出来ることが分かりました。
「Gutenberg as a framework」に関する取り組みはこれからも続いていくと思うので、ますます楽しみです !