Gutenbergのブロックを作る

目次

  1. ブロック作成の概説
    1. 必要知識とスキル
    2. 作例ブロック
  2. 開発環境の用意
    1. ビルドしてみる
  3. ブロック本体 index.js の調整
  4. InnerBlockのjsファイルを作成・登録
    1. InnerBlock用 jsファイルの作成
    2. InnerBlockを使えるようにする
  5. InnerBlockの実装
    1. edit メソッドにコンポーネントを登録
    2. attributes を設定
    3. HTMLでの保存をSaveメソッドに実装
  6. index.js の edit/save メソッド
  7. スタイルの調整
  8. 完成

1. ブロック作成の概説

ブロックの作成には、WordPress用のnpmパッケージである@wordpress/create-blockを利用します。

Create Block は公式でサポートされるブロック作成方法です。WordPress プラグインを使用してブロックを登録します。Create Block はモダンなビルド設定を提供します。構成は必要ありません。PHP、JS、CSS コード、その他、プロジェクトの開始に必要なすべてのファイルを生成します。

@wordpress/create-block – Japanese Team — WordPress.org

npx コマンドを実行すると、プラグインのPHPファイル、ブロック用jsファイルの雛形、scssファイルなど、Gutenbergブロック用のファイルと、ビルド環境が一式用意されます。jsはECMAScript2015( ES6 / ESNext )で書いていきます。

1.1 必要知識とスキル

ECMAScript2015 と JSX で書いて Babel でビルドしますが、ビルド環境は公式スクリプトが自動で構築してくれます。npm runができれば大体、大丈夫でしょう。JavaScript と JSX は基本的な構文や仕組みが分かっていれば問題ないかと思います。npm も package.json が読めてnpmコマンドが使えれば十分でしょう。

他には、プラグインのPHPでブロック用js/CSSを読み込ませますので、WordPressにおけるスクリプトのエンキュー方法など、確認しておくといいかと思います。 wp_register_script() | WordPress Developer Resources

ローカルでのWordPress実行環境は今回 wp-env を利用しました。ローカル実行環境は各自でご用意下さい。

1.2 作例ブロック

このようなフレームワークに関する定義リストのブロックを作ってみたいと思います。イメージとしてはACFの繰り返しフィールドに近いものです。

左図がGutenbergエディタでの表示と入力のモックアップで、右が表示のモックです。

gutenberg-block
block-page-view

フレームワーク名をdt要素、登場年、言語、説明をそれぞれ3つのdd要素とします。このdt×1・dd×3を一組として、一つの定義リスト(dl要素)内に複数のフレームワークの説明を入力し、表示します。

InnerBlockとGutenbergコンポーネントを組み合わせて作っていきます。

2. 開発環境の用意

適当なフォルダで、npx @wordpress/create-block で対話モードとして実行し、スラッグと名前空間、ブロックのタイトルを指定しました。各項目で特に指定がない場合は、何も入力せずenterでデフォルト値が使われます。「The short description for your block」やライセンス項目などは今回、特に指定していません。

下記のように、最低限スラッグだけ指定すればいいのですが、ブロックの識別子がcreate-block/となってしまう上に、後から識別子を変更するのは結構手間がかかるため、最初に指定しました。

npx @wordpress/create-block framework-dl-block

セットアップが完了すると、このように表示されます。

npxを実行したフォルダ内に、framework-dl-blockというスラッグ名のフォルダが生成され、フォルダ内にはプラグインとして使えるようにファイル一式が入っています。

生成されるファイルは下記の通りです。
editorconfig や gitignore も揃っているので、このままgit init / git commit -am "initial commit"してGitでのトラッキングを始められます。

.editorconfig
.gitignore
block.json
framework-dl-block.php
package-lock.json
package.json
readme.txt
build
|       index.asset.php
|       index.css
|       index.js
|       style-index.css
|               
src
|       edit.js
|       editor.scss
|       index.js
|       save.js
|       style.scss
|       
node_modules

ビルドコマンドを叩くと、src 内の jsファイルが babel によってビルドされてbuid フォルダに書き出されます。build/index.js ファイルを framework-dl-block.php 内のwp_register_script()関数がエンキューすることで、Gutenberg内でオリジナルのブロックが使えるようになります。

ビルドしてみる

@wordpress/eslint-pluginとしてeslintもインストールされていますので、必要なら.eslintrcをプロジェクトルートに配置します。

一度ビルドしてみます。

npm run build

srcのjs、scssがビルドされてbuildフォルダに出力されます。

セットアップ完了後に表示される、最初のコマンドnpm startを試します。

npm start

こちらはファイル監視をして、変更が保存されると自動でビルドします。eslintで文法チェックもされているので、jsの文法が間違っているとエラーメッセージが出力され、ビルドは行われません。

「return文が関数の外側である」という構文エラー

終了する時は、ctrl-cです。

コーディングスタイルに準拠するよう自動整形も利用できます。

npm run format:js
Gutenbergのコーディングスタイルに合わせるよう自動整形してくれる

3. ブロック本体 index.js の調整

index.jsではregisterBlockType関数に、ブロックの識別子とオブジェクトが渡されています。オブジェクト内は、各種設定・editメソッド・saveメソッドなど、Gutenbergのブロックとして必要な機能や設定が記述されています。edit/saveでのHTML出力はJSXで書かれています。
参照: ブロックの登録 – WordPress.org / JSX の導入 – React

npx @wordpress/create-blockで生成されたindex.jsは、そのままだと今回は使いにくいので調整します。

コメントは全削除。プロパティやコンポーネントの説明と参照URLが書いてありますが、コードの流れが追いにくくなるため削除します。説明とURLは目を通しておいて下さい。
edit.js/save.js も削除して import 文も削除。分割するほどの行数ではなく、InnerBlock の js にも edit / save のメソッドを実装するため、ファイル構成が冗長になってしまいますので、今回は削除。
多言語対応の __関数のインポートも削ってしまってもいいのですが、今回は残してます。

index.jsは一旦、このようになります。

import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import './style.scss';

registerBlockType( 'framework-dl/framework-dl-block', {
	title: __( 'Framework description list', 'framework-dl-block' ),
	description: __(
		'Example block written with ESNext standard and JSX support – build step required.',
		'framework-dl-block'
	),
	category: 'widgets',
	icon: 'smiley',
	supports: {
		// Removes support for an HTML mode.
		html: false,
	},
	edit: ( { className } ) => {
		return (
			<p className={ className }>
				{ __(
					'Framework description list',
					'framework-dl-block'
				) }
			</p>
		);
	},
	save: () => {
		return null;
	},
} );

この状態で、ビルドを通せば最低限のブロックとして動作します。

4. InnerBlockのjsを作成、登録

4.1 InnerBlock用 jsファイルの作成

InnerBlockとして、もう一つ、ブロックのjsファイルを作ります。

src/framework-dd-block.js

import { registerBlockType } from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
import './style.scss';

registerBlockType( 'framework-dl/description-block', {
    title: __( 'Framework description ', 'framework-dl-block' ),
    description: __( 'Framework descriptions block', 'framework-dl-block' ),
    category: 'widgets',
    parent: [ 'framework-dl/framework-dl-block' ],
    supports: {
        // Removes support for an HTML mode.
        html: false,
    },
    edit: ( { className } ) => {
        return (
            <p className={ className }>
                { __(
                    'Framework description block, this is inner block!',
                    'framework-dl-block'
                ) }
            </p>
        );
    },
    save: () => {
        return null;
    },
} );

index.jsファイルをコピーして、framework-dd-block.js にリネームして中身を書き換えました。
変更点は主に二つ。ブロック名と parent プロパティです。

registerBlockType( 'framework-dl/description-block', {

index.jsで登録するdlブロックと被らないよう、第1引数であるブロックの一意識別子を変えておきます。index.jsにてInnerBlockとして許可するブロックを指定する際に、この識別子を利用します。ファイル名と識別子は一致していなくても構いません。

また、下記のように「親」ブロックを指定することで、ページ内に自由に挿入できなくなります。InnerBlockとしてのみ使用するので、今回は「親」ブロックを設定して、framework-dl-block 以外では description-block を使えなくします。

parent: [ 'framework-dl/framework-dl-block' ],

この時点での、srcフォルダ内のファイルは下記の通りです。

src
        framework-dd-block.js
        index.js
        style.scss

4.2 InnerBlockを使えるようにする

先に作ったframework-dd-block.jsをInnerBlockとして使えるように、index.jsのedit/saveメソッドを書き換えます。
参照:ネストしたブロック: InnerBlocks の使用 – WordPress.org

src/index.js – import 文

import { registerBlockType } from '@wordpress/blocks';
import { InnerBlocks } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
import './style.scss';
import './framework-dd-block.js';

InnerBlocksと、先に作った インナーブロック用jsファイルをインポートします。framework-dd-block.jsのregisterBlockType()が実行されればいいので、変数に代入しません。そもそもframework-dd-block.jsにはexport宣言がないので、何も代入できません。

src/index.js – editメソッド

edit: ( { className } ) => {
    return (
        <dl className={ className }>
            <InnerBlocks
                allowedBlocks={ [ 'framework-dl/description-block' ] }
            />
        </dl>
    );
},

<InnerBlocks>タグのプロパティで、許可するブロックを指定します。allowedBlocksには framework-dd-block.js で登録したブロックの識別子を入れます。一種類しか許可しない場合でも、配列でないと allowedBlocksプロパティに渡せないので配列に入れて代入します。

saveメソッドも、InnerBlocksの内容を保存するよう実装します。

src/index.js – saveメソッド

save: () => {
    return <InnerBlocks.Content />;
},

この時点で、Gutenbergエディタでは「Framework description list」ブロック内に、 「Framework description block, this is inner block! 」というテキストのブロックを複数、挿入できるようになっているはずです。

Gutenbergのエディターモードを切り替えてコードエディターモードにすると、ブロックの開始と終了を表すHTMLコメントのみが保存されていると思います。

<!-- wp:framework-dl/framework-dl-block -->
<!-- wp:framework-dl/description-block /-->

<!-- wp:framework-dl/description-block /-->

<!-- wp:framework-dl/description-block /-->
<!-- /wp:framework-dl/framework-dl-block -->

5. InnerBlockの実装

5.1 edit メソッドにコンポーネントを登録

Gutenbergエディタでブロック内に表示するフォームは、Gutenbergのコンポーネントを使って実装していきます。入力フォームは下図のようにControlコンポーネントを利用します。
参照: Component Reference | Block Editor Handbook | WordPress Developer Resources

使うコンポーネントは、

framework-dd-block.jsにて@wordpress/componentsモジュールから上記コンポーネントをインポートするよう宣言を追記しておきます。

framework-dd-block.js

import {
	Flex,
	TextControl,
	__experimentalNumberControl as NumberControl,
	SelectControl,
	TextareaControl,
} from '@wordpress/components';

登場年を入力する NumberControl は WordPress5.5のGutenbergでは実験的な実装となっているため、__experimentalNumberControlと長いエクスポート名になっています。NumberControl変数として扱えるようにエイリアスを使ってインポートします。

Flex コンポーネントは、タグで囲うだけでフレックスボックスにしてくれます。エディターでのレイアウトを組むのに便利なので、合わせてインポートしています。(editor-style.cssでフレックスボックスを指定することもできます)

続いてframework-dd-block.jsのeditメソッドにJSXでコンポーネントを記述します。

edit: ( { attributes, setAttributes } ) => {
	const { name, since, language, description } = attributes;
	return (
		<>
		<TextControl
			placeholder="Framework name"
			value={ name }
			onChange={ ( value ) => setAttributes( { name: value } ) }
		/>
		<Flex>
			<NumberControl
				label="登場年"
				shiftStep={ 1 }
				value={ since }
				onChange={ ( value ) =>
						setAttributes( { since: value } )
				}
			/>
			<SelectControl
				label="言語"
				options={ [
					{ label: 'PHP', value: 'PHP' },
					{ label: 'JavaScript', value: 'JavaScript' },
					{ label: 'Ruby', value: 'Ruby' },
					{ label: 'Erlang', value: 'Erlang' },
					] }
				value={ language }
				onChange={ ( value ) =>
						setAttributes( { language: value } )
				}
			/>
		</Flex>
		<TextareaControl
			placeholder="概要"
			value={ description }
			onChange={ ( value ) =>
				setAttributes( { description: value } )
				}
		/>
		</>
	);
},

attributessetAttributes はブロックへの入力内容を保持するために必要なオブジェクト、関数です。editメソッド内で利用するため、引数として渡しておきます。グローバル変数のような感じで、特に宣言なく利用できます。attributesについて詳しくは次節で説明します。

HTML要素に規定されている属性に対しても、placeholder="概要"のようにプロパティを設定できます。

valueに代入した内容が、各input要素の内容としてGutenbergエディタで表示されます。

onChangeには変更を検知した際の動作を書きます。今回はvalueattributesプロパティに代入しています。

余談:setAttributesの他にも、特に宣言なくregisterBlockType関数で利用できる変数がいくつかありますが、公式ハンドブックにも解説がない場合があります。気づいたらイシューを立ててみたり、ドキュメントを書いてみるといいでしょう。
Project Overview | Block Editor Handbook | WordPress Developer Resources
gutenberg/docs at master · WordPress/gutenberg · GitHub

5.2 attributesを設定

ブロック内で入力した内容はattributesプロパティを利用して保存、読み出しを行います。

attributes プロパティはすべての利用可能な属性と対応する値を表します。属性はブロックタイプ登録の際に attributes プロパティで記述されます。属性ソースを指定する方法については属性のドキュメントを参照してください。

edit と save – Japanese Team — WordPress.org

registerBlockType関数の第2引数のオブジェクトにattributesプロパティを追記します。attributesのプロパティ(=属性)には、保持したい値についての設定を記述していきます。

Framework dl blockでは、下表のように4種類の属性を保持します。

入力内容使用コンポーネント保存先
フレームワーク名TextControlattributes.name
登場年NumberControlattributes.since
言語SelectControlattributes.language
概要TextareaControlattributes.description

完成形ではHTMLから読み出してattributesにセットするため、年を表すsince属性もintegerでなく、stringとします。

parent: [ 'framework-dl/framework-dl-block' ],
supports: {
	// Removes support for an HTML mode.
	html: false,
},

attributes: {
	name: {
		type: 'string',
	},
	since: {
		type: 'string',
		default: 2010,
	},
	language: {
		type: 'string',
	},
	description: {
		type: 'string',
	},
},

edit: ( { attributes, setAttributes } ) => {

attributesで属性を設定したので、onChangesetAttributesを実行すると、入力内容がattributesに反映されます。

onChangeイベント時に、value と attributes を console.log に出力するとこのようになります。sinceプロパティはデフォルト値の2010が格納されています。

<TextControl
	placeholder="Framework name"
	value={ name }
	onChange={ ( value ) => {
		console.log( 'TextControl value: ' + value );
		setAttributes( { name: value } );
		console.log( attributes );
		}
	}
/>
name: framewor となっていて、保存完了までは若干ラグがある

5.3 HTMLでの保存をSaveメソッドに実装

saveメソッドがnullを返しているので、HTMLで保存するように実装します。

下記のようにブロックで入力したとして、

input-sample

現時点では入力内容はJSON形式で、ブロックの開始、終了を表すHTMLコメント内に保持されます。Gutenbergをコードエディターモードに切り替えれば実際の保存内容が確認できます。このままではHTMLが保存されないためプレビューや投稿ページには何も表示されませんので、saveメソッドでJSXを記述しHTMLでDBに保存するよう実装します。

逆にnullのままにしておけば、HTML構造に依存しない形でブロックの内容をDBに保存できます。このようにJSONで保存した場合は、HTMLを出力するレンダー関数を別途PHPにて実装する必要があります。

<!-- wp:framework-dl/framework-dl-block -->
<!-- wp:framework-dl/description-block {"name":"framework","since":2016,"language":"JavaScript","description":"A framework description.\nSomthing framework distinction."} /-->

<!-- wp:framework-dl/description-block {"name":"framework 2","since":2009,"description":"A framework description.\nSomthing framework distinction."} /-->
<!-- /wp:framework-dl/framework-dl-block -->

今回は、HTMLで保存するため、saveメソッドは下記のようになります。

save: ( { attributes } ) => {
	return (
	<>
		<dt>{ attributes.name }</dt>
		<dd>
			<span className="since">{ attributes.since }</span>年~
		</dd>
		<dd>
			言語:<span className="language">{ attributes.language }</span>
		</dd>
		<dd className="description">{ attributes.description }</dd>
	</>
	);
},

dt dd要素として表示したいフレームワーク名や言語、説明は、attributesに保持されているので、引数としてattributesを渡します。editメソッドのように、複数の変数へ分割代入せずに、直接attributes.nameなどで値を呼び出しています。

登場年と言語に関しては、attributes.since / attributes.languagespanタグで括っています。下書きや公開状態の投稿をGutenbergエディターを開いて編集する場合、GutenbergはDBを読み込んでattributesに値をセットして表示する仕組みになっています。

そのために、保存したHTMLのどこからname / sinceなどの値を読み取るかの指定をattributesプロパティに追記します。

attributes: {
	name: {
		type: 'string',
		source: 'text',
		selector: 'dt',
	},
	since: {
		type: 'string',
		default: '2010',
		source: 'text',
		selector: 'span.since',
	},
	language: {
		type: 'string',
		source: 'text',
		selector: 'span.language',
	},
	description: {
		type: 'string',
		source: 'text',
		selector: 'dd.description',
	},
},

SelectorプロパティでHTMLを指定します、jQueryでDOMを取得する感じです。
Sourceプロパティでは取得したHTML全体を使うか、内部テキストを使うか、などを指定します。
defaultでデフォルト値を入れておくこともできます。
属性 – Japanese Team — WordPress.org

例えばdescription属性は、descriptionクラスのddタグから内部テキストを取得する設定となっています。

ブロックが表示される時には、このsource / selectorの設定に基づいてDBのHTMLからパースした値をattributesにセットし、editメソッドではコンポーネントのvalueattributes内の値を代入します。このようにして、DBに保存している内容をGutenbergで表示しています。

実際にどういうタイミングで読取りや受け渡しが行われるかは、Reactコンポーネントのライフサイクルとかに基づいていると思いますが、詳しくは調べてません。 state とライフサイクル – React

InnerBlockのjsはこれで完成で、最終的なコードはこうなります。
src/framework-dd-block.js

import { registerBlockType } from '@wordpress/blocks';
import {
	Flex,
	TextControl,
	__experimentalNumberControl as NumberControl,
	SelectControl,
	TextareaControl,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';

import './style.scss';

registerBlockType( 'framework-dl/description-block', {
	title: __( 'Framework description ', 'framework-dl-block' ),

	description: __( 'Framework descriptions block', 'framework-dl-block' ),

	category: 'widgets',

	parent: [ 'framework-dl/framework-dl-block' ],
	supports: {
		// Removes support for an HTML mode.
		html: false,
	},

	attributes: {
		name: {
			type: 'string',
			source: 'text',
			selector: 'dt',
		},
		since: {
			type: 'string',
			default: 2010,
			source: 'text',
			selector: 'span.since',
		},
		language: {
			type: 'string',
			source: 'text',
			selector: 'span.language',
			default: '',
		},
		description: {
			type: 'string',
			source: 'text',
			selector: 'dd.description',
		},
	},

	edit: ( { attributes, setAttributes } ) => {
		const { name, since, language, description } = attributes;
		return (
			<>
				<TextControl
					placeholder="Framework name"
					value={ name }
					onChange={ ( value ) => setAttributes( { name: value } ) }
				/>
				<Flex>
					<NumberControl
						label="登場年"
						shiftStep={ 1 }
						value={ since }
						onChange={ ( value ) =>
							setAttributes( { since: value } )
						}
					/>
					<SelectControl
						label="言語"
						options={ [
							{ label: 'PHP', value: 'PHP' },
							{ label: 'JavaScript', value: 'JavaScript' },
							{ label: 'Ruby', value: 'Ruby' },
							{ label: 'Erlang', value: 'Erlang' },
						] }
						value={ language }
						onChange={ ( value ) =>
							setAttributes( { language: value } )
						}
					/>
				</Flex>

				<TextareaControl
					placeholder="概要"
					value={ description }
					onChange={ ( value ) =>
						setAttributes( { description: value } )
					}
				/>
			</>
		);
	},

	save: ( { attributes } ) => {
		return (
			<>
				<dt>{ attributes.name }</dt>
				<dd>
					<span className="since">{ attributes.since }</span>年~
				</dd>
				<dd>
					言語:
					<span className="language">{ attributes.language }</span>
				</dd>
				<dd className="description">{ attributes.description }</dd>
			</>
		);
	},
} );

6. index.js の edit/save メソッド

iconを変更して、edit/saveメソッドはdlタグを返すよう実装します。

icon: 'feedback',

edit: () => {
	return (
		<InnerBlocks
			allowedBlocks={ [ 'framework-dl/description-block' ] }
		/>
	);
},

save: () => {
	return (
		<dl>
			<InnerBlocks.Content />
		</dl>
	);
},

Gutenbergでのスタイルを調整したいのでクラス名を付与したいのですが、saveメソッドで返された最上位のHTML(ここではdl要素)には、自動的にclassNameが付与されます。よって、特に指定はなし。
editメソッドではルート要素(returnされる最上位の要素)が見た目と一致しない場合があるため、明示的にclassNameを指定する必要があるそうです。

実際にWordPressが投稿を表示する際にthe_content()関数で出力するHTMLはこのようになります。

<dl class="wp-block-framework-dl-framework-dl-block">
  <dt>framework</dt>
  <dd><span class="since">2007</span>年~</dd>
  <dd>言語:<span class="language">JavaScript</span></dd>
  <dd class="description">A framework description. Something framework distinction.</dd>
</dl>

参照: Edit and Save | Block Editor Handbook | WordPress Developer Resources

デフォルトで付与されるclassNameは、registerBlockType関数に渡された一意識別子から生成されるようです。
framework-dl/framework-dl-block → wp-block-framework-dl-framework-dl-block

7.スタイルの調整

ブロックに対しクラス名が付与されているので、スタイルを当てます。

scssファイルが既に用意されていて、background-colorpadding が指定されているので、追記していきます。

src/style.scss

.wp-block-framework-dl-framework-dl-block {
	background-color: none;
	padding: 2px;

	dt {
		border-bottom: solid 1px black;
	}
	dd, dt {
		margin-left: 0;
	}
}

src/index.jsで、このscssファイルがインポートされているので一緒にビルドされます。

import './style.scss';

また、ビルド済みのCSSファイルは build/style-index.css で、framework-dl-block.phpにてエンキューの登録がされています。

$style_css = 'build/style-index.css';
wp_register_style(
	'framework-dl-framework-dl-block-block',
	plugins_url( $style_css, __FILE__ ),
	array(),
	filemtime( "$dir/$style_css" )
);

完成

framework-dl-block-post

コードエディターモードにすると、下記のようなHTMLでDBに保存されていることが分かります。

<!-- wp:framework-dl/framework-dl-block -->
<dl class="wp-block-framework-dl-framework-dl-block"><!-- wp:framework-dl/description-block -->
<dt>CakePHP</dt>
<div class="flex"><dd><span class="since">2006</span>年~</dd><dd>言語:<span class="language">PHP</span></dd></div>
<dd class="description">Ruby on Railsの概念を多く取り込んだWEBアプリケーションフレームワーク。PHPでは老舗。ビューが柔軟に構築できる。</dd>
<!-- /wp:framework-dl/description-block -->

<!-- wp:framework-dl/description-block -->
<dt>Ruby on Rails</dt>
<div class="flex"><dd><span class="since">2005</span>年~</dd><dd>言語:<span class="language">Ruby</span></dd></div>
<dd class="description">WEBアプリケーションフレームワークとしては古くかつ有名。MVC、スキャフォルド、設定より規約などの特徴を持ち、DRYであることを基本理念としている。2020年現在も広く使われている。</dd>
<!-- /wp:framework-dl/description-block -->

<!-- wp:framework-dl/description-block -->
<dt>Vue.js</dt>
<div class="flex"><dd><span class="since">2014</span>年~</dd><dd>言語:<span class="language">JavaScript</span></dd></div>
<dd class="description">プロジェクトの一部分に使うことも、シングルページアプリケーションの構築もできる軽量シンプルなUIフレームワーク。開発者は元々GoogleでAngular.jsの開発に携わっていた。</dd>
<!-- /wp:framework-dl/description-block -->

<!-- wp:framework-dl/description-block -->
<dt>Laravel</dt>
<div class="flex"><dd><span class="since">2010</span>年~</dd><dd>言語:<span class="language">PHP</span></dd></div>
<dd class="description">後発ながら高いシェアを誇る。Webアプリケーションに必要な機能は全部入り。フロントはVue.js、バックエンドは依存性注入ができる。Artisanコマンドも種類が豊富。</dd>
<!-- /wp:framework-dl/description-block --></dl>
<!-- /wp:framework-dl/framework-dl-block -->

GitHubにコードをアップしています。

https://github.com/akiya64/framework-dl-block/releases/tag/v1.0.0

Comments

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください