Gutenberg 编辑器资源加载指南:在 iframe 化 Editor 中正确 enqueue 脚本与样式
2026/9/16 19:07:32 网站建设 项目流程

Gutenberg 编辑器资源加载指南:在 iframe 化 Editor 中正确 enqueue 脚本与样式

【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg

导读

本文是 Gutenberg 仓库中关于在块编辑器(Block Editor)中加载资源(脚本与样式)的权威实操指南。无论是为编辑器 UI(工具栏控件、检查器控件、插件面板)加载 JavaScript,还是为 iframe 内的用户生成内容(区块)注入样式,不同目标对应着enqueue_block_editor_assetsenqueue_block_assetsblock_editor_settings_all等不同的钩子。读完本文,你将掌握在插件与主题中按场景正确选择资源加载钩子、理解 iframe 编辑器的加载机制,并能在兼容旧版 WordPress 时做出正确取舍。

本文基于 Gutenberg 仓库 docs/how-to-guides/enqueueing-assets-in-the-editor.md 展开,并结合仓库lib/目录下的真实实现源码进行纵深讲解。文中引用的行号均可直接在仓库中核对。

背景:Editor 为什么是 iframe 化的

Site Editor(站点编辑器)始终使用 iframe。本文档撰写时,Gutenberg 23.6 与 WordPress 7.1 起,无论文章内容中区块的 Block API 版本 如何,Post Editor(文章编辑器)也始终使用 iframe;WordPress 7.0 仍保留了对非 iframe 文章编辑器的条件性回退。本文默认你的目标是 iframe 化编辑器,支持旧版本 WordPress 时的做法请参考文末"向后兼容"一节。

iframe 化的意义在于:编辑器的画布(用户内容)与编辑器 UI 被隔离在独立的文档上下文中,主题的前端样式不会直接污染编辑界面,而编辑器中看到的区块渲染与前端也得以保持一致。这也意味着,你为编辑器加载的资源,其最终去向(编辑器 UI 文档,还是 iframe 内的内容文档)直接决定了你应该使用哪个钩子

第一步:先分清 "Editor" 与 "Editor content"

在动手 enqueue 任何资源之前,必须先回答一个问题:你到底想给谁加载资源?

  • Editor(编辑器 UI):指编辑器本身的界面组件——顶部工具栏、检查器(Inspector)、区块工具条、设置面板、插件注册的侧边栏等,以及所有通过 JavaScript 注册的区块变体、格式、插件。
  • Editor content(编辑器内容):指用户在编辑器中创建的内容,即页面/文章中的区块本体及其渲染结果。

两个目标使用完全不同的钩子;如果你在构建区块或主题,还有额外的方法可选。下表先给出概览,下文逐一展开:

目标推荐钩子 / 方法生效范围
编辑器 UI 的脚本与样式enqueue_block_editor_assets仅编辑器
用户生成内容(区块)的脚本与样式enqueue_block_assets编辑器 iframe 内 + 前端
仅编辑器内的内容样式(高级做法)block_editor_settings_all仅编辑器 iframe 内
区块自身的脚本与样式block.json(Block Metadata)按声明控制
主题的编辑器样式add_editor_style()/wp_enqueue_block_style()/theme.json编辑器 / 前端

场景一:为编辑器 UI 加载脚本与样式

当需要为编辑器本身(而非用户生成内容)加载资源时,使用enqueue_block_editor_assets钩子,配合标准的wp_enqueue_script()wp_enqueue_style()函数。

典型用途包括:添加自定义检查器控件与工具条控件、在 JavaScript 中注册区块样式与区块变体、注册编辑器插件等。

/** * Enqueue Editor assets. */ function example_enqueue_editor_assets() { wp_enqueue_script( 'example-editor-scripts', plugins_url( 'editor-scripts.js', __FILE__ ) ); wp_enqueue_style( 'example-editor-styles', plugins_url( 'editor-styles.css', __FILE__ ) ); } add_action( 'enqueue_block_editor_assets', 'example_enqueue_editor_assets' );

在 Gutenberg 仓库自身,这一钩子被大量用于加载编辑器所需的模块化资源。例如 lib/client-assets.php 中,插件通过enqueue_block_editor_assets加载了三个编辑器脚本模块:

add_action( 'enqueue_block_editor_assets', 'gutenberg_enqueue_latex_to_mathml_loader' ); function gutenberg_enqueue_latex_to_mathml_loader() { wp_enqueue_script_module( '@wordpress/latex-to-mathml/loader' ); } // 以及 vips 加载器、video-conversion 加载器,均注册为 import map 中的动态依赖, // 以便在客户端媒体处理被触发时按需加载。

