WP DEVELOP

EP136. “引入 JSX 与 @wordpress/scripts 构建工具”

首页 WordPress 开发课程 插件开发 CH2:插件里的 JS · EP136
约 12 分钟· #EP136#插件开发 CH2:插件里的 JS
🔒 登录后可标记已读

wp.element.createElement() 手写嵌套 HTML 结构太啰嗦,这一讲引入 JSX——一种写起来几乎跟 HTML 一样、但浏览器本身不认识的语法,需要一个「中间工具」把它编译成浏览器能执行的 createElement() 调用。这个中间工具就是 WordPress 官方的 @wordpress/scripts npm 包:约定一个固定的目录结构(src/index.js 写源码,编译产物自动输出到 build/),配置几乎为零。同时约定了源码文件夹和产物文件夹的分工、npm run start(持续监听自动编译)和 npm run build(编译一次)两个命令,以及 JSX 里「只能有一个根节点」的规则(用 React Fragment <>...</> 包裹多个并列元素而不引入多余的 <div>)。


涉及文件

  • wp-content/plugins/are-you-paying-attention/package.json (新建,npm init -y 生成后手动补 scripts)
  • wp-content/plugins/are-you-paying-attention/src/index.js (新建,取代 test.js
  • wp-content/plugins/are-you-paying-attention/build/index.js (编译产物,由 @wordpress/scripts 自动生成,不手写)
  • wp-content/plugins/are-you-paying-attention/index.php (修改,脚本加载路径指向 build 产物)

代码实现

安装 Node.js 与 @wordpress/scripts(终端命令)

# 检查是否已装 Node
node --version

# 在插件文件夹里初始化 package.json
npm init -y

# 安装 WordPress 官方的构建工具包
npm install @wordpress/scripts --save-dev

package.json:新增 build/start 两个命令

{
  "name": "are-you-paying-attention",
  "version": "1.0.0",
  "description": "",
  "main": "test.js",
  "scripts": {
    "build": "wp-scripts build",
    "start": "wp-scripts start",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "@wordpress/scripts": "^15.0.1"
  }
}

src/index.js:改用 JSX 语法

wp.blocks.registerBlockType("ourplugin/are-you-paying-attention", {
  title: "Are You Paying Attention?",
  icon: "smiley",
  category: "common",
  edit: function () {
    return (
      <div>
        <p>Hello, this is a paragraph.</p>
        <h4>Hi there.</h4>
      </div>
    )
  },
  save: function () {
    return (
      <>
        <h3>H3 on the frontend.</h3>
        <h5>H5 on the frontend.</h5>
      </>
    )
  }
})

index.php:脚本加载路径改指向 build/ 目录下编译好的文件

wp_enqueue_script('ournewblocktype', plugin_dir_url(__FILE__) . 'build/index.js', array('wp-blocks', 'wp-element'));

关键改动点:

  • npm init -y 生成 package.json,相当于给项目建一份「依赖清单」;-y 表示跳过交互式提问,全部用默认值
  • @wordpress/scripts(简称 wp-scripts)是官方维护的构建工具集合,约定优于配置:只要源码放在固定的 src/ 目录下(入口文件必须叫 index.js),编译产物就会自动输出到固定的 build/ 目录,不需要自己写 Webpack 配置文件
  • wp-scripts build:跑一次性编译;wp-scripts start:持续监听 src/ 目录变化,每次保存源文件自动重新编译——开发阶段用 start,最终发布前跑一次 build 定稿
  • 编译产物 build/index.js 是给浏览器执行用的、经过压缩转换的代码,不是给人读的——源码里的 JSX 标签在产物里会被转换回 createElement() 调用形式
  • PHP 里 wp_enqueue_script() 引用的路径要相应地改成指向 build/index.js(浏览器真正加载、执行的是编译产物,不是 src/ 里的原始 JSX 源码,浏览器根本无法直接理解 JSX
  • VS Code 需要手动把 .js 文件关联到 JavaScript React 语法高亮(Settings 里搜 files.associations 加一条 "*.js": "javascriptreact"),这样在 .js 文件里输入 HTML 标签时才会有自动补全提示——这只是编辑器体验优化,不影响实际编译结果
  • JSX 的核心限制:一个函数只能返回一个根节点。如果要并列多个元素又不想凭空多包一层无意义的 <div>,可以用 React Fragment 空标签 <>...</> 包裹——它在最终渲染结果里不会生成任何真实的 DOM 元素
  • 📌 修改已注册 Block 的 save 函数结构后,页面里已经存在的旧 Block 实例会报「非预期或无效内容」的错误——这是正常现象(编辑器发现存进数据库的旧 HTML 跟当前 save 函数会生成的新 HTML 对不上),处理方式是先删除旧实例、重新插入一个新的;这个问题的根本原因和更稳妥的处理方法会在后面讲座展开

Hook / Function 速查

名称类型用途
npm init -ynpm 命令快速生成默认的 package.json
npm install <pkg> --save-devnpm 命令安装一个开发依赖包
wp-scripts build / wp-scripts start@wordpress/scripts 提供的命令一次性编译 / 持续监听自动编译
React Fragment <>...</>JSX 语法包裹多个并列元素、不产生额外真实 DOM 节点

常见坑

  • JSX 里返回多个并列的根级元素(不用 <div> 或 Fragment 包裹)——会直接编译报错,「只能有一个根节点」是硬性规则
  • 改了 src/index.js 之后忘记确认 npm run start 是否还在运行——没有监听进程在跑的话build/ 里的产物不会自动更新,浏览器加载的还是旧代码,容易让人误以为改动没生效
  • PHP 里 wp_enqueue_script() 的路径忘记从 test.js 改成 build/index.js——两者共存时容易搞混到底加载的是哪个版本
  • 修改了已发布 Block 的 HTML 结构后,直接以为旧内容会自动兼容——编辑器会明确报错提示内容不匹配,需要手动处理(删除重插,或后续学到的更规范做法)

延伸 / 后续讲座会用到

下一讲开始让 Block 真正具备交互性:学习 attributes(Block 自己的数据存储机制)和 RichText 等编辑器组件,做一个用户可以直接在编辑器里输入内容、并且内容会被保存下来的字段。


Sources

Udemy:

  • Become a WordPress Developer: Unlocking Power With Code — Section 24, EP136