剖析 WordPress `gutenberg_get_assets()` 函数的源码:如何加载 Gutenberg 的前端资源。

好,各位朋友们,今天咱们来聊聊 WordPress 里 Gutenberg 编辑器的资源加载问题。这可是个挺重要的环节,直接关系到你的页面能不能正常显示,用户体验好不好。咱们的目标就是把 gutenberg_get_assets() 这个函数扒个精光,看看它到底是怎么把 Gutenberg 的前端资源像变魔术一样加载到页面上的。

开场白:Gutenberg 的那些“家当”

在深入代码之前,咱们先得对 Gutenberg 的资源有个大致的了解。Gutenberg 可不是只有一个文件就能跑起来的,它需要一系列的 JavaScript、CSS 文件,还有一些翻译文件等等。这些就是 Gutenberg 的“家当”,gutenberg_get_assets() 的任务就是把这些“家当”打包好,送到浏览器那里。

正题:gutenberg_get_assets() 函数的剖析

好了,废话不多说,直接上代码。不过,因为 Gutenberg 的代码量比较大,咱们这里只关注核心的部分,也就是资源加载相关的逻辑。

<?php

/**
 * Retrieves the assets for the Gutenberg editor.
 *
 * @since 5.0.0
 *
 * @return array {
 *     Assets for the Gutenberg editor.
 *
 *     @type string $dependencies    Array of script dependencies.
 *     @type string $version         Version of the Gutenberg editor.
 *     @type string $js              Path to the Gutenberg JavaScript file.
 *     @type string $css             Path to the Gutenberg CSS file.
 *     @type string $editor_settings Array of editor settings.
 * }
 */
function gutenberg_get_assets() {
    static $assets = null;

    if ( is_array( $assets ) ) {
        return $assets;
    }

    $dependencies = array(
        'wp-polyfill',
        'wp-blocks',
        'wp-i18n',
        'wp-element',
        'wp-components',
        'wp-editor',
        'wp-plugins',
        'wp-edit-post',
        'wp-edit-site', // Site Editor.
        'wp-media-utils',
        'wp-block-directory',
        'wp-block-library',
    );

    $version = false;
    $js      = null;
    $css     = null;

    // Check if the Gutenberg plugin is active.
    if ( function_exists( 'gutenberg_url' ) ) {
        $js  = gutenberg_url() . 'build/index.js';
        $css = gutenberg_url() . 'build/edit-post.css';

        if ( defined( 'GUTENBERG_VERSION' ) ) {
            $version = GUTENBERG_VERSION;
        }
    } else {
        $version = get_bloginfo( 'version' );
        $js      = includes_url( 'js/dist/editor.js' );
        $css     = includes_url( 'css/dist/edit-post.css' );
    }

    $assets = array(
        'dependencies'    => $dependencies,
        'version'         => $version,
        'js'              => $js,
        'css'             => $css,
        'editor_settings' => gutenberg_get_editor_settings(),
    );

    return $assets;
}

代码解读:一步一个脚印

咱们来一步步地解读这段代码。

  1. 静态变量缓存:

    static $assets = null;
    
    if ( is_array( $assets ) ) {
        return $assets;
    }

    这段代码使用了静态变量 $assets 来缓存资源信息。这意味着 gutenberg_get_assets() 函数只会执行一次资源信息的获取过程。后续的调用都会直接从缓存中读取,避免重复计算,提高性能。 这就像是,你第一次去饭店吃饭,服务员会给你一张菜单。以后你再来,如果还是点同样的菜,服务员就直接从记忆里拿菜单了,不用再给你一张新的。

  2. 依赖项声明:

    $dependencies = array(
        'wp-polyfill',
        'wp-blocks',
        'wp-i18n',
        'wp-element',
        'wp-components',
        'wp-editor',
        'wp-plugins',
        'wp-edit-post',
        'wp-edit-site', // Site Editor.
        'wp-media-utils',
        'wp-block-directory',
        'wp-block-library',
    );

    这里定义了一个 $dependencies 数组,列出了 Gutenberg 编辑器所依赖的 JavaScript 模块。这些模块都是 WordPress 自带的,它们提供了各种各样的功能,比如区块管理、国际化、UI 组件等等。 这些依赖项就像是盖房子需要的砖头、水泥、钢筋,Gutenberg 要想正常工作,就必须先准备好这些材料。WordPress 会负责把这些依赖项按照正确的顺序加载到页面上。

  3. 判断 Gutenberg 插件是否激活:

    if ( function_exists( 'gutenberg_url' ) ) {
        $js  = gutenberg_url() . 'build/index.js';
        $css = gutenberg_url() . 'build/edit-post.css';
    
        if ( defined( 'GUTENBERG_VERSION' ) ) {
            $version = GUTENBERG_VERSION;
        }
    } else {
        $version = get_bloginfo( 'version' );
        $js      = includes_url( 'js/dist/editor.js' );
        $css     = includes_url( 'css/dist/edit-post.css' );
    }

    这段代码会检查 Gutenberg 插件是否已经激活。如果激活了,就从插件目录中加载 JavaScript 和 CSS 文件;如果没有激活,就从 WordPress 核心目录中加载。这样做是为了保证在 Gutenberg 插件没有激活的情况下,WordPress 也能正常使用 Gutenberg 编辑器。 这就像是,如果你的电脑里装了 Photoshop,就用 Photoshop 打开图片;如果没有装,就用系统自带的图片查看器打开。

  4. 构建资源数组:

    $assets = array(
        'dependencies'    => $dependencies,
        'version'         => $version,
        'js'              => $js,
        'css'             => $css,
        'editor_settings' => gutenberg_get_editor_settings(),
    );

    最后,这段代码把所有的资源信息都放到了一个 $assets 数组里。这个数组包含了依赖项、版本号、JavaScript 文件路径、CSS 文件路径,以及编辑器设置。 这个数组就像是一个大礼包,里面装满了 Gutenberg 需要的所有东西。WordPress 会把这个礼包送到浏览器那里,让浏览器知道该加载哪些文件。

重点:gutenberg_get_editor_settings()

刚才咱们提到了 gutenberg_get_editor_settings() 函数,这个函数也很重要,因为它负责获取 Gutenberg 编辑器的各种设置。这些设置包括区块的可用性、主题支持、自定义字段等等。

<?php
/**
 * Retrieves the editor settings.
 *
 * @since 5.0.0
 *
 * @return array Editor settings.
 */
function gutenberg_get_editor_settings() {
    global $current_screen;

    $settings = array(
        'alignWide'           => get_theme_support( 'align-wide' ),
        'availableTemplates'  => _gutenberg_get_available_templates(),
        'allowedBlockTypes'   => _gutenberg_get_allowed_block_types( $current_screen ),
        'disableCustomColors' => get_theme_support( 'disable-custom-colors' ),
        'disableCustomFontSizes' => get_theme_support( 'disable-custom-font-sizes' ),
        'enableCustomLineHeight' => get_theme_support( 'custom-line-height' ),
        'enableCustomSpacing'  => get_theme_support( 'custom-spacing' ),
        'enableCustomUnits'    => get_theme_support( 'custom-units' ),
        'isRTL'               => is_rtl(),
        'imageSizes'          => get_intermediate_image_sizes(),
        'maxUploadFileSize'   => wp_max_upload_size(),
        'nonce'               => wp_create_nonce( 'wp_rest' ),
        'post'                => null,
        'richEditingEnabled'  => user_can_richedit(),
        'styles'              => _gutenberg_get_editor_styles(),
        'template'            => get_page_template_slug(),
        'titlePlaceholder'    => _x( 'Add title', 'block title' ),
        'bodyPlaceholder'     => _x( 'Start writing or type / to choose a block', 'block body' ),
        'defaultBlock'        => get_option( 'default_block' ),
        '__experimentalBlockPatterns' => WP_Block_Patterns_Registry::get_instance()->get_all_registered(),
        '__experimentalBlockPatternCategories' => WP_Block_Pattern_Categories_Registry::get_instance()->get_all_registered(),
    );

    if ( ! empty( $current_screen->post_type ) ) {
        $settings['post'] = _gutenberg_get_current_post( $current_screen->post_type );
    }

    /**
     * Filters the settings passed to the editor.
     *
     * @since 5.0.0
     *
     * @param array $settings Array of settings.
     */
    return apply_filters( 'block_editor_settings', $settings );
}

这个函数会从主题、插件和 WordPress 核心中获取各种设置,然后把它们放到一个数组里。这些设置会影响 Gutenberg 编辑器的行为和外观。 比如说,alignWide 设置决定了是否支持宽对齐;allowedBlockTypes 设置决定了允许使用哪些区块;styles 设置决定了编辑器的样式。

资源加载的流程:从 PHP 到浏览器

现在咱们已经了解了 gutenberg_get_assets() 函数的作用,接下来咱们来看看资源加载的整个流程。

  1. enqueue_block_editor_assets 钩子:

    WordPress 提供了一个 enqueue_block_editor_assets 钩子,允许我们在后台加载 Gutenberg 编辑器的资源。通常,我们会把加载资源的代码放到这个钩子里。

    add_action( 'enqueue_block_editor_assets', 'my_enqueue_block_editor_assets' );
    
    function my_enqueue_block_editor_assets() {
        $assets = gutenberg_get_assets();
    
        wp_enqueue_script(
            'my-gutenberg-script',
            $assets['js'],
            $assets['dependencies'],
            $assets['version'],
            true // 在页脚加载
        );
    
        wp_enqueue_style(
            'my-gutenberg-style',
            $assets['css'],
            array(),
            $assets['version']
        );
    
        wp_localize_script(
            'my-gutenberg-script',
            'myGutenbergSettings',
            $assets['editor_settings']
        );
    }

    这段代码会调用 gutenberg_get_assets() 函数获取资源信息,然后使用 wp_enqueue_script()wp_enqueue_style() 函数把 JavaScript 和 CSS 文件加载到页面上。wp_localize_script() 函数则会把编辑器设置传递给 JavaScript 代码。

  2. wp_enqueue_script()wp_enqueue_style()

    这两个函数是 WordPress 提供的标准函数,用于加载 JavaScript 和 CSS 文件。它们接受几个参数,包括脚本/样式句柄、文件路径、依赖项、版本号和加载位置。 wp_enqueue_script() 函数的第五个参数 true 表示在页脚加载脚本,这样可以提高页面加载速度。

  3. wp_localize_script()

    这个函数用于把 PHP 变量传递给 JavaScript 代码。它接受三个参数,包括脚本句柄、JavaScript 对象名称和 PHP 数组。 在上面的例子中,我们把编辑器设置传递给了一个名为 myGutenbergSettings 的 JavaScript 对象。

  4. 浏览器加载资源:

    当 WordPress 生成 HTML 页面时,它会在 <head><body> 标签中插入 <script><link> 标签,指向我们加载的 JavaScript 和 CSS 文件。 浏览器会解析这些标签,然后从服务器下载这些文件,并执行 JavaScript 代码和应用 CSS 样式。

总结:gutenberg_get_assets() 的核心作用

咱们来总结一下 gutenberg_get_assets() 函数的核心作用:

  • 获取资源信息: 它负责获取 Gutenberg 编辑器所需要的 JavaScript、CSS 和其他资源的信息。
  • 管理依赖项: 它定义了 Gutenberg 编辑器的依赖项,确保这些依赖项按照正确的顺序加载。
  • 提供编辑器设置: 它获取并传递编辑器设置,影响 Gutenberg 编辑器的行为和外观。

表格总结:

功能 描述
资源获取 获取 Gutenberg 编辑器所需的 JavaScript, CSS, 版本号等资源信息.
依赖管理 定义并管理 Gutenberg 的 JavaScript 依赖项,确保按顺序加载.
编辑器设置 获取并传递编辑器配置信息,如主题支持、区块类型限制等,影响编辑器的行为和外观.
缓存机制 使用静态变量缓存资源信息,避免重复计算,提高性能.
插件/核心路径判断 根据 Gutenberg 插件是否激活,选择从插件目录或 WordPress 核心目录加载资源.
与 WordPress 集成 与 WordPress 的 enqueue_block_editor_assets 钩子集成,方便开发者加载 Gutenberg 编辑器资源. 使用 wp_enqueue_script, wp_enqueue_style, wp_localize_script 等 WordPress 函数进行资源加载.

进阶:自定义 Gutenberg 资源加载

如果你想自定义 Gutenberg 的资源加载,可以考虑以下几个方面:

  • 修改依赖项: 你可以修改 $dependencies 数组,添加或删除依赖项。
  • 替换 JavaScript 和 CSS 文件: 你可以使用 wp_deregister_script()wp_deregister_style() 函数取消注册 Gutenberg 的默认脚本和样式,然后注册你自己的脚本和样式。
  • 修改编辑器设置: 你可以使用 block_editor_settings 过滤器修改编辑器设置。

注意事项:

  • 在自定义 Gutenberg 资源加载时,一定要小心谨慎,避免破坏 Gutenberg 编辑器的正常功能。
  • 在修改依赖项时,要确保你的依赖项与 Gutenberg 编辑器兼容。
  • 在替换 JavaScript 和 CSS 文件时,要确保你的文件包含了 Gutenberg 编辑器所需要的所有功能。

结束语:Gutenberg 的奥秘

好了,今天的讲座就到这里。希望通过今天的讲解,大家对 gutenberg_get_assets() 函数有了更深入的了解。Gutenberg 编辑器是一个非常复杂的系统,资源加载只是其中的一个环节。如果你想深入了解 Gutenberg,还需要学习更多的知识。祝大家学习愉快!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注