块编辑器开发文档

💡 云策文档标注

概述

功能标志是变量,用于控制 Gutenberg 项目中的特定代码是否包含在 WordPress 核心中,以及是否仅在插件中运行实验性功能。文档介绍了 globalThis.IS_GUTENBERG_PLUGIN 环境变量的使用,以区分插件和核心环境。

关键要点

  • globalThis.IS_GUTENBERG_PLUGIN 是一个环境变量,在插件构建时设为 true,在 WordPress 核心构建时设为 false 或 undefined。
  • 导出插件专用功能时,应使用三元语法,如 export const pluginOnlyFeature = globalThis.IS_GUTENBERG_PLUGIN ? myPluginOnlyFeature : undefined。
  • 导入插件专用功能时,需用 if 语句包装调用,如 if ( globalThis.IS_GUTENBERG_PLUGIN ) { pluginOnlyFeature(); }。
  • 在 webpack 构建过程中,globalThis.IS_GUTENBERG_PLUGIN 会被替换为布尔值,以启用或禁用代码执行。
  • 生产构建时,webpack 的 dead code elimination 会移除不必要的代码,确保插件专用代码不包含在核心构建中。
  • 避免将涉及 IS_GUTENBERG_PLUGIN 的表达式赋值给变量,以防止 webpack 无法识别和消除死代码。

代码示例

function myPluginOnlyFeature() {
    // implementation
}

export const pluginOnlyFeature = globalThis.IS_GUTENBERG_PLUGIN
    ? myPluginOnlyFeature
    : undefined;

注意事项

  • 使用功能标志时,应遵循文档中的示例,以确保 webpack 能正确进行 dead code elimination。
  • 避免复杂表达式,以免干扰 webpack 的优化过程。

📄 原文内容

‘Feature flags’ are variables that allow you to prevent specific code in the Gutenberg project from being shipped to WordPress core, and to run certain experimental features only in the plugin.

Introducing globalThis.IS_GUTENBERG_PLUGIN

The globalThis.IS_GUTENBERG_PLUGIN is an environment variable whose value ‘flags’ whether code is running within the Gutenberg plugin.

When the codebase is built for the plugin, this variable will be set to true. When building for WordPress core, it will be set to false or undefined.

Basic usage

Exporting features

A plugin-only function or constant should be exported using the following ternary syntax:

function myPluginOnlyFeature() {
    // implementation
}

export const pluginOnlyFeature = globalThis.IS_GUTENBERG_PLUGIN
    ? myPluginOnlyFeature
    : undefined;

In the above example, the pluginOnlyFeature export will be undefined in non-plugin environments such as WordPress core.

Importing features

If you’re attempting to import and call a plugin-only feature, be sure to wrap the function call in an if statement to avoid an error:

import { pluginOnlyFeature } from '@wordpress/foo';

if ( globalThis.IS_GUTENBERG_PLUGIN ) {
    pluginOnlyFeature();
}

How it works

During the webpack build, instances of globalThis.IS_GUTENBERG_PLUGIN will be replaced using webpack’s define plugin.

For example, in the following code –

if ( globalThis.IS_GUTENBERG_PLUGIN ) {
    pluginOnlyFeature();
}

– the variable globalThis.IS_GUTENBERG_PLUGIN will be replaced with the boolean true during the plugin-only build:

if ( true ) {
    // Webpack has replaced `globalThis.IS_GUTENBERG_PLUGIN` with `true`
    pluginOnlyFeature();
}

This ensures that code within the body of the if statement will always be executed.

In WordPress core, the globalThis.IS_GUTENBERG_PLUGIN variable is replaced with undefined. The built code looks like this:

if ( undefined ) {
    // Webpack has replaced `globalThis.IS_GUTENBERG_PLUGIN` with `undefined`
    pluginOnlyFeature();
}

undefined evaluates to false so the plugin-only feature will not be executed.

Dead code elimination

For production builds, webpack ‘minifies’ the code, removing as much unnecessary JavaScript as it can.

One of the steps involves something known as ‘dead code elimination’. For example, when the following code is encountered, webpack determines that the surrounding if statement is unnecessary:

if ( true ) {
    pluginOnlyFeature();
}

The condition will always evaluate to true, so webpack removes it, leaving behind the code that was in the body:

pluginOnlyFeature(); // The `if` condition block has been removed. Only the body remains.

Similarly, when building for WordPress core, the condition in the following if statement always resolves to false:

if ( undefined ) {
    pluginOnlyFeature();
}

In this case, the minification process will remove the entire if statement including the body, ensuring plugin-only code is not included in WordPress core build.

Frequently asked questions

Why shouldn’t I assign the result of an expression involving IS_GUTENBERG_PLUGIN to a variable, e.g. const isMyFeatureActive = ! Object.is( undefined, globalThis.IS_GUTENBERG_PLUGIN )?

Introducing complexity may prevent webpack’s minifier from identifying and therefore eliminating dead code. Therefore it is recommended to use the examples in this document to ensure your feature flag functions as intended. For further details, see the Dead Code Elimination section.