WordPress development is currently undergoing a transitional period. Whether you are a newbie or a senior developer, the introduction of "Site-wide Editing" (FSE) features, including Block Editor (WordPress 5.0) and Site Editor (WordPress 5.9), has subverted the traditional way we build WordPress themes and plugins.
Although we have been in contact with Block Editor for five years, its development is still challenging because the documentation is either missing or outdated. This reflects more the current situation of rapid iteration of FSE functions.
For example, in 2018, a series of articles on introduction to Gutenberg development was published on CSS-tricks. But time has passed, and although that development method is still effective, it is no longer recommended (in addition, the create-guten-block project it is based on is no longer maintained).
This article is intended to help you start WordPress block development and follow the current approach. Of course, things may change after this article is published. But I will try to focus on its core idea, because even if the tool develops over time, the core concept is likely to remain the same.
First, let's clarify some terms, such as "block". All developments of these features prior to WordPress 5.0 were used with the code name "Gutenberg" (inventor of printing).
Since then, "Gutenberg" has been used to describe everything related to blocks, including block editors and site editors, so it has become so complicated that some people hate the name. Most importantly, there is also a Gutenberg plugin for testing experimental features that may be included in the future. If you think calling all of this “website-wide editing” can solve the problem, there are also some concerns.
So, in this article, when we refer to "blocks", we refer to components that create content in WordPress block editor. Blocks are inserted into pages or articles and provide structure for specific types of content. WordPress comes with some "core" blocks for common content types, such as paragraphs, lists, images, videos, audio, and more.
In addition to these core blocks, we can also create custom blocks. This is the focus of WordPress block development (you can also filter core blocks to modify their functionality, but you may not need them for the time being).
Before we dive into creating a block, we must first understand how the block works internally. This will definitely save us a lot of trouble in the future.
I like to understand blocks abstractly as: an entity with certain attributes (called attributes) that represent certain content. I know this sounds vague, but please be patient with me to explain. Blocks are basically manifested in two ways: as graphical interfaces in the block editor, or as data blocks in the database.
When you open the WordPress block editor and insert a block (for example, a Pullquote block), you get a nice interface. You can click on the interface and edit the referenced text. The Settings panel on the right side of the Block Editor UI provides options for adjusting text and setting the appearance of a block.
When you finish creating a beautiful quote and clicking Publish, the entire post is stored in the wp_posts table of the database. This is nothing new due to Gutenberg. This is how things have always worked - WordPress stores article content in a specified table in the database. But the new one is that the representation of the Pullquote block is part of the content stored in the post_content field of the wp_posts table.
What does this expression look like? Let's take a look:
<blockquote> <p>It is not an exaggeration to say that peas can be described as nothing less than perfect spheres of joy.</p> <cite>The Encyclopedia of world peas</cite> </blockquote>
attribute - a block-related attribute.
Suppose you close the block editor and then open it again after a while. The block editor will retrieve the contents in the relevant post_content field. The editor then parses the retrieved content and when encountering the following:
<code>...</code>
Okay, this looks like a Pullquote block. Well...it also has a property...I do have a JavaScript file that tells me how to construct a graphical interface of a Pullquote block in the editor based on its properties. I should do this now so that this block is presented in its full glory.As a block developer, your job is:
Hope this gives you a clearer understanding of how blocks work.
Blocks are just plugins
blocks in the theme or multiple blocks in one plugin. However, usually if you want to make a block, you will want to make a plugin. So if you've ever created a WordPress plugin, you've partially mastered how to make WordPress blocks. But let's assume you've never set up a WordPress plugin, let alone blocks. Where do you even start?
Set blockWe have already introduced what a block is. Let's start setting up to make one.
This will give you access to npm and npx commands, where npm installs the dependencies of the block and helps compile the content, while npx runs commands on the package without installing the package. If you are using macOS, you may have Node installed and you can use nvm to update the version. If you are using Windows, you need to download and install Node.
Now you may come across other tutorials that jump directly to the command line and instruct you to install a package called @wordpress/create-block. This package is great because it generates a complete project folder with all the dependencies and tools you need to start your development.
I personally take this approach when setting up my own blocks, but please tolerate me for a moment, as I want to eliminate the subjective content it introduces and focus only on the necessary parts of the basic development environment for understanding.
These are the documents I want to point out specifically:
In addition to these files, there is also an src directory, which should contain the source code of the block.
Having these files and src directories is enough to start. In that group, please note that we actually only need a file (plugin.php) to make the plugin. The rest either provides information or is used to manage the development environment.
The aforementioned @wordpress/create-block package builds these files for us (and more). You can think of it as an automation tool, not a necessity. It does make the work easier anyway, so you can freely use it to build blocks by running the following command:
<blockquote> <p>It is not an exaggeration to say that peas can be described as nothing less than perfect spheres of joy.</p> <cite>The Encyclopedia of world peas</cite> </blockquote>
Suppose you have prepared the three files mentioned in the previous section and it is time to install the dependencies. First, we need to specify the dependencies we will need. We do this by editing package.json. When using the @wordpress/create-block utility, the following is generated for us (annotation was added; JSON does not support annotation, so if you copy the code, please delete the annotation):
<blockquote> <p>It is not an exaggeration to say that peas can be described as nothing less than perfect spheres of joy.</p> <cite>The Encyclopedia of world peas</cite> </blockquote>
View uncommented version
```json
{
"name": "block-example",
"version": "0.1.0",
"description": "Example block scaffolded with Create Block tool.",
"author": "The WordPress Contributors",
"license": "GPL-2.0-or-later",
"main": "build/index.js",
"scripts": {
"build": "wp-scripts build",
"format": "wp-scripts format",
"lint:css": "wp-scripts lint-style",
"lint:js": "wp-scripts lint-js",
"packages-update": "wp-scripts packages-update",
"plugin-zip": "wp-scripts plugin-zip",
"start": "wp-scripts start"
},
"devDependencies": {
"@wordpress/scripts": "^24.1.0"
}
}
<code>...</code>
Now that package.json is set up, we should be able to install all these dependencies by navigating to the project folder in the command line and running npm install.
If you are from classic WordPress plugin development, you probably know that all plugins have a piece of information in the main plugin file, which helps WordPress recognize the plugin and display information about it on the Plug-in screen in the WordPress admin panel.
The following is a plugin created for me by @wordpress/create-block for a creatively called "Hello World":
npx @wordpress/create-block
This is in the main plugin file and you can name it as you like. You can name it a common name like index.php or plugin.php. The create-block package automatically names it as the project name you provided at installation. Since I'm referring to this example as "Block Example", the package gives us a block-example.php file with all of this.
You need to change some details, such as making yourself an author, etc. Not all of this is necessary. If I start with "head", then it may be closer to this:
{ // 定义项目名称 "name": "block-example", // 使用语义版本控制设置项目版本号 "version": "0.1.0", // 项目的简短描述 "description": "Example block scaffolded with Create Block tool.", // 您可以将其替换为您自己 "author": "The WordPress Contributors", // 标准许可信息 "license": "GPL-2.0-or-later", // 定义主JavaScript文件 "main": "build/index.js", // 我们在开发过程中构建和编译插件所需的一切 "scripts": { "build": "wp-scripts build", "format": "wp-scripts format", "lint:css": "wp-scripts lint-style", "lint:js": "wp-scripts lint-js", "packages-update": "wp-scripts packages-update", "plugin-zip": "wp-scripts plugin-zip", "start": "wp-scripts start" }, // 定义使用脚本包的哪个版本(撰写本文时为24.1.0) // https://developer.wordpress.org/block-editor/reference-guides/packages/packages-scripts/ "devDependencies": { "@wordpress/scripts": "^24.1.0" } }
I won't go into detail about the exact purpose of each line, as this is already a complete pattern in the WordPress plugin manual.
We have viewed the files required for the block. However, if you are using @wordpress/create-block, you will see many other files in the project folder.
The following is what is currently included:
<code> 这里的@wordpress/scripts包是主要的依赖项。如您所见,它是一个devDependency,这意味着它有助于开发。如何?它公开了wp-scripts二进制文件,我们可以使用它来编译我们的代码,从src目录到build目录,等等。 WordPress维护了许多其他软件包,用于各种目的。例如,@wordpress/components软件包为WordPress区块编辑器提供了一些预制UI组件,可用于为区块创建一致的用户体验,并符合WordPress设计标准。 您实际上*不需要*安装这些软件包,即使您想使用它们也是如此。这是因为这些@wordpress依赖项不会与您的区块代码捆绑在一起。相反,任何引用实用程序软件包代码的导入语句——例如@wordpress/components——都用于在编译期间构造“资产”文件。此外,这些导入语句被转换为将导入映射到全局对象的属性的语句。例如,import { \_\_ } from "@wordpress/i18n"被转换为const \_\_ = window.wp.i18n.\_\_的缩小版本。(window.wp.i18n是一个保证在全局范围内可用的对象,一旦相应的i18n软件包文件被排队)。 在插件文件中注册区块期间,隐式使用“资产”文件来告诉WordPress区块的软件包依赖项。这些依赖项会自动排队。所有这些都在幕后完成,前提是您使用的是scripts软件包。也就是说,您仍然可以选择在package.json文件中本地安装依赖项以进行代码完成和参数信息: ```json // etc. "devDependencies": { "@wordpress/scripts": "^24.1.0" }, "dependencies": { "@wordpress/components": "^19.17.0" }</code>
Wow, so much! Let's point out new content:
I want to dig into the src directory with you, but first focus on one of the files: block.json. If you are using create-block, it is ready for you; if not, keep creating it. WordPress is pushing hard to use it as a standard specification method to register a block by providing metadata that provides context for WordPress to simultaneously identify the block and render it in the block editor.
The following is what @wordpress/create-block generates for me:
<blockquote> <p>It is not an exaggeration to say that peas can be described as nothing less than perfect spheres of joy.</p> <cite>The Encyclopedia of world peas</cite> </blockquote>
Actually, we can include a lot of different information here, but we really only need name and title. A super-lite version might look like this:
<blockquote> <p>It is not an exaggeration to say that peas can be described as nothing less than perfect spheres of joy.</p> <cite>The Encyclopedia of world peas</cite> </blockquote>
One more thing before we get into the actual code is to register the plugin. We just set up all this metadata and we need a way to get WordPress to use it. This way WordPress knows where to find all the plugin assets so that they can be queued for use in the block editor.
Registering a block is a two-step process. We need to register it in PHP and JavaScript. For the PHP aspect, open the main plugin file (in this case block-example.php) and add the following after the plugin title:
<code>...</code>
This is what the create-block utility generates for me, which is why the function is named in such a way. We can use different names. The key is to avoid conflicts with other plugins, so it's better to use your namespace here to make it as unique as possible:
npx @wordpress/create-block
If the block.json containing all block metadata is in src, why do we point to the build directory? This is because our code still needs to be compiled. The scripts package processes the code of files in the src directory and places the compiled files used in production in the build directory, while copy block.jsonfile.
Okay, let's go to the JavaScript aspect of the registration block. Open src/index.js and make sure it looks like this:
{ // 定义项目名称 "name": "block-example", // 使用语义版本控制设置项目版本号 "version": "0.1.0", // 项目的简短描述 "description": "Example block scaffolded with Create Block tool.", // 您可以将其替换为您自己 "author": "The WordPress Contributors", // 标准许可信息 "license": "GPL-2.0-or-later", // 定义主JavaScript文件 "main": "build/index.js", // 我们在开发过程中构建和编译插件所需的一切 "scripts": { "build": "wp-scripts build", "format": "wp-scripts format", "lint:css": "wp-scripts lint-style", "lint:js": "wp-scripts lint-js", "packages-update": "wp-scripts packages-update", "plugin-zip": "wp-scripts plugin-zip", "start": "wp-scripts start" }, // 定义使用脚本包的哪个版本(撰写本文时为24.1.0) // https://developer.wordpress.org/block-editor/reference-guides/packages/packages-scripts/ "devDependencies": { "@wordpress/scripts": "^24.1.0" } }
We are entering the React and JSX world! This tells WordPress:
What's going on with Edit and save functions? One of the subtleties of WordPress block development is the distinction between "backend" and "frontend", which are used to render the content of the block in these contexts, where edit handles the backend rendering, save writes the content from the block editor to the database to render the content on the frontend of the website.
We can quickly operate and see if our blocks work in the block editor and render on the front end. Let's open index.js again and use the edit and save functions to return some basics to illustrate how they work:
<blockquote> <p>It is not an exaggeration to say that peas can be described as nothing less than perfect spheres of joy.</p> <cite>The Encyclopedia of world peas</cite> </blockquote>
This is basically a slim version of our previous code, just that we point directly to the metadata in block.json to get the block name and omit the Edit and Save components because we run the function directly from here.
We can compile it by running npm run build on the command line. After that, we can access the block named "Block Example" in the block editor:
If we put the block into the content area, we will get the message returned from the edit function:
If we save and publish the article, when viewing in front-end, we should get the message returned from the save function:
It looks like everything is normal! Now that we have confirmed that everything is fine, we can restore to what is in index.js before the test:
<code>...</code>
Note that the edit and save functions are associated with the two existing files generated by @wordpress/create-block in the src directory and contain other imports we need in each file. More importantly, these files create Edit and Save components containing block tags.
npx @wordpress/create-block
Look at what we did? We are importing props from the @wordpress/block-editor package, which allows us to generate classes that can be used for styles later. We also import the __ internationalization function for processing translation.
This will create a Save component, we will use almost the same content as src/edit.js, but with slightly different text:
{ // 定义项目名称 "name": "block-example", // 使用语义版本控制设置项目版本号 "version": "0.1.0", // 项目的简短描述 "description": "Example block scaffolded with Create Block tool.", // 您可以将其替换为您自己 "author": "The WordPress Contributors", // 标准许可信息 "license": "GPL-2.0-or-later", // 定义主JavaScript文件 "main": "build/index.js", // 我们在开发过程中构建和编译插件所需的一切 "scripts": { "build": "wp-scripts build", "format": "wp-scripts format", "lint:css": "wp-scripts lint-style", "lint:js": "wp-scripts lint-js", "packages-update": "wp-scripts packages-update", "plugin-zip": "wp-scripts plugin-zip", "start": "wp-scripts start" }, // 定义使用脚本包的哪个版本(撰写本文时为24.1.0) // https://developer.wordpress.org/block-editor/reference-guides/packages/packages-scripts/ "devDependencies": { "@wordpress/scripts": "^24.1.0" } }
Similarly, we got a nice class that can be used in CSS:
We just introduced how to use block properties to create classes. You are reading this on a CSS-related website, so I feel like I'd miss something if we didn't specifically cover how to write block styles.
If you look at block.json in the src directory, you will find two style-related fields:
Kev Quirk has a detailed article showing his way of making the backend editor look like a frontend UI.
Recall that the @wordpress/scripts package copies the block.json file when it processes the code in the /src directory and places the compiled assets in the /build directory. The build/block.json file used to register the block. This means that any path we provide in src/block.json should be written relative to build/block.json.
We can put several CSS files into the build directory, refer to the path in src/block.json, run build, and then it's done. But this does not take full advantage of the @wordpress/scripts compilation process, which can compile Sass into CSS. Instead, we put the style files in the src directory and import them in JavaScript.
When doing this, we need to pay attention to how @wordpress/scripts handles styles:
@wordpress/scripts packages are bundled using webpack and styled using PostCSS plugin. PostCSS can be extended with other plugins. The scripts package uses plugins from Sass, SCSS, and Autoprefixer, all of which can be used without installing additional packages.
In fact, when you start the initial block with @wordpress/create-block, you can get started with SCSS files very well, you can use these files to get started quickly:
Now let's do it by writing some Sass that we will compile into block CSS. Although these examples are not very Sassized, I still write them to a SCSS file to demonstrate the compilation process.
OK, let's start with the styles applied to the front-end and back-end. First, we need to create src/style.scss (if you are using @wordpress/create-block, it already exists) and make sure we import it, we can do this in index.js:
<blockquote> <p>It is not an exaggeration to say that peas can be described as nothing less than perfect spheres of joy.</p> <cite>The Encyclopedia of world peas</cite> </blockquote>
Open src/style.scss and put some basic styles in it using the class we generated from the block attribute:
<code>...</code>
That's all now! When we run build, this compiles to build/style.css and is referenced by the block editor and front-end.
You may need to write block editor-specific styles. To do this, create src/editor.scss (again, @wordpress/create-block does this for you) and put some styles in it:
npx @wordpress/create-block
Then import it in edit.js, which contains our Edit component (we can import it anywhere, but since these styles are for editors, it's more logical to import components here):
<blockquote> <p>It is not an exaggeration to say that peas can be described as nothing less than perfect spheres of joy.</p> <cite>The Encyclopedia of world peas</cite> </blockquote>
Now, when we run npm run build, the style will be applied to blocks in both contexts:
We imported the style files in edit.js and index.js, but remember that the compilation step generates two CSS files for us in the build directory: index.css and style-index.css. We need to reference these generated files in the block metadata.
Let's add a few statements to the block.json metadata:
<code>...</code>
Run npm run build again, install and activate the plugin on your WordPress website and you're ready to use it!
You can run your build in monitoring mode using npm run start, and your code will be automatically compiled every time you change the code and save it.
The actual block uses the Settings sidebar of the Block Editor and other features provided by WordPress to create a rich user experience. Also, since the block actually has two versions - edit and save - you also need to think about how to organize your code to avoid duplication of code.
But hopefully this helps to remove the mystery of the overall process of creating WordPress blocks. This is indeed a new era of WordPress development. Learning new ways of doing things is difficult, but I look forward to seeing it develop. Tools like @wordpress/create-block help, but even then it's nice to know what it's doing and why.
Will the content we introduce here change? Very likely! But at least you have a baseline for reference, as we continue to focus on the maturity of WordPress blocks, including best practices for making them.
Again, my goal is to plan an efficient path to enter block development in this fast-growing era, and WordPress documents are a little hard to keep up. Here are some resources I used to organize these contents:
The above is the detailed content of Getting Started With WordPress Block Development. For more information, please follow other related articles on the PHP Chinese website!