博客

停止重建每个WordPress网站

一份实用的、逐项反驳的指南,教你使用 theme.json 和块模式来标准化 WordPress 构建——而不会让每个客户网站千篇一律。

摘要

大多数机构都从空白主题开始构建每个 WordPress 网站,即使共享基础本可以缩短数周时间。本文认为,theme.json、块模式和动态块可以在保留每个客户独特设计的同时,让你标准化结构层。它直接回应了阻止团队改变的五个反对意见:“我们有不同的客户”、“自定义块太贵”、“编辑器令人困惑”、“我们会失去钩子和过滤器”、“FSE 尚未准备好用于生产”。每个反对意见都得到了一个实用的反论和一个你可以逐步采用的具体模式。回报是一个可重复的构建流程,同时仍然在适当之处尊重定制工作。警告:不承诺一键重置按钮。

你的客户网站中有多少行代码是共享的?不是版权行——是真正的代码。如果答案是“几乎没有”,你已经感受到了痛苦:同一个英雄版块第九次重建,同一个团队网格标记从一个项目复制到下一个项目,同一些预处理调整在六七个主题中交叉引用。你也听见过这样的辩护:“每个客户都有不同的需求。”没错。但每个人都得出的结论——每个网站都需要一个定制的基础——是错误的。WordPress 生态系统现在提供了一种方法,可以在不标准化设计的情况下标准化结构部分:用 theme.json 定义设计令牌,用块模式处理重复布局,用动态块处理少数需要真正服务端逻辑的功能。本文要讨论的正是那些阻止机构迈出这一步的反对意见,以及当你反驳它们时真正有效的方法。

“但每个客户都不同”的反对意见

基本原则:标准化基础,而不是表面。将结构放在共享库中的原因恰恰是为了让视觉层保持自由。theme.json 文件不是设计——它是一组设计令牌。颜色、间距和排版是值,而不是标记。这就是关键转变:你可以共享标记,而每个站点的 theme.json 则让网站呈现出完全不同的品牌外观。

以两个客户为例:一家律师事务所和一家户外零售商。他们的设计语言相差甚远。但两者都需要英雄版块、客户评价网格和行动号召区域。与其为每个客户重建标记,不如维护三个块模式,让每个客户的 theme.json 定义颜色、字体和间距。结构保持不变;设计令牌将其从一个品牌变成另一个品牌。当明年春天零售商改变其调色板时,你只需编辑他们网站上的一个文件——而不是六个模板中的标记。

实际上,这意味着你的团队以代码的形式创建模式,将它们注册到共享插件中,并让每个客户站点的 theme.json 来处理外观。模式中的类名成为你的架构;值成为变量。你甚至可以更进一步,扩展 theme.json 以包含针对文章类型或插件输出的自定义设置,但在某种程度上,你构建的是一个配置界面,而不是一个网站——这个陷阱在我们关于扩展 theme.json 的探讨中有讨论。保持共享层精简:它只应包含跨客户重复出现的内容。当你发现自己添加一个设置“以防将来有人需要”时,你就创建了一个维护成本高于节省成本的抽象。

当你开始一个新客户时,前 30 分钟应该是:克隆共享模式插件,创建一个包含客户调色板和字体比例的新的 theme.json,并注册他们的标志和页脚。这不是自定义构建;这是一项配置任务。剩下的客户特定工作则投入到内容、结构和任何真正定制的功能中。这就是从零开始建造每一栋房屋与拥有一套预制平面图(你可以重新粉刷和贴墙纸)之间的区别。这个类比并不严格,但原则成立:你越是把内容推入 theme.json 的值,就越不需要碰标记。

最简单的胜利之一就是真正了解块模式的工作原理。模式只是带有预定义内容和样式的块的集合。你可以将任何块配置保存为模式,然后客户就可以插入它,而无需知道它是如何构建的。这意味着模式成为非技术用户的‘入口点’。当你的团队在代码中维护底层模式时,客户会得到一个一致的库,而无需触碰一个 PHP 标签。

现在,我要反复强调的告诫是:不要过度集中。一个为每个可想象的细微差别都提供设置的 theme.json 是一个维护泥潭。共享模式应该是有主见的,而不是万能的。如果客户需要一个完全不同的布局——比如一个带有大型精选网格的杂志首页——它们可能不适合你的标准模式库。那没关系。标准化意味着你在 80% 相似的项目上获胜,而不是强制每个网站都千篇一律。

“自定义块会超出预算”的反对意见

这里有一个听起来很无聊但能省钱的反原则:大多数你认为需要自定义块的东西其实并不需要。核心块加模式就能覆盖绝大多数布局。自定义块是最后的手段,而不是第一选择。

经典例子是团队网格。如果它是一次性的,使用核心的“列”和“组”块,让客户手动放入头像。如果有三个客户要求相同网格,且都带有相同的“名字下方社交链接”结构,那么你就有资格创建一个块模式了。当这个模式开始积累新选项——悬停效果、排序、评分星星——模式会变成一个难以管理的杂物袋,这时候就该编写自定义块了。最伤预算的错误是一接到请求就直接跳到自定义块。

一个更隐蔽的场景:客户要求一个“案例研究轮播”。第一反应往往是“我需要一个轮播块”。但他们真的需要轮播吗?也许他们需要一个水平滚动的文章组,核心块用“组”块加一些 CSS 就能处理。或者他们需要一个最近案例研究的动态列表,那是一个查询 CPT 的动态块。问题不在于“客户想要什么功能?”,而在于“它依赖什么数据?”。如果数据是静态的、客户可编辑的,那么模式就够了。如果数据来自数据库查询,那么动态块是合理的。如果数据需要从 API 实时更新,那么你需要的可能是一个 REST API 集成——那就跨入了不同类型的构建。

当你确实要构建一个块时,block.json 是你的朋友。它是属性、脚本和样式的唯一来源,这使得块可以跨项目移植。它还允许你清晰地声明依赖项和翻译,这在跨多个客户站点分发库时至关重要。对于依赖实时数据的内容,动态块在服务器上渲染,因此你不需要在每次页面视图时都提供 JavaScript 包。而且如果你的块演化了,你可以优雅地处理弃用,使现有内容不会损坏——我们的块弃用指南详细介绍了确切的模式。

在构建任何东西之前,用这个网格来做出决策:

方法最适合避免当
核心块一次性内容、简单页面布局在很多客户间重复且需要丰富选项
块模式无逻辑的可重复布局布局需要条件判断、动态数据或复杂交互
自定义块重复的、数据驱动的或高度特定的行为唯一原因是可以通过类处理的一次性板块

你还需要从第一天起就考虑块的命名。块名称本质上是与内容的契约。如果你把它叫做 wagent/team-grid,后来又重命名为 wagent/team-carousel,除非你提供弃用路径,否则会破坏现有内容。选择通用的、基于用途的名称,这样随着块的演化,它们不会变成虚假广告。这是我们所有人都从插件前缀中学到的命名纪律的一种体现,它同样适用于块名称。

这里反直觉的观点是我能说的最有用的:因为客户要求“只要一个”而构建的自定义块几乎总是一个错误。礼貌地说不,交付一个带有类的核心块,并把省下的时间存起来。你会赢得客户更多的尊重——而且维护预算中的开支也会更少。

“客户会搞坏编辑器”的反对意见

这个反对意见对了一半。块编辑器本身不是问题;问题是给了客户太多的自由。theme.json 可以锁定哪些是可编辑的:禁用模板编辑器,限制允许的块,并设置默认样式,这样放错的列造成的破坏会更小。有些客户仍然会设法弄坏东西,但你可以一键清除页面并恢复到已保存的模式——这是经典编辑器无法提供的。

让我描述一个场景。客户打来电话说:“我移动了一个板块,现在整个页面看起来不对了。”使用经典主题时,你通常需要登录、检查 CSS,然后可能花一个小时修复布局。而使用块设置,你可以打开页面,选择内容区域,然后重置为已保存的模式。模式是基线;客户的更改是覆盖层。当覆盖层出错时,你移除它。这不仅是一个更好的工作流程;它从根本上是一个更宽容的编辑器。

现在说说细微差别:大多数客户根本不想做太多编辑。他们只想更改文本、替换照片,也许重新排列某个板块。块模式正好为你提供了这些,而无需暴露整个站点结构。从这个意义上说,编辑器不是玩具;它是一个取景器。你的工作是校准客户能看到的内容。这意味着你可能要禁用“模板”设置,将块插入器限制为精选列表,甚至用占位内容预填充空模式。编辑器变成了一张内容录入表单,而不是网页设计画布。

在无障碍性方面,块编辑器的焦点管理和键盘支持通常优于经典编辑器的模板字段。但你仍然需要确保模式具有正确的标题层级和可访问的名称。由于模式是在客户之间共享的,你只需要修复一次这些问题,这是标准化的另一个隐藏优势。

真正困难的部分是在内部。对于你的团队来说,学习用块进行原型设计需要摒弃“用 PHP 做”的习惯。这是一个真实的成本,但这是每人的一次性成本。这不是回避这种方法的原因;而是从一套模式库和一个宽容的客户开始,然后再全面推广的原因。不要让“我的客户应付不了块”这句话掩盖你还没有配置好一套块设置来帮助他们的事实。

“我们已经有钩子和过滤器”的反对意见

这里的原则是:你并没有丢弃钩子;你只是在上面加了一层。块是表现层的边界;钩子仍然是你注入逻辑的方式。动态块的渲染回调在 PHP 中运行,这意味着你可以调用相同的函数并应用你已经信任的过滤器。

想象一个插件,它允许你通过过滤器向任何文章添加“精选产品”字段。使用动态块,你可以包含一个服务器渲染的块,该块运行该过滤器并在块的包装器内输出结果。客户插入块;现有的 PHP 逻辑完成繁重的工作。什么都不会丢弃。再举一个更具体的例子:考虑一个列出最近项目文章的自定义块。在其渲染回调中,你调用 get_posts(),然后循环应用 the_title()the_permalink()——这些是你多年来一直在使用的模板标签。

这也是诚实面对哪些东西无法迁移的地方。一些聪明的旧主题使用 template-parts 和复杂的条件判断,这些判断根据页面上下文获取参数。将其重建为块可能会很麻烦。但你不必一次性重建。渐进式的方法是保留 PHP 逻辑,把它包装在动态块中,然后把标记移到块模板中。你经常会发现现有的过滤器模式能够处理新的输出。如果逻辑与模板层级紧密耦合(例如,“在搜索结果页面上,以不同方式显示这个”),你仍然可以对那些特定视图使用经典模板,同时使用块来处理常规页面。

REST API 还打开了另一扇门:你可以构建从其他 WordPress 网站或第三方服务拉取数据的块。动态块可以调用 wp_remote_get() 来获取 JSON 并渲染到前端。对于机构构建来说,这是一个强大的模式,因为客户希望展示社交动态、产品列表或内部数据,而无需管理单独的集成。其代价是缓存和错误处理——如果远程 API 很慢,你的页面也会很慢。不要让基于 API 的块出现在关键的、首屏内容中,或者使用带有适当加载状态的客户端渲染。

动作和过滤器仍然在保存和渲染时运行;当你采用块时,钩子架构不会消失,它只是转移到了新的上下文。如果你需要重新了解动作和过滤器如何与这个新块世界衔接,我们的钩子深度解析是一份有用的复习资料。

“FSE 尚未准备好用于生产”的反对意见

有道理,但要问一下“风险”到底意味着什么。全站编辑已经经历了多个版本,theme.json 也已经稳定为一个可靠的模式。风险不在于编辑器“突然崩溃”——而在于你的团队的自定义代码可能依赖于旧式的 PHP 模板,这些模板与块模板笨拙地共存。此外,一些第三方插件仍然假定使用经典编辑器或自定义程序。这是一个兼容性决策,而不是抛弃整个模型的理由。

一个有用的思考方式:简单、可重复且内容用块编写的网站风险最低。高风险客户是那些拥有深度定制的经典主题或渲染自己的前端的专有插件的客户。对于那样的小众市场,坚持使用经典主题是合理的。错误在于假装“生产就绪”是一个要么开要么关的开关。

在向客户提议块主题之前,快速检查一下这个清单:

  • 客户是否有需要迁移的深度定制主题?
  • 必备插件是否支持站点编辑器和 REST API?
  • 托管环境是否允许块主题所需的文件访问?
  • 你是否为模式设计留出了时间,而不仅仅是块注册?
  • 客户的团队能否接受编辑器更改,还是需要一个锁定模板?

如果任何答案是“否”,那就调整范围或使用混合方法。这不是妥协;这是工程判断。如果你正在构建一个混合方案,记住上面关于钩子和过滤器的故事——你仍然可以在动态块中包装旧逻辑,同时让 theme.json 处理全局外观。

对你的 theme.json 进行版本管理不仅仅是一个理论问题。我曾见过一个机构的自定义块库在客户更新 WordPress 时崩溃,因为该块的 style 文件是用 wp_register_style() 在更改后的句柄下注册的。修复很容易,但恐慌是真实的。一个简单的测试流程——在站点的暂存副本上运行更新,点击浏览关键页面,然后发布——就能解决大多数这类意外。

你还没向自己提出的反对意见

这里有一个元反对意见让机构无法标准化:“这是一个巨大的变化,而且在客户工作中没有时间去做。”这是事实——所以不要在客户工作中去做。选择一个内部项目或一个小客户,建立一套模式库。使用 theme.json 作为设计令牌系统。只有在合理时才添加自定义块。在有用的地方包装旧钩子。迭代。

以下是大致的前 30 天:

  1. 审查你最近的五个客户构建,列出重复率最高的十个布局片段。
  2. 将这十个片段转化为块模式,并附带一小套 CSS 类。
  3. 构建一个共享插件(或 mu-plugin)来注册这些模式。如果你还没有考虑过插件组织方式,先略读这份关于构建健壮插件的指南
  4. 创建一个与你的基线设计匹配的 theme.json;在启动项目时添加客户特定的值。
  5. 选择一个小型内部项目或一个友好的客户,将其迁移到该技术栈上。
  6. 记录一个客户故事,讲述客户在未联系你的情况下编辑了自己的首页。

在那次实验结束时,你不会有一个‘块优先’的徽章可以挂在墙上。你会有一个能够从共享基线快速启动新客户网站而无需为时间表道歉的团队。你也会更有底气对客户要第 42 个自定义块的请求说不——因为你确切知道核心块能做什么,或者因为你能够展示为什么动态块真的会更快。

你还会构建一些定制网站吗?是的。有些客户总是需要自定义模板、定制页面或专有集成,这些不值得强行纳入共享模型。目标不是消除定制工作——而是让它成为例外而不是默认。

可重复性来自于那些枯燥的部分:一个可靠的 theme.json 模式,一个清晰的模式库,以及保持共享层精简的纪律。这不是你在网络研讨会上听到的花哨版本。而是那个能战胜周一早晨空白主题忧郁情绪的版本。

Sources (5)