WordPress 区块编辑器基于这样一个理念:你可以将独立的区块组合在一起来撰写文章或构建页面。区块之间还可以相互使用与交互。这使其非常模块化且灵活。
但区块编辑器的模块化并不仅仅体现在其行为和输出上。Gutenberg 代码库也是从零开始构建为若干可重用且独立的模块或包,它们组合在一起,便形成了我们大家都熟悉的应用程序和界面。这些模块被称为 WordPress 包,并定期在 npm 包仓库中发布和更新。
这些包用于驱动区块编辑器,但它们也可以用于驱动 WordPress 管理后台之内或之外的任何页面。
为什么?
对所有相关参与者而言,采用模块化架构有若干好处:
- 每个包都是一个独立的单元,拥有定义明确的公共 API,用于与其他包和第三方代码进行交互。这让核心贡献者更容易理解代码库。他们可以一次专注于一个包,理解它并进行更新,同时确切地知道这些改动会如何影响所有依赖该包的其他部分。
- 模块化方式对最终用户同样有益。它允许在不同的 WordPress 管理页面中选择性地加载脚本,同时控制打包体积。例如,如果我们使用 components 包来驱动插件的设置页面,那么该页面就无需加载 block-editor 包。
- 这种架构还允许第三方开发者将这些包用作 npm 依赖或 WordPress 脚本依赖,从而在 WordPress 环境内外重用这些包。
包的类型
Gutenberg 代码库中几乎所有的内容都被构建为包。我们可以将这些包分为两种不同的类型:
生产包
这些包以 JavaScript 脚本的形式随 WordPress 本身一起发布。它们构成了在你的浏览器中实际运行的生产代码。例如,有一个 components 包,它是一组可重用的 React 组件,用于快速制作原型和构建界面。还有一个 api-fetch 包,可用于调用 WordPress REST API。
第三方开发者可以通过两种不同的方式使用这些生产包:
- 如果你正在构建在 WordPress 环境之外运行的 JavaScript 应用、网站或页面,你可以像使用 npm 仓库中的任何其他 JavaScript 包一样使用这些包。
npm install @wordpress/components
import { Button } from '@wordpress/components';
function MyApp() {
return <Button>Nice looking button</Button>;
}
- 如果你正在构建运行于 WordPress 之上的插件,你很可能更愿意使用 WordPress 自身附带的包。这样,多个插件可以重用相同的包,避免代码重复。在 WordPress 中,这些包以 WordPress 脚本的形式提供,其句柄遵循
wp-package-name这样的格式(例如wp-components)。一旦你将该脚本添加到自己的 WordPress 插件脚本依赖中,该包就可以通过wp全局变量来使用。
// myplugin.php
// 依赖于 "components" 和 "element" 包的脚本注册示例。
wp_register_script( 'myscript', 'pathtomyscript.js', array ('wp-components', "react" ) );
// 在你的脚本中使用该包
const { Button } = wp.components;
function MyApp() {
return <Button>Nice looking button</Button>;
}
对开发者来说,定义脚本依赖可能是一项繁琐的工作,很容易出现错误和疏漏。如果你想了解如何将这项任务自动化,请查阅 @wordpress/scripts 和 @wordpress/dependency-extraction-webpack-plugin 的文档。
带样式表的包
某些生产包提供了正常运行所需的样式表。
- 如果你将包作为 npm 依赖使用,样式表将位于该包的
build-style文件夹中。请务必在你的应用程序中加载该样式文件。 - 如果你在 WordPress 环境中工作,则需要将这些样式表排入队列(enqueue),或将它们添加到你的样式表依赖中。样式表的句柄与脚本的句柄相同。
在现有 WordPress 页面的上下文中,如果你遗漏了正确的脚本或样式依赖定义,只要这些脚本和样式已经由 WordPress 或其他插件在该页面加载,你的插件可能仍然能够正常工作;但如果想避免未来版本中可能出现的故障,强烈建议详尽地定义所有依赖。
带数据存储的包
一些 WordPress 生产包定义了数据存储来管理其状态。这些存储也可以被第三方插件和主题用来检索和操作数据。这些数据存储的名称同样遵循 core/package-name 格式进行了规范化(例如,@wordpress/block-editor 包定义并使用了 core/block-editor 数据存储)。
如果你在插件中使用其中一个存储来访问和操作 WordPress 数据,请不要忘记将相应的 WordPress 脚本添加到自己的脚本依赖中,以确保插件正常工作。(例如,如果你要从 core/block-editor 存储中检索数据,就应当如上所示将 wp-block-editor 包添加到你的脚本依赖中。)
开发包
这些包用于开发模式,帮助开发者完成开发、构建和发布 JavaScript 应用、WordPress 插件与主题的日常任务。它们包含用于对代码库进行 lint 检查、构建、测试等工具……
编辑器包

不同的编辑器包之间有什么区别?每个包的用途是什么?
新贡献者常常会惊讶地发现,文章编辑器是由三个独立的包——@wordpress/edit-post、@wordpress/editor 和 @wordpress/block-editor——以分层抽象的方式构建而成的。
上文的为什么?部分应该为各个包如何满足特定需求提供了一些背景。这同样适用于这些包:
@wordpress/block-editor提供了用于实现区块编辑器的组件,它操作的是一个由区块对象组成的数组这一原始值。它对该值的保存方式不做任何假设,对 WordPress 站点也没有任何感知(也不作任何要求)。@wordpress/editor是面向 WordPress 文章的增强版区块编辑器。它使用了@wordpress/block-editor包中的组件。由于它理解 WordPress 文章的概念,它将表示区块的值的加载与保存机制与文章及其内容关联起来。它还提供了在编辑器环境中处理文章对象的各种相关组件(例如文章标题输入组件)。这个包可以支持编辑任何文章类型的内容,并且不假定渲染发生在任何特定的 WordPress 屏幕或布局中。@wordpress/edit-post是 WordPress 管理后台中“新文章”(“编辑文章”)屏幕的实现。它负责对@wordpress/editor和@wordpress/block-editor提供的各种组件进行布局,并完全了解它们在 WordPress 管理仪表盘特定屏幕上的呈现方式。
以这种方式构建,这些包可以在“新文章”屏幕用例之外以多种组合方式使用:
@wordpress/edit-site或@wordpress/edit-widgets包可以以与@wordpress/edit-post大致相同的方式,充当“站点编辑器”或“小工具编辑器”的类似实现。@wordpress/editor可用于实现“可重用区块”区块,因为它本质上是一个与wp_block文章类型关联的嵌套区块编辑器。@wordpress/block-editor可以独立于 WordPress 使用,或与完全不同的保存机制配合使用。例如,它可以用于站点文章的评论编辑器。