WP DEVELOP

EP217. “用 block.json 迁移 Footer:register_block_type_from_metadata”

首页 WordPress 开发课程 现代化 BLOCK 开发标准做法 · EP217
约 17 分钟· #EP217#现代化 BLOCK 开发标准做法
🔒 登录后可标记已读

先复制一份 Block Theme 主题文件夹(fictional-block-themefictional-clean-blocks),保留旧版本作参照,在新副本里用官方标准做法重新实现最简单的 Footer Block。核心变化:所有 Block 相关文件统一放进 src/{block名}/ 子文件夹(@wordpress/scripts 会自动扫描 src/ 下每一个带 block.json 的子文件夹,不需要手动列举),每个 Block 文件夹里固定放 block.json(声明名字/标题/脚本/渲染文件路径)、render.php(PHP 渲染内容,取代上一章手写的渲染回调方法)、index.js(编辑器脚本,用 registerBlockType + 读取 block.jsonmetadata)。PHP 端注册也从手写一整套「注册脚本 + 注册 Block 类型」的样板代码,精简成一行 register_block_type_from_metadata()


涉及文件

  • wp-content/themes/fictional-clean-blocks/(新建,复制自 fictional-block-theme
  • wp-content/themes/fictional-clean-blocks/style.css (修改,改主题名)
  • wp-content/themes/fictional-clean-blocks/functions.php (修改,注释掉旧的 footer 占位 Block,新增一行现代注册代码)
  • wp-content/themes/fictional-clean-blocks/src/footer/block.json (新建)
  • wp-content/themes/fictional-clean-blocks/src/footer/render.php (新建,从旧的 our-blocks/footer.php 搬运内容)
  • wp-content/themes/fictional-clean-blocks/src/footer/index.js (新建)
  • wp-content/themes/fictional-clean-blocks/package.json (修改,新增 blocks 脚本)

代码实现

src/footer/block.json(新建)

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "ourblocktheme/footer",
  "title": "Fictional University Footer",
  "editorScript": "file:./index.js",
  "render": "file:./render.php"
}

src/footer/render.php(新建,原样搬运旧的 our-blocks/footer.php 内容)

<footer class="site-footer">
    <div class="site-footer__inner container container--narrow">
      <div class="group">
        <div class="site-footer__col-one">
          <h1 class="school-logo-text school-logo-text--alt-color"><a href="<?php echo site_url() ?>"><strong>Fictional</strong> University</a></h1>
          <p><a class="site-footer__link" href="#">555.555.5555</a></p>
        </div>
        <!-- ...其余页脚 HTML 结构不变... -->
      </div>
    </div>
  </footer>

src/footer/index.js(新建)

import { registerBlockType } from "@wordpress/blocks"
import metadata from "./block.json"

function Edit() {
  return <div>Hello, I am the footer block in the editor.</div>
}

registerBlockType(metadata.name, {
  edit: Edit
})

functions.php:注释掉旧的占位 Block,新增一行 register_block_type_from_metadata()

// new PlaceholderBlock("footer");

// Register our new blocks
function our_new_blocks() {
  register_block_type_from_metadata(__DIR__ . '/build/footer');
}

add_action('init', 'our_new_blocks');

package.json:新增 blocks 脚本(不指定入口文件,靠自动扫描)

"scripts": {
  "start": "wp-scripts start src/index.js our-blocks/banner.js our-blocks/genericheading.js our-blocks/genericbutton.js our-blocks/slideshow our-blocks/slide",
  "blocks": "wp-scripts start --experimental-modules",
  "dev": "wp-scripts start",
  "devFast": "wp-scripts start",
  "test": "echo \"Error: no test specified\" && exit 1"
}

关键改动点:

  • 先复制整个主题文件夹再动手改,保留旧版本对照:这一章的转换过程会逐个 Block 迁移,随时可能想回头参考旧写法是怎么实现同样功能的,留一份没有改动过的原版更安全
  • src/{block名}/ 是这套现代做法的核心目录约定:只要 Block 相关文件放在 src/ 目录下、且这个子文件夹里有一份 block.json@wordpress/scripts 就能自动识别、自动处理构建——不再需要像上一章那样,每新增一个 Block 就要去 package.json 手动追加一段入口路径
  • block.json 集中声明所有元信息
    • $schema:给 IDE/编辑器提供字段提示,不影响功能
    • apiVersion: 3:写这门课时最新的 Block API 版本
    • name:必须跟原本命名空间/Block 名保持一致(ourblocktheme/footer),这样前台/编辑器的行为才能跟旧版本一一对应
    • editorScript: "file:./index.js":声明编辑器要加载的 JS 文件,用相对路径 file:./ 前缀
    • render: "file:./render.php"这是取代上一章 render_callback 方法的新写法——不用再手写一个 PHP 方法去 ob_start()/require/ob_get_clean(),只需要在 block.json 里指定一个 PHP 文件路径,WordPress 会自动去渲染这个文件的输出作为 Block 的最终内容
  • PHP 端注册精简成一行 register_block_type_from_metadata(__DIR__ . '/build/footer'):这个 WordPress 内建函数直接读取指定目录下的 block.json,自动完成「注册脚本、注册样式、绑定渲染文件」这一整套原本要手写的样板代码——传入的路径指向编译产物所在的 build/footer 目录(不是 src/footer),因为 index.js 要经过转译才能在浏览器里运行
  • index.js 的写法import metadata from "./block.json" 直接把 block.json 当模块导入,取 metadata.name 当作 registerBlockType() 的第一个参数——这样 Block 名字只需要在 block.json 里维护一份,不需要在 JS 里重复写一遍容易脱节的字符串
  • 先写最简单的占位 Edit 函数<div>Hello, I am the footer block in the editor.</div>)验证整条链路能跑通,真正的编辑器 JSX 内容留到下一讲
  • 新增独立的 blocks 脚本,跟原本的 start 脚本并行运行、互不干扰"blocks": "wp-scripts start --experimental-modules"——不传任何入口文件路径,让它用「自动扫描 src/ 下所有带 block.json 的子文件夹」这个默认行为;写这门课时这个自动扫描能力还需要加 --experimental-modules 这个参数才能启用
  • 旧的 start 脚本暂时保持原样不变:因为还没迁移完的 Block(Banner、标题、按钮、幻灯片等)依然需要旧脚本继续处理,新旧两套构建任务分别在两个终端窗口同时运行——后面的讲座会讲怎么把两套任务合并成一条命令
  • 验证方式:先看 build/footer/ 目录下是否真的生成了对应的编译产物(证明自动扫描生效),再看前台页脚是否正确显示(证明 render.php 生效),最后看编辑器里插入这个 Block 时是否显示占位文字而不是报错(证明 index.jsregisterBlockType 生效)

Hook / Function 速查

名称类型用途
block.jsonrender 属性Block 元数据字段声明一个 PHP 文件,WordPress 自动渲染它的输出作为 Block 内容,取代手写 render_callback
register_block_type_from_metadata($目录路径)WP 内建 function读取指定目录下的 block.json,一次性完成脚本/样式注册和渲染绑定
import metadata from "./block.json"JS 模块导入直接把 block.json 当模块使用,metadata.name 取代手写字符串
wp-scripts start --experimental-modules命令行参数启用自动扫描 src/ 下所有 Block 子文件夹的能力(写这门课时仍是实验性功能)

常见坑

  • register_block_type_from_metadata() 传入的路径指向 src/ 而不是编译产物所在的 build/——JS 还没经过转译,注册的脚本文件不存在
  • block.json 里的 name 跟旧版本对不上——前台渲染出的 HTML 结构没变,但 Block 类型名字变了,会被 Gutenberg 当成完全不同的 Block,导致已有内容里的旧引用失效
  • 忘记新旧两套构建任务(startblocks)要同时运行——只跑其中一个,另一批还没迁移完的 Block 会因为缺少编译产物而报错

延伸 / 后续讲座会用到

下一讲继续完善 Footer Block 的编辑器 JSX 内容,并把这套「多入口构建脚本要分开跑」的问题一并解决。


Sources

Udemy:

  • Become a WordPress Developer: Unlocking Power With Code — Section 29, EP217