LoginSignup
6
5

Gutenberg as a framework: WordPress 外でブロックエディターを動かしてみる

Last updated at Posted at 2023-12-16

この記事は、「CMS Advent Calendar 2023」の16日目の記事で、「WordPress 外でブロックエディターを動かしてみる」ことに挑戦してみた経緯を記載したものです。

記事の背景

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

起動しました。中央あたりのボタンをクリックすると、数字がカウントアップされる模様

開発環境の初期構築_1.png

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

ドキュメントサイトが立ち上がりました !

Gutenberg ドキュメントの確認_1.png

ドキュメントの Getting Started を見ると、まずは依存関係をインストールする必要があるとの事

$bun i -D @wordpress/block-editor @wordpress/block-library @wordpress/components

ブロックエディターの組み込み

いよいよブロックエディターの組み込みを試してみます。

まずは、アプリを CSS も適用されていないとにかくフラットな状態にしてみます。

src/main.jsx
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>,
)
src/App.jsx
function App() {
  return (
    <div>Hello World!</div>
  )
}

export default App

ここに、ドキュメントに記載されている通りブロックエディターを組み込んでみます。開発環境の構成に合わせて、一部調整しています。

src/App.jsx
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 を読み取っているっぽいですが、そもそも processundefined であるのが問題

ブロックエディターの組み込み_1.png

この記事によると、Vite では「process.env.HOGEimport.meta.env.VITE_HOGEに書き換える」とありますが、そもそも外部ライブラリなので書き換える事が出来ない。。

Gutenberg プロジェクトでも似た問題が報告されていた

issue のこのコメントによると、@rollup.plugin-replace を使用して置き換える事でも解決出来るらしいですが、Vite のドキュメントによると、define プロパティでグローバル定数の置換 ? を定義出来るらしいので試してみる

vite.config.js
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [react()],
  // これを追加
  define: {
    'process.env': {}
  },
})

ブロックエディターが動いた !

ブロックエディターの組み込み_2.png

WordPress の中の場合の見た目・動作と違う部分は多くありますが、基本的な機能は動作するようです。

せっかくなので、ブロックサイドバーも追加してみます。Gutenberg で公開されている Storybook にはブロックエディターもあり、サイドバー付きのストーリーも存在します。

該当ファイルを見てみると、BlockInspector コンポーネントを使用すればよいようです。エディターキャンバス (BlockCanvas コンポーネント) の高さも 100% に変更しておきます。

src/App.jsx
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-stylesvariables に定義されているものを使用しています。

src/App.scss
@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 パネルしかありませんが、それっぽくなりました !

ブロックエディターの組み込み_3.png

State について

ここで、useState を介してコントロールされている blocks にどのような情報が入っているかを確認してみます。

WordPress のブロックエディター上でブロックの Edit コンポーネントが持つものと似ているようですが、RichText データの持ち方 (attributes.content 等) が異なるようです。

State について.png

まとめ

過去にも、WordPress 外でブロックエディターを構築する事を試みた事はありますが、情報も少なく挫折してしまいました。今回、つまづきポイントは多少ありましたが、かなりシンプルな方法で構築出来ることが分かりました。

「Gutenberg as a framework」に関する取り組みはこれからも続いていくと思うので、ますます楽しみです !

6
5
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
6
5