可见该钩子不仅支持传统wp_enqueue_script,也支持以wp_enqueue_script_module()注册 ES Module(脚本模块),供编辑器内部按需取用。仓库 lib/script-loader.php 还演示了如何在同一条钩子上替换全局样式 CSS 自定义属性的注册逻辑。

需要强调的是:虽然enqueue_block_editor_assets在技术上也能用于给编辑器内容加样式,但这不是推荐做法,仅作为向后兼容手段存在(详见文末)。

场景二:为编辑器内容(区块)加载脚本与样式

2.1 首选方案:enqueue_block_assets

自 WordPress 6.3 起,通过enqueue_block_assetsPHP 动作添加的所有资源,也会被 enqueue 到 iframe 化编辑器内。这是为用户生成内容(区块)加载资源的主要方法——该钩子在编辑器与站点前端都会触发。

因此它不应被用于添加面向编辑器 UI 的资源,也不应被用来调用编辑器 API。

某些场景下你可能只希望在编辑器内加载资源、而不希望它在前端出现,可以通过is_admin()判断实现:

/** * Enqueue content assets but only in the Editor. */ function example_enqueue_editor_content_assets() { if ( is_admin() ) { wp_enqueue_script( 'example-editor-content-scripts', plugins_url( 'content-scripts.js', __FILE__ ) ); wp_enqueue_style( 'example-editor-content-styles', plugins_url( 'content-styles.css', __FILE__ ) ); } } add_action( 'enqueue_block_assets', 'example_enqueue_editor_content_assets' );

从源码层面看,iframe 内内容样式的加载链路在 Gutenberg 中有着精心设计的依赖顺序。lib/client-assets.php 中注册wp-edit-blocks样式时,注释明确写着"Only add CONTENT styles here that should be enqueued in the iframe!"(这里只添加应当在 iframe 内 enqueue 的内容样式),并维护了如下依赖链:

$wp_edit_blocks_dependencies = array( 'wp-theme', // 设计系统 tokens 最先加载,确保 :root CSS 自定义属性先于消费它的样式表被定义 'wp-components', 'wp-reset-editor-styles', // 需在块库样式之前,块库样式会覆盖 reset 样式 'wp-block-library', 'wp-block-editor-content', 'wp-base-styles', );

这段实现印证了:进入 iframe 的内容样式并非随意拼接,而是按"设计令牌 → 组件 → 重置 → 块库 → 编辑器内容 → 基础样式"的顺序加载,从而保证变量定义、重置与覆盖关系都正确。

2.2 进阶方案:block_editor_settings_all 过滤器

block_editor_settings_all钩子允许直接修改编辑器设置,实现方式稍复杂但灵活性更高。仅当enqueue_block_assets无法满足需求时才应使用它。

下面的例子为所有段落设置默认文字颜色为green

/** * Modify the Editor settings by adding custom styles. * * @param array $editor_settings An array containing the current Editor settings. * @param string $editor_context The context of the editor. * * @return array Modified editor settings with the added custom CSS style. */ function example_modify_editor_settings( $editor_settings, $editor_context ) { $editor_settings["styles"][] = array( "css" => 'p { color: green }' ); return $editor_settings; } add_filter( 'block_editor_settings_all', 'example_modify_editor_settings', 10,2 );

这些样式会被内联进 iframe 编辑器的body,并以.editor-styles-wrapper作为前缀,最终生成的标记如下:

<style>.editor-styles-wrapper p { color: green; }</style>

自 WordPress 6.3 起,还可以通过 JavaScript 动态修改编辑器设置来实时变更样式。

在 Gutenberg 仓库中,lib/block-editor-settings.php 的gutenberg_get_block_editor_settings()函数正是在block_editor_settings_all过滤器上(优先级 0)替换 core 的styles__experimentalFeatures设置:它收集全局样式预设、区块类样式、定制器附加 CSS 与自定义 CSS,与get_block_editor_theme_styles()的结果合并后写回$settings['styles']。这展示了该过滤器在真实项目中的典型用法——在编辑器设置送达 iframe 之前,集中注入、排序与兜底全局样式。

场景三:区块自身的脚本与样式(block.json)

当你在构建区块时,block.json是声明区块所需全部脚本与样式的推荐方式。你可以在其中分别声明用于编辑器、前端或两者兼有的资源(editorScripteditorStylescriptstyleviewScript等字段),详见仓库中的 Block Metadata 参考。

Gutenberg 对区块资源的注册同样遵循"每块多样式"的分工。查看 lib/blocks.php 的gutenberg_register_core_block_assets():它为每个核心区块分别解析三个样式文件——style.css(前端样式,注册为wp-block-{name})、theme.css(主题化样式,注册为wp-block-{name}-theme)以及style-editor.css(编辑器样式,注册为wp-block-{name}-editor),并借助wp_should_load_separate_core_block_assets()判断是否启用"按区块拆分加载"策略。这正是block.json声明在运行时如何被翻译为独立、可精确控制的作用域。

场景四:主题的脚本与样式

如果需要在主题中 enqueue 编辑器 JavaScript,可以按前文所述使用enqueue_block_assetsenqueue_block_editor_assets。而编辑器专属的样式表,几乎总应通过以下方式之一添加:

  • add_editor_style():经典主题将样式表同时应用于编辑器内容与前端渲染的常用做法;
  • wp_enqueue_block_style():允许在编辑器与前端按区块粒度加载样式表,与theme.json配合是当前性能最优的区块样式方案之一。

wp_enqueue_block_style()的核心价值在于按需加载——只有当页面真正渲染了某个区块时,对应的样式才会被加载,从而避免一次性输出全部区块样式拖慢首屏。结合theme.json中的样式声明(stylessettings体系),主题作者可以把区块样式从"全局兜底"细化为"区块级精准投递"。Gutenberg 仓库 lib/theme.json 与 lib/global-styles-and-settings.php 即演示了这类配置如何被解析为最终的编辑器与前端样式输出。

向后兼容与已知问题

兼容规则速览

作为一般规则:在 iframe 化编辑器中 enqueue 的资源,只要你在使用 WordPress 6.3+,那么当编辑器不是iframe 时这些资源同样会被 enqueue;反过来则不一定成立。

需要兼容 6.2 及更低版本时

如果你的插件或主题需要向后兼容 WordPress 6.2 或更低版本,同时又要兼容 6.3,那么不能依赖enqueue_block_assets——因为在 6.3 之前,该钩子不会把资源 enqueue 进 iframe 编辑器的内容中。

作为替代方案,可以改用enqueue_block_editor_assets,但前提是 enqueue 的样式表中至少包含以下选择器之一:.editor-styles-wrapper.wp-block.wp-block-*。此时浏览器控制台会记录一条警告信息,但钩子仍会把样式应用到编辑器内容上。也就是说,旧版 WordPress 依赖"编辑器文档内选择器命中间接应用到内容"这一机制,新版则直接支持 iframe 内加载。

资源双加载问题

自 WordPress 6.3 起,enqueue_block_assetsenqueue 的资源出于向后兼容考虑,会同时在编辑器 iframe 内部和外部被加载。如果你 enqueue 的脚本库对重复加载敏感(例如初始化全局监听器、重复绑定事件),这可能导致问题。关于这一方案的取舍,Gutenberg 仓库中仍有持续的讨论,遇到问题可先搜索是否已被报告。

处理未收录的问题

如果你在使用本文所述方法时遇到尚未被报告的问题,建议在仓库的 Issue 系统中提交新问题,并注明所用 WordPress/Gutenberg 版本、钩子与复现步骤。

总结:一个决策清单

  1. 目标是谁?——编辑器 UI 用enqueue_block_editor_assets;用户内容用enqueue_block_assets;仅编辑器内的内容样式可尝试block_editor_settings_all
  2. 是区块吗?——优先使用block.json声明资源,让运行时的"每块多样式"机制为你管理作用域。
  3. 是主题吗?——编辑器样式优先add_editor_style()/wp_enqueue_block_style(),并结合theme.json做按块加载。
  4. 要兼容 6.2 以下吗?——避免单独依赖enqueue_block_assets,改用带.editor-styles-wrapper/.wp-block选择器的enqueue_block_editor_assets,并接受控制台警告。
  5. 担心重复加载?——注意 6.3 起enqueue_block_assets在 iframe 内外双加载的影响,评估脚本库的幂等性。

按照这张清单选择钩子,你的资源就能在 iframe 化编辑器中各归其位:UI 归 UI,内容归内容,前端归前端。

【免费下载链接】gutenbergThe Block Editor project for WordPress and beyond. Plugin is available from the official repository.项目地址: https://gitcode.com/GitHub_Trending/gu/gutenberg

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询