社区新闻

如何构建一个多区块插件

查看官方原文 ↗ 发布于

作为一名主要专注于企业级解决方案的WordPress开发者,多区块插件的概念远比拥有多个独立的区块插件更有意义。从长远来看,一个设计良好的企业系统可能轻松拥有数十个自定义区块,以及其他与修改区块或改善编辑器体验相关的功能。

多区块插件的概念我在网上见过几次,但我不记得有看到过深入的教程。在本文中,我将创建一个基础的多区块插件,然后添加高级功能,将其转变为一个强大的、可以扩展到注册区块之外的区块插件。

在本文结束时,你将完成设置自己的多区块插件的步骤,并准备好在一个中心化的插件中构建和管理任意数量的区块,以及其他与区块编辑器相关的功能,如变体、注册区块样式、添加插槽填充以及你可能需要的任何其他功能。

多区块插件的优势

  • 维护更少,依赖管理更容易
  • 增加共享代码,减少跨插件的重复
  • 可能改善安全响应时间(我不是专家,但关键依赖中的一个漏洞在1个插件中比在10个插件中更容易处理和遏制)

如果你不熟悉创建自定义区块及其系统设置和要求,请阅读关于在WordPress中创建区块开发环境的内容。

如果你正在跟随本教程操作,可以参考一个插件示例,可以在公共仓库中查看。

基础设置

在本教程的这一部分结束时,你将构建一个名为WP Multi Block的单一插件,它将注册两个静态区块和一个动态区块。让我们从创建你的区块插件开始。

创建区块插件

第一步是为区块获取一个基础插件设置。为此,你将使用官方支持的create-block工具。这个工具将负责搭建这个插件,只需在你的/plugins文件夹内运行一个简单的命令:

npx @wordpress/create-block@latest wp-multi-block

默认情况下,@wordpress/create-block生成一个静态区块,但有一个参数--variant dynamic,如果你希望只从一个动态区块开始,可以使用它。如果你正在跟随操作,你将在本教程后面使用这个参数。

静态区块和动态区块有什么区别?在非常高的层面上,静态区块使用save()函数将区块的HTML标记存储到数据库的post_content表中。动态区块使用PHP渲染回调在查看页面或文章时在服务器端渲染内容,只将区块的属性存储在数据库中。更多细节可以阅读开发者博客上的静态与动态区块:有什么区别?

出于本教程的目的,你将使用基本命令并从静态区块开始。

重构插件结构

为了更好地组织插件中的多个区块,可以对插件结构进行一些更改。

创建主区块目录

src目录内执行以下操作:

  • 删除所有现有文件
  • 创建一个名为blocks的文件夹

为什么添加一个blocks目录,这似乎没有必要?我们希望能够稍后添加src/scriptssrc/styles,因此对区块进行分组将改善长期的组织和维护。

创建单个区块

我们可以使用@wordpress/create-block并通过--no-plugin选项来仅设置区块所需的内容。在src/blocks目录内运行以下命令:

npx @wordpress/create-block@latest block-one --no-plugin

以下是我在VS Code中更新后的目录结构视图:

VS Code中区块一的文件和文件夹结构视图。

更新注册区块类型操作

将区块移动到新目录后,现在需要更新register_block_type操作中对其位置的引用:

  • 编辑wp-multi-block.php文件
  • 让我们给现有函数一个更好的名字,使用multiblock_register_static_blocks
  • register_block_type函数中,你需要包含到我们区块的新路径,使其看起来像/build/blocks/block-one

我们最终的代码如下所示:

function multiblock_register_blocks() {
	register_block_type( __DIR__ . '/build/blocks/block-one' );
}
add_action( 'init', 'multiblock_register_blocks' );

更新构建文件

  • 是时候通过运行npm run build来重新生成构建文件了

让我们确认这些更改是否有效,激活插件并刷新编辑器,然后添加我们的第一个区块。我们应该得到类似这样的结果:

第一个静态区块的编辑器视图。

添加更多区块

添加更多区块就像创建第一个区块时运行相同的命令一样简单,但使用不同的名称。继续创建区块二

创建新区块

你可以在src/blocks目录内运行以下命令,重复创建第一个区块的操作:

npx @wordpress/create-block@latest block-two --no-plugin

以下是我在VS Code中更新后的目录结构视图:

VS Code中前两个区块的文件和文件夹结构视图。

更新注册区块类型操作

  • 编辑wp-multi-block.php文件,复制register_block_type函数,并将引用更改为/build/blocks/block-two

最终的代码如下所示:

function multiblock_register_blocks() {
	register_block_type( __DIR__ . '/build/blocks/block-one' );
	register_block_type( __DIR__ . '/build/blocks/block-two' );
}
add_action( 'init', 'multiblock_register_blocks' );

更新构建文件

  • 是时候通过运行npm run build来重新生成我们的构建文件了

让我们确认这些更改是否有效,刷新编辑器并添加我们的两个区块。我们应该得到类似这样的结果:

前两个静态区块的编辑器视图。

添加动态区块

到目前为止,你只处理了静态区块,但这如何应用于动态区块呢?通过一些更新,你也可以将动态区块与我们的静态区块一起包含进来。如果你不熟悉这两种区块类型,可以阅读开发者博客上的静态与动态区块:有什么区别?

你将像之前一样开始创建一个新区块,但这次我们将添加一个选项来指定我们正在创建一个动态区块。继续创建区块三

创建动态区块

你可以再次使用@wordpress/create-block来创建我们的动态区块。在src/blocks目录内运行以下命令:

npx @wordpress/create-block@latest block-three --no-plugin --variant dynamic

更新注册区块类型操作

  • 编辑wp-multi-block.php文件,复制register_block_type函数,并将引用更改为/build/blocks/block-three

最终的代码如下所示:

function multiblock_register_blocks() {
	register_block_type( __DIR__ . '/build/blocks/block-one' );
	register_block_type( __DIR__ . '/build/blocks/block-two' );
	register_block_type( __DIR__ . '/build/blocks/block-three' );
}
add_action( 'init', 'multiblock_register_blocks' );

更新构建和启动命令

在更新构建之前,你需要在构建命令中添加一个参数。通过添加--webpack-copy-php,你是在告诉构建过程将任何PHP文件包含到最终的构建目录中。

  • 编辑package.json
  • 更新buildstart命令,告诉webpack复制PHP文件。

最终的命令应如下所示:

"build": "wp-scripts build --webpack-copy-php"
"start": "wp-scripts start --webpack-copy-php"

更新构建文件

是时候通过运行npm run build来重新生成我们的构建文件了

让我们确认这些更改是否有效,刷新编辑器并添加我们的所有三个区块。我们应该得到类似这样的结果:

到目前为止构建的三个区块的编辑器视图。

关于文本域的说明

当使用@wordpress/create-block时,block.json中的text-domain与区块名称匹配。在你的插件中,每个区块将有一个唯一的text-domain。这是编辑每个block.json文件并将text-domain更改为wp-multi-block的好时机。

基础设置回顾

恭喜!如果你一直跟着操作,你刚刚创建了一个多区块插件,它加载三个区块,并由一组依赖项维护。你可以根据需要重复这些步骤来添加新区块。需要记住的要点是:

  • 单个区块名称必须是唯一的,所以不要忘记在整个区块文件中更新对namestitles的引用
  • 每个区块必须通过register_block_type函数注册

每个动态区块在其register_block_type函数中必须引用一个PHP文件,该文件在block.json文件中定义

高级配置

虽然从这一点开始的每个部分完全是可选的,因为你已经拥有一个功能齐全的多区块插件,但我建议你完成这些额外的步骤,以改善插件的整体配置,从而更好地简化开发、简化维护并提高代码的整体可读性。

在本教程的这一部分结束时,你将:

  • 添加另一个动态区块
  • 创建区块数组
  • 更新函数以使用foreach
  • 添加webpack以将我们的资源编译成单个资源
  • 添加一个脚本来修改核心区块样式。

添加一个新的register_block_type函数相当容易,但是重复20次或更多次,代码会是什么样子?相反,你可以添加一个区块数组,然后使用foreach来注册数组中的每个区块。

添加另一个动态区块

在我们深入之前,为了测试目的,拥有第二个动态区块会很有帮助,所以在src/blocks目录内创建一个:

npx @wordpress/create-block@latest block-four --no-plugin --variant dynamic

创建完区块四后,你需要再次通过运行npm run build来构建。这个新区块暂时还不会在编辑器中可用,我们必须先更新几个函数。

创建数组并添加foreach循环

首先创建一个数组,允许你根据需要快速轻松地向插件添加新区块,而无需再添加另一个register_block_type函数。然后使用foreach循环遍历数组,并在register_block_type函数中注册每个区块。编辑wp-multi-block.php文件,将multiblock_register_blocks函数更新为如下所示:

function multiblock_register_blocks() {
	$custom_blocks = array (
		'block-one',
		'block-two',
		'block-three',
		'block-four',
	);
	
	foreach ( $custom_blocks as $block ) {
		register_block_type( __DIR__ . '/build/blocks/' . $block );
	}
}
add_action( 'init', 'multiblock_register_blocks' );

通过刷新编辑器或前端并添加所有四个区块来确认这些更改是否有效。我们应该得到类似这样的结果:

到目前为止构建的四个区块的编辑器视图。

现在,当你添加新区块时,只需要快速添加到区块数组中即可,这使得我们其余代码保持精简且更易于维护。

合并区块资源

默认情况下,脚本文件的加载由block.json文件处理。这对于单区块插件效果很好,但在多区块插件中,你可能会考虑简化脚本文件的加载。

现在,这种方法有一些利弊,可能并不适合所有人。一方面,你减少了加载项的数量,并且对输出有更多的控制。另一方面,你也失去了一些很好的功能,比如只在区块出现在页面上时才加载view.js文件。

出于本教程的目的,首选方法是合并和编译我们的JavaScript和CSS文件,并计划将来对它们进行gZip压缩并托管在内容分发网络(CDN)上。为了设置这个,你将添加webpack,利用核心WordPress默认的webpack配置,并将所有内容打包成一个脚本和一个样式表。

创建webpack配置文件

首先创建一个webpack配置文件。在这里,你将扩展@wordpress/scripts包中的webpack配置,因为你希望在添加自己功能的同时保持该功能。

首先在你的插件根文件夹中创建一个webpack.config.js文件,并粘贴以下内容:

const defaultConfig = require( '@wordpress/scripts/config/webpack.config' );
const path = require( 'path' );

module.exports = {
    ...defaultConfig,
    entry: {
        'multi-block-editor': [ path.resolve( __dirname, 'src/multi-block-editor.js' ) ],
        'multi-block-frontend': [ path.resolve( __dirname, 'src/multi-block-frontend.js' ) ],
    },
    output: {
        path: path.resolve( __dirname, 'build' ), filename: '[name].js',
    },
};

在webpack文件中,你扩展了作为@wordpress/scripts包一部分的配置文件,然后添加了自己的入口点,用于编译并加载到编辑器中的资源,以及另一个用于编译将在前端加载的资源。我们将这些入口点命名为multi-block-editormulti-block-frontend

添加入口点

现在你需要创建在webpack.config.js文件中指定的入口点文件。

首先添加区块编辑器的脚本。在src目录中创建一个名为multi-block-editor.js的文件,并粘贴以下内容:

import './blocks/block-one';
import './blocks/block-two';
import './blocks/block-three';
import './blocks/block-four';

接下来添加前端资源的脚本。在src目录中创建一个名为multi-block-frontend.js的文件,暂时只需粘贴以下内容:

console.log( 'frontend test' )

加载编辑器和前端资源

加载编辑器资源

现在脚本和样式文件已作为单个文件输出,你需要使用enqueue_block_editor_assets操作将它们加载到编辑器中。

打开文件并添加以下功能:wp-multi-block.php

function multiblock_enqueue_block_assets() {
	wp_enqueue_script(
		'multi-block-editor-js',
		plugin_dir_url( __FILE__ ) . 'build/multi-block-editor.js',
		array('wp-blocks', 'wp-components', 'wp-data', 'wp-dom-ready', 'wp-edit-post', 'wp-element', 'wp-i18n', 'wp-plugins'),
		null,
		false
	);
	
	wp_enqueue_style(
		'multi-block-editor-css',
		plugin_dir_url( __FILE__ ) . 'build/multi-block-editor.css',
		array(),
		null
	);
}
add_action( 'enqueue_block_editor_assets', 'multiblock_enqueue_block_assets' );

Enqueue 前端资产

现在你需要通过在文件中添加另一个函数来排队前端资源:wp-multi-block.php

function multiblock_enqueue_frontend_assets() {
	wp_enqueue_style(
		'multi-block-frontend-css',
		plugin_dir_url( __FILE__ ) . 'build/style-multi-block-editor.css',
	);

	wp_enqueue_script(
		'multi-block-frontend-js',
		plugin_dir_url( __FILE__ ) . 'build/multi-block-frontend.js',
		array(),
		null,
		true
	);
}
add_action( 'wp_enqueue_scripts', 'multiblock_enqueue_frontend_assets' );

更新块样式

在这种配置中,每个模块都有一个独立的文件,用于编辑和前端样式。在大多数情况下,我们在前端加载的内容,也是我们想在编辑器中加载的内容。我更倾向于把我的文件导入到文件里。这样你可以保留一套前端类,同时添加编辑器中独特的内容。style.scsseditor.scss

这里有一个例子,说明经过几次更新后,块文件会是什么样子。边框只在编辑器中添加,且添加边框后仅在选中块时出现。editor.scss.is-selected

更新我们每个方块的文件,像这个示例一样导入该文件:editor.scssstyle.scss

@import "./style.scss";

.wp-block-example-block-one.is-selected {
    border: 2px dotted #f00;
}

删除未使用文件并清理block.json

现在你已经有了单文件资源,我们可以逐一查看块,删除任何未被使用的view.js文件,这些文件不再通过块加载。如果你正在为自己的多块插件添加模块,并且有需要此功能的模块,你可以将它们包含在我们的前端入口点 js 文件中。想了解view.js文件在使用交互性API中的作用,可以阅读本网站的《互动API初步介绍》。

在每个模块中,编辑文件以移除对js和css文件的引用。您希望移除以下物品:block.json

"editorScript": "file:./index.js",
"editorStyle": "file:./index.css",
"style": "file:./style-index.css",
"viewScript": "file:./view.js"

注意:在动态方块中,确保不要移除看起来像这样的渲染线:

"render": "file:./render.php"

你可以去生成新的插件资源,并在编辑器和开发环境前端测试新模块。npm run build

附加剧本

你在插件中还要包含一个示例,说明如何向编译后的编辑器脚本添加额外脚本。这些脚本可用于块修改或变体、槽位填充或其他功能。

添加一个简单的脚本,去除核心按钮上的轮廓样式。

添加脚本修改块样式

首先你需要安装几个新的依赖:

npm install @wordpress/blocks @wordpress/dom-ready --save-dev

安装包后,创建如下脚本文件:

  • src/scripts/modifications
  • 创建一个名为文件并粘贴以下内容:button.js
import { unregisterBlockStyle } from '@wordpress/blocks';
import domReady from '@wordpress/dom-ready';

domReady(() => {
    unregisterBlockStyle( 'core/button', array( 'outline' ) )
});

现在你需要将这个脚本包含在块编辑器的入口中:

  • 编辑multi-block-editor.js
  • 导入后,修改后的文件如下:button.js
// Import the plugin blocks
import './blocks/block-one';
import './blocks/block-two';
import './blocks/block-three';
import './blocks/block-four';

// Import other block scripts
import './scripts/modifications/button';

现在你只需要更新构建文件并刷新编辑器。试着加个按钮,你会发现样式选项已经消失了。npm run buildoutline

如果你对更多策划编辑体验的方法感兴趣,文章《15种策划WordPress编辑体验的方法》提供了额外的代码片段,帮助简化内容创作、确保一致性并打造个性化编辑体验。

收官

作者的话:我希望其他人在未来的工作中也能从这种构建模块插件的方法中找到益处。我相信我的做法有多种方式可以被认可,我也很想听听我们作为一个社区该如何做到这一点。

关于不同方法的教程,可以参考《使用 InnerBlocks 设置多块插件》和 post meta 文章。

资源

文献资料

相关视频教程

Learn.WordPress 上的课程