WordPress 无代码主题开发:基于 FSE 和 block.json 的进阶实践
大家好,今天我们来深入探讨如何利用 WordPress 的 Full Site Editing (FSE) 和 block.json
打造一个无需编写 PHP 代码的主题。这并非完全字面意义上的“无代码”,而是指将主题逻辑主要集中在区块配置和模板定制上,最大限度地减少对传统 PHP 主题文件的依赖。
1. FSE 和 block.json
概述
Full Site Editing (FSE) 是 WordPress 5.9 引入的一项重大更新,它允许用户使用区块编辑器来构建整个网站,包括头部、页脚、文章模板等。FSE 的核心思想是将网站的各个部分都视为可编辑的区块,从而实现高度的可定制性和灵活性。
block.json
文件是区块元数据的核心载体。它定义了区块的名称、标题、描述、属性、样式、脚本和样式依赖等信息。通过 block.json
,我们可以以声明式的方式定义区块的行为和外观,而无需编写大量的 JavaScript 或 CSS 代码。
2. 准备工作
在开始之前,我们需要确保满足以下条件:
- WordPress 版本: 确保你的 WordPress 版本为 5.9 或更高。
- 主题支持: 激活一个支持 FSE 的主题,例如 Twenty Twenty-Two 或 Twenty Twenty-Three。或者,我们可以创建一个基本的主题结构,并声明对 FSE 的支持。
- 开发环境: 搭建一个本地 WordPress 开发环境,方便测试和调试。
3. 创建一个基本的 FSE 主题
要创建一个最简 FSE 主题,只需包含以下文件:
style.css
: 包含主题的基本信息。theme.json
: 定义主题的全局样式和设置。index.php
(可选): 在 FSE 完全接管之前,用于处理一些兼容性问题。
3.1 style.css
/*
Theme Name: My FSE Theme
Theme URI: https://example.com/my-fse-theme/
Description: A basic FSE theme.
Version: 1.0.0
Author: Your Name
Author URI: https://example.com/
License: GPL v2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: my-fse-theme
*/
3.2 theme.json
{
"version": 2,
"settings": {
"appearanceTools": true,
"color": {
"palette": [
{
"slug": "primary",
"color": "#007bff",
"name": "Primary"
},
{
"slug": "secondary",
"color": "#6c757d",
"name": "Secondary"
},
{
"slug": "light",
"color": "#f8f9fa",
"name": "Light"
},
{
"slug": "dark",
"color": "#343a40",
"name": "Dark"
}
],
"gradients": [
{
"slug": "vivid-cyan-blue-to-vivid-purple",
"gradient": "linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)",
"name": "Vivid Cyan Blue to Vivid Purple"
}
],
"custom": true,
"link": true
},
"typography": {
"fontFamilies": [
{
"fontFamily": "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif",
"slug": "system-font",
"name": "System Font"
}
],
"fontSizes": [
{
"slug": "small",
"size": "14px",
"name": "Small"
},
{
"slug": "medium",
"size": "16px",
"name": "Medium"
},
{
"slug": "large",
"size": "18px",
"name": "Large"
}
],
"custom": true
},
"layout": {
"contentSize": "900px",
"wideSize": "1200px"
}
},
"styles": {
"elements": {
"link": {
"color": {
"text": "var(--wp--preset--color--primary)"
}
}
}
}
}
这个 theme.json
文件定义了主题的颜色方案、字体、布局等全局设置。 appearanceTools
: true 开启了许多额外的外观控制选项。
3.3 index.php
(可选)
<?php
/**
* The main template file
*
* This is the most generic template file in a WordPress theme
* and one of the two required files for a theme (the other being style.css).
* It is used to display a page when nothing more specific matches a query.
* E.g., it puts together the home page when no home.php file exists.
*
* @link https://developer.wordpress.org/themes/basics/template-hierarchy/
*
* @package My_FSE_Theme
*/
get_header();
?>
<main id="primary" class="site-main">
<?php
if ( have_posts() ) {
// Load posts loop.
while ( have_posts() ) {
the_post();
get_template_part( 'template-parts/content/content' );
}
// Previous/next page navigation.
the_posts_navigation();
} else {
// If no content, include the "No posts found" template.
get_template_part( 'template-parts/content/content-none' );
}
?>
</main><!-- #primary -->
<?php
get_footer();
虽然 FSE 允许我们通过区块编辑器创建模板,但 index.php
仍然可以作为后备方案,或者用于处理一些高级逻辑。
4. 创建区块模板
FSE 的强大之处在于可以通过区块编辑器创建和定制模板。我们可以创建以下类型的模板:
- index.html: 默认的站点模板。
- home.html: 用于显示博客首页。
- single.html: 用于显示单个文章。
- page.html: 用于显示页面。
- archive.html: 用于显示文章归档。
- search.html: 用于显示搜索结果。
- 404.html: 用于显示 404 错误页面。
4.1 创建 index.html
- 在 WordPress 后台,进入“外观” -> “编辑器”。
- 点击站点图标,选择“模板” -> “添加新模板”。
- 选择 "index" 作为模板类型,并点击 "创建"。
- 使用区块编辑器构建你的站点模板。例如,你可以添加一个头部区块、一个文章区块循环、和一个页脚区块。
- 保存模板。
一个简单的 index.html
模板可能如下所示:
<!-- wp:template-part {"slug":"header","tagName":"header"} -->
<header id="masthead" class="wp-block-template-part has-no-title">
<!-- wp:site-title /-->
<!-- wp:navigation {"isResponsive":true,"openSubmenusOnClick":false,"showSubmenuIcon":true,"useSeparators":true} /-->
</header>
<!-- /wp:template-part -->
<!-- wp:group {"tagName":"main","layout":{"inherit":true}} -->
<main class="wp-block-group">
<!-- wp:query {"query":{"perPage":10,"pages":0,"offset":0,"postType":"post","inherit":true},"displayLayout":{"columns":3}} -->
<div class="wp-block-query">
<!-- wp:post-template -->
<!-- wp:post-featured-image {"isLink":true} /-->
<!-- wp:post-title {"isLink":true} /-->
<!-- wp:post-excerpt /-->
<!-- /wp:post-template -->
<!-- wp:query-pagination -->
<!-- wp:query-pagination-previous /-->
<!-- wp:query-pagination-numbers /-->
<!-- wp:query-pagination-next /-->
<!-- /wp:query-pagination -->
</div>
<!-- /wp:query -->
</main>
<!-- /wp:group -->
<!-- wp:template-part {"slug":"footer","tagName":"footer"} -->
<footer class="wp-block-template-part has-no-title">
<!-- wp:paragraph {"align":"center"} -->
<p class="has-text-align-center">Powered by WordPress</p>
<!-- /wp:paragraph -->
</footer>
<!-- /wp:template-part -->
注意:这些模板实际上是以 HTML 注释的形式存储在数据库中的。
4.2 创建模板部件 (Template Parts)
模板部件是可以在多个模板中重复使用的区块集合。常见的模板部件包括头部、页脚、侧边栏等。
- 在 WordPress 后台,进入“外观” -> “编辑器”。
- 点击站点图标,选择“模板部件” -> “添加新模板部件”。
- 为模板部件指定一个名称和区域(例如 "header" 或 "footer"),并点击 "创建"。
- 使用区块编辑器构建你的模板部件。
- 保存模板部件。
5. 创建自定义区块 (Custom Blocks)
虽然 WordPress 已经提供了大量的内置区块,但有时我们需要创建自定义区块来满足特定的需求。 我们可以使用 block.json
来定义自定义区块,而无需编写复杂的 JavaScript 代码 (对于简单的静态区块)。
5.1 创建区块目录
在你的主题目录下创建一个 blocks
目录,用于存放所有的自定义区块。
5.2 创建区块文件
在 blocks
目录下,为你的区块创建一个单独的目录,例如 blocks/my-custom-block/
。 在这个目录下,创建以下文件:
block.json
: 区块的元数据定义。index.php
: 区块的渲染逻辑(如果需要)。
5.3 block.json
示例
{
"name": "my-fse-theme/my-custom-block",
"title": "My Custom Block",
"description": "A simple block for displaying custom content.",
"category": "common",
"icon": "smiley",
"keywords": [ "custom", "block" ],
"attributes": {
"content": {
"type": "string",
"default": "Hello, world!"
},
"alignment": {
"type": "string",
"enum": [ "left", "center", "right" ],
"default": "center"
}
},
"supports": {
"align": true,
"html": false
},
"textdomain": "my-fse-theme",
"editorScript": "file:./index.js",
"style": "file:./style.css",
"viewScript": "file:./view.js"
}
这个 block.json
文件定义了一个名为 my-fse-theme/my-custom-block
的区块,它具有以下属性:
name
: 区块的唯一名称。title
: 区块的显示名称。description
: 区块的描述。category
: 区块所属的类别。icon
: 区块的图标。keywords
: 区块的关键词。attributes
: 区块的属性,例如content
和alignment
。supports
: 区块支持的功能,例如对齐方式和 HTML 编辑。textdomain
: 区块的文本域,用于国际化。editorScript
: 编辑器环境下的 JS 文件style
: 编辑器和前端通用的 CSS 样式文件viewScript
: 前端 JS 文件
5.4 index.php
示例
<?php
/**
* Registers the block using the metadata loaded from the `block.json` file.
* Behind the scenes, it registers also all assets so they can be enqueued
* through the block editor in the corresponding context.
*
* @see https://developer.wordpress.org/reference/functions/register_block_type/
*/
function create_block_my_custom_block_block_init() {
register_block_type( __DIR__ );
}
add_action( 'init', 'create_block_my_custom_block_block_init' );
这个 index.php
文件注册了区块。 register_block_type( __DIR__ )
函数会自动加载 block.json
文件,并根据其中的元数据注册区块。
5.5 无需 JavaScript 的静态区块
如果你的区块只是简单地显示一些静态内容,你可以完全省略 editorScript
和 viewScript
,并在 index.php
中使用 render_callback
来定义区块的渲染逻辑。
<?php
/**
* Registers the block using the metadata loaded from the `block.json` file.
* Behind the scenes, it registers also all assets so they can be enqueued
* through the block editor in the corresponding context.
*
* @see https://developer.wordpress.org/reference/functions/register_block_type/
*/
function create_block_my_custom_block_block_init() {
register_block_type( __DIR__, [
'render_callback' => 'render_my_custom_block'
] );
}
add_action( 'init', 'create_block_my_custom_block_block_init' );
function render_my_custom_block( $attributes, $content, $block ) {
$content = isset( $attributes['content'] ) ? $attributes['content'] : 'Hello, World!';
$alignment = isset( $attributes['alignment'] ) ? $attributes['alignment'] : 'center';
return '<div style="text-align: ' . esc_attr( $alignment ) . ';">' . esc_html( $content ) . '</div>';
}
在这个例子中,render_my_custom_block
函数根据区块的属性生成 HTML 代码。 esc_attr
和 esc_html
函数用于对属性值进行转义,以防止安全漏洞。
5.6 使用 JavaScript 的动态区块
如果你的区块需要更复杂的交互或动态行为,你需要使用 JavaScript 来定义区块的编辑器界面和前端行为。
-
创建
index.js
(编辑器脚本): 这个文件包含区块的编辑器逻辑,例如自定义控件、属性处理等。import { registerBlockType } from '@wordpress/blocks'; import { useBlockProps, RichText, AlignmentToolbar, BlockControls } from '@wordpress/block-editor'; import { __ } from '@wordpress/i18n'; registerBlockType( 'my-fse-theme/my-custom-block', { edit: ( props ) => { const { attributes, setAttributes } = props; const { content, alignment } = attributes; const onChangeContent = ( newContent ) => { setAttributes( { content: newContent } ); }; const onChangeAlignment = ( newAlignment ) => { setAttributes( { alignment: newAlignment === undefined ? 'center' : newAlignment } ); }; return ( <div { ...useBlockProps() }> <BlockControls> <AlignmentToolbar value={ alignment } onChange={ onChangeAlignment } /> </BlockControls> <RichText tagName="p" className="my-custom-block-text" placeholder={ __( 'Enter your text...', 'my-fse-theme' ) } value={ content } onChange={ onChangeContent } style={ { textAlign: alignment } } /> </div> ); }, save: ( props ) => { const { attributes } = props; const { content, alignment } = attributes; return ( <div { ...useBlockProps.save() }> <p style={ { textAlign: alignment } }>{ content }</p> </div> ); }, } );
-
创建
view.js
(前端脚本): 这个文件包含区块的前端逻辑,例如动画效果、事件处理等。通常来说,对于静态区块,这个文件可以为空。// This file can be empty if your block doesn't require any front-end JavaScript.
-
配置
block.json
: 在block.json
文件中,指定editorScript
和viewScript
的路径。{ "name": "my-fse-theme/my-custom-block", "title": "My Custom Block", "description": "A simple block for displaying custom content.", "category": "common", "icon": "smiley", "keywords": [ "custom", "block" ], "attributes": { "content": { "type": "string", "default": "Hello, world!" }, "alignment": { "type": "string", "enum": [ "left", "center", "right" ], "default": "center" } }, "supports": { "align": true, "html": false }, "textdomain": "my-fse-theme", "editorScript": "file:./index.js", "viewScript": "file:./view.js" }
-
构建 JavaScript 文件: 你需要使用 Webpack 或其他构建工具将 JavaScript 文件打包成浏览器可以识别的格式。WordPress 提供了
@wordpress/scripts
包,可以简化构建过程。-
安装
@wordpress/scripts
:npm install @wordpress/scripts --save-dev
-
在
package.json
文件中添加构建脚本:{ "name": "my-fse-theme", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "build": "wp-scripts build", "start": "wp-scripts start" }, "keywords": [], "author": "", "license": "ISC", "devDependencies": { "@wordpress/scripts": "^26.7.0" }, "dependencies": { "@wordpress/block-editor": "^12.10.0", "@wordpress/blocks": "^11.20.0", "@wordpress/i18n": "^4.4.0" } }
-
运行构建脚本:
npm run build
这将在你的区块目录下生成
build
目录,其中包含打包后的 JavaScript 文件。
-
-
Enqueue 脚本和样式: 确保在你的主题中 Enqueue 区块的脚本和样式。WordPress 会自动处理这一点,只要
editorScript
和style
属性在block.json
中正确设置。
6. 全局样式与 theme.json
theme.json
文件是 FSE 主题的核心配置文件。它允许你定义主题的全局样式、设置和特性。
6.1 全局样式 (Styles)
styles
属性用于定义主题的全局样式,例如颜色、字体、间距等。
{
"version": 2,
"styles": {
"elements": {
"link": {
"color": {
"text": "var(--wp--preset--color--primary)"
}
},
"heading": {
"color": {
"text": "var(--wp--preset--color--dark)"
},
"typography": {
"fontFamily": "var(--wp--preset--font-family--system-font)"
}
}
},
"blocks": {
"core/heading": {
"color": {
"text": "var(--wp--preset--color--secondary)"
}
}
}
}
}
elements
: 用于设置 HTML 元素(例如link
、heading
)的样式。blocks
: 用于设置特定区块的样式。
6.2 全局设置 (Settings)
settings
属性用于定义主题的全局设置,例如颜色调色板、字体大小、布局等。
{
"version": 2,
"settings": {
"appearanceTools": true,
"color": {
"palette": [
{
"slug": "primary",
"color": "#007bff",
"name": "Primary"
},
{
"slug": "secondary",
"color": "#6c757d",
"name": "Secondary"
}
],
"gradients": [],
"custom": true,
"link": true
},
"typography": {
"fontFamilies": [],
"fontSizes": [],
"custom": true
},
"layout": {
"contentSize": "900px",
"wideSize": "1200px"
}
}
}
appearanceTools
: 启用或禁用主题外观工具。color
: 定义颜色调色板、渐变等。typography
: 定义字体系列、字体大小等。layout
: 定义内容区域的宽度。
7. 高级技巧
-
模式 (Patterns): 模式是预定义的区块布局,可以方便用户快速创建复杂的页面结构。你可以使用区块编辑器创建模式,并将它们导出为 JSON 文件,然后将这些文件放置在主题的
patterns
目录下。 -
模板层叠 (Template Hierarchy): FSE 仍然支持传统的 WordPress 模板层叠。这意味着你可以使用 PHP 文件来覆盖 FSE 模板。例如,你可以创建一个
single.php
文件来覆盖single.html
模板。 -
条件逻辑: 虽然 FSE 旨在减少对 PHP 代码的依赖,但在某些情况下,你可能需要使用 PHP 代码来实现条件逻辑。你可以使用
render_callback
函数或创建自定义区块来实现这一点。 -
主题继承: 你可以创建一个子主题,并继承父主题的 FSE 模板和区块。这可以方便你定制现有主题,而无需从头开始。
8. 常见问题与解决方案
问题 | 解决方案 |
---|---|
区块未显示在编辑器中 | 检查 block.json 文件是否正确配置,并确保区块已正确注册。 检查 index.php 文件中的注册函数是否被正确调用. 检查 JavaScript 构建过程是否成功完成,并且生成的 JavaScript 文件已正确 Enqueue。 |
区块样式未生效 | 检查 style.css 文件是否已正确 Enqueue。 检查 CSS 选择器是否正确。 检查 theme.json 文件中的全局样式是否正确配置。 |
JavaScript 代码未执行 | 检查 editorScript 和 viewScript 是否已正确配置。 检查 JavaScript 代码是否存在错误。 确保 JavaScript 文件已正确 Enqueue。 |
模板未生效 | 检查模板文件是否已正确命名。 检查模板文件是否已正确放置在主题目录下。 清除 WordPress 缓存。 |
theme.json 配置无效 |
检查 theme.json 文件的语法是否正确。 检查 WordPress 版本是否支持你使用的 theme.json 功能。 |
模板编辑器无法保存更改 | 检查服务器的 max_input_vars 设置是否足够大。 一些主机提供商可能会限制允许的输入变量数量,这可能会导致模板编辑器无法保存更改。 |
模板部件 (Template Parts) 不显示 | 确保在模板部件中添加了内容。 确保模板部件已正确分配到区域。 检查模板部件是否已正确 Enqueue。 |
9. 小结
通过 FSE 和 block.json
,我们可以构建高度可定制的 WordPress 主题,而无需编写大量的 PHP 代码。 这种方法使主题开发更加灵活和高效,并使更多的人能够参与到 WordPress 主题的定制中来。 当然,要完全实现“无代码”可能仍然有挑战,但我们可以通过充分利用区块配置和模板定制,最大限度地减少对传统 PHP 主题文件的依赖。 拥抱 FSE 和 block.json
,将开启 WordPress 主题开发的新纪元。
让主题开发更友好
使用 FSE 和 block.json
可以简化主题开发,降低了技术门槛。