Skip to content

Commit

Permalink
Build: Use globalThis over process.env and enable TS lib checking (Wo…
Browse files Browse the repository at this point in the history
…rdPress#61486)

# Change `process.env.NAME` to `globalThis.NAME`.

This includes changing `SCRIPT_DEBUG` global to use
`globalThis.SCRIPT_DEBUG`.

There are a few problems with `process.env`:

- It only exists in Node.js. It does not exist in the browser. This
  means that additional checks must be added in application code to make
  sure that it doesn't error.
- `process.env` in Node.js is unusual. It's a key-value structure where
  _the values are always strings_.
  See https://nodejs.org/docs/latest-v20.x/api/process.html#processenv
  Gutenberg used non-string values which was wrong in environments where
  `process.env` exists, but also did compile-time replacement in some
  environments with impossible values. This makes everything confusing.
- The inconsistent `process.env` values caused problems in the type
  system. They conflicted with the Node.js types that correctly assert
  that process.env values must be `strings`.

Using `globalThis` has the benefit of being safer in third party code and valid in the
type system.

# Remove all skipLibCheck from tsconfig

The `skipLibCheck` configuration is no longer necessary and helps to
produce better type declarations for Gutenberg's published libraries.

---------

Co-authored-by: Greg Ziółkowski <grzegorz@gziolo.pl>
  • Loading branch information
2 people authored and carstingaxion committed Jun 4, 2024
1 parent 84fb04c commit 539b07c
Show file tree
Hide file tree
Showing 63 changed files with 780 additions and 572 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ module.exports = {
],
globals: {
wp: 'off',
globalThis: 'readonly',
},
settings: {
jsdoc: {
Expand All @@ -104,7 +105,7 @@ module.exports = {
'jest/expect-expect': 'off',
'react/jsx-boolean-value': 'error',
'@wordpress/dependency-group': 'error',
'@wordpress/is-gutenberg-plugin': 'error',
'@wordpress/wp-global-usage': 'error',
'@wordpress/react-no-unsafe-timeout': 'error',
'@wordpress/i18n-text-domain': [
'error',
Expand Down
8 changes: 4 additions & 4 deletions docs/contributors/code/coding-guidelines.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ An **plugin-only API** is one which is planned for eventual public availability,
Plugin-only APIs are excluded from WordPress Core and only available in the Gutenberg Plugin:

```js
// Using process.env.IS_GUTENBERG_PLUGIN allows Webpack to exclude this
// Using globalThis.IS_GUTENBERG_PLUGIN allows Webpack to exclude this
// export from WordPress core:
if ( process.env.IS_GUTENBERG_PLUGIN ) {
if ( globalThis.IS_GUTENBERG_PLUGIN ) {
export { doSomethingExciting } from './api';
}
```
Expand Down Expand Up @@ -448,8 +448,8 @@ lock( privateApis, { privateEverywhere, privateInCorePublicInPlugin } );

// The privateInCorePublicInPlugin function is explicitly exported,
// but this export will not be merged into WordPress core thanks to
// the process.env.IS_GUTENBERG_PLUGIN check.
if ( process.env.IS_GUTENBERG_PLUGIN ) {
// the globalThis.IS_GUTENBERG_PLUGIN check.
if ( globalThis.IS_GUTENBERG_PLUGIN ) {
export const privateInCorePublicInPlugin =
unlock( privateApis ).privateInCorePublicInPlugin;
}
Expand Down
27 changes: 15 additions & 12 deletions docs/how-to-guides/feature-flags.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

'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 `process.env.IS_GUTENBERG_PLUGIN`
## Introducing `globalThis.IS_GUTENBERG_PLUGIN`

The `process.env.IS_GUTENBERG_PLUGIN` is an environment variable whose value 'flags' whether code is running within the 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`.

Expand All @@ -19,8 +19,9 @@ function myPluginOnlyFeature() {
// implementation
}

export const pluginOnlyFeature =
process.env.IS_GUTENBERG_PLUGIN ? myPluginOnlyFeature : undefined;
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.
Expand All @@ -32,37 +33,39 @@ If you're attempting to import and call a plugin-only feature, be sure to wrap t
```js
import { pluginOnlyFeature } from '@wordpress/foo';

if ( process.env.IS_GUTENBERG_PLUGIN ) {
if ( globalThis.IS_GUTENBERG_PLUGIN ) {
pluginOnlyFeature();
}
```

## How it works

During the webpack build, instances of `process.env.IS_GUTENBERG_PLUGIN` will be replaced using webpack's [define plugin](https://webpack.js.org/plugins/define-plugin/).
During the webpack build, instances of `globalThis.IS_GUTENBERG_PLUGIN` will be replaced using webpack's [define plugin](https://webpack.js.org/plugins/define-plugin/).

For example, in the following code –

```js
if ( process.env.IS_GUTENBERG_PLUGIN ) {
if ( globalThis.IS_GUTENBERG_PLUGIN ) {
pluginOnlyFeature();
}
```

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

```js
if ( true ) { // Wepack has replaced `process.env.IS_GUTENBERG_PLUGIN` with `true`
if ( true ) {
// Wepack 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 `process.env.IS_GUTENBERG_PLUGIN` variable is replaced with `undefined`. The built code looks like this:
In WordPress core, the `globalThis.IS_GUTENBERG_PLUGIN` variable is replaced with `undefined`. The built code looks like this:

```js
if ( undefined ) { // Wepack has replaced `process.env.IS_GUTENBERG_PLUGIN` with `undefined`
if ( undefined ) {
// Webpack has replaced `globalThis.IS_GUTENBERG_PLUGIN` with `undefined`
pluginOnlyFeature();
}
```
Expand Down Expand Up @@ -99,6 +102,6 @@ In this case, the minification process will remove the entire `if` statement inc

## Frequently asked questions

### Why shouldn't I assign the result of an expression involving `IS_GUTENBERG_PLUGIN` to a variable, e.g. `const isMyFeatureActive = process.env.IS_GUTENBERG_PLUGIN === 2`?
### 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](#dead-code-elimination) section.
6 changes: 5 additions & 1 deletion packages/block-library/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Breaking Changes

- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)).

## 8.35.0 (2024-05-16)

### Internal
Expand Down Expand Up @@ -84,7 +88,7 @@

### Breaking Changes

- Updated dependencies to require React 18 ([45235](https://github.com/WordPress/gutenberg/pull/45235))
- Updated dependencies to require React 18 ([#45235](https://github.com/WordPress/gutenberg/pull/45235))

## 7.19.0 (2022-11-16)

Expand Down
32 changes: 16 additions & 16 deletions packages/block-library/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -314,21 +314,21 @@ export const registerCoreBlocks = (
* __experimentalRegisterExperimentalCoreBlocks( settings );
* ```
*/
export const __experimentalRegisterExperimentalCoreBlocks = process.env
.IS_GUTENBERG_PLUGIN
? ( { enableFSEBlocks } = {} ) => {
const enabledExperiments = [ enableFSEBlocks ? 'fse' : null ];
getAllBlocks()
.filter( ( { metadata } ) =>
isBlockMetadataExperimental( metadata )
)
.filter(
( { metadata: { __experimental } } ) =>
__experimental === true ||
enabledExperiments.includes( __experimental )
)
.forEach( ( { init } ) => init() );
}
: undefined;
export const __experimentalRegisterExperimentalCoreBlocks =
globalThis.IS_GUTENBERG_PLUGIN
? ( { enableFSEBlocks } = {} ) => {
const enabledExperiments = [ enableFSEBlocks ? 'fse' : null ];
getAllBlocks()
.filter( ( { metadata } ) =>
isBlockMetadataExperimental( metadata )
)
.filter(
( { metadata: { __experimental } } ) =>
__experimental === true ||
enabledExperiments.includes( __experimental )
)
.forEach( ( { init } ) => init() );
}
: undefined;

export { privateApis } from './private-apis';
7 changes: 6 additions & 1 deletion packages/blocks/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Breaking Changes

- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)).

## 12.35.0 (2024-05-16)

## 12.34.0 (2024-05-02)
Expand Down Expand Up @@ -92,7 +96,8 @@

## 11.17.0 (2022-09-21)

- The block attribute sources `children` and `node` have been deprecated. Please use the `html` source instead. See https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/ and the core blocks for examples.
- The block attribute sources `children` and `node` have been deprecated. Please use the `html` source instead. See https://developer.wordpress.org/block-editor/how-to-guides/block-tutorial/introducing-attributes-and-editable-fields/ and the core blocks for examples.

## 11.16.0 (2022-09-13)

## 11.15.0 (2022-08-24)
Expand Down
2 changes: 1 addition & 1 deletion packages/blocks/src/api/parser/convert-legacy-block.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ export function convertLegacyBlockNameAndAttributes( name, attributes ) {

// The following code is only relevant for the Gutenberg plugin.
// It's a stand-alone if statement for dead-code elimination.
if ( process.env.IS_GUTENBERG_PLUGIN ) {
if ( globalThis.IS_GUTENBERG_PLUGIN ) {
// Convert pattern overrides added during experimental phase.
// Only four blocks were supported initially.
// These checks can be removed in WordPress 6.6.
Expand Down
4 changes: 4 additions & 0 deletions packages/components/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Breaking Changes

- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)).

### Enhancements

- `ComboboxControl`: Introduce Combobox expandOnFocus prop ([#61705](https://github.com/WordPress/gutenberg/pull/61705)).
Expand Down
5 changes: 1 addition & 4 deletions packages/components/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@
"gutenberg-test-env",
"jest",
"@testing-library/jest-dom"
],
// TODO: Remove `skipLibCheck` after resolving duplicate declaration of the `process` variable
// between `@types/webpack-env` (from @storybook packages) and `gutenberg-env`.
"skipLibCheck": true
]
},
"references": [
{ "path": "../a11y" },
Expand Down
7 changes: 6 additions & 1 deletion packages/core-data/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Breaking Changes

- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)).

## 6.35.0 (2024-05-16)

## 6.34.0 (2024-05-02)
Expand Down Expand Up @@ -97,7 +101,7 @@

### Breaking Changes

Add TypeScript types to the built package (via "types": "build-types" in the package.json)
– Add TypeScript types to the built package (via "types": "build-types" in the package.json)

## 4.14.0 (2022-08-24)

Expand Down Expand Up @@ -132,6 +136,7 @@
## 4.3.0 (2022-03-23)

### New Features

- The saveEntityRecord, saveEditedEntityRecord, and deleteEntityRecord actions now accept an optional throwOnError option (defaults to false). When set to true, any exceptions occurring when the action was executing are re-thrown, causing dispatch().saveEntityRecord() to reject with an error. ([#39258](https://github.com/WordPress/gutenberg/pull/39258))
- Added support for fetching block patterns and their categories, with the `getBlockPatterns` and `getBlockPatternCategories` selectors.

Expand Down
2 changes: 1 addition & 1 deletion packages/core-data/src/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ export const editEntityRecord =
}, {} ),
};
if ( window.__experimentalEnableSync && entityConfig.syncConfig ) {
if ( process.env.IS_GUTENBERG_PLUGIN ) {
if ( globalThis.IS_GUTENBERG_PLUGIN ) {
const objectId = entityConfig.getSyncObjectId( recordId );
getSyncProvider().update(
entityConfig.syncObjectType + '--edit',
Expand Down
4 changes: 2 additions & 2 deletions packages/core-data/src/entities.js
Original file line number Diff line number Diff line change
Expand Up @@ -485,7 +485,7 @@ export const getOrLoadEntitiesConfig =

if ( configs?.length > 0 && hasConfig ) {
if ( window.__experimentalEnableSync ) {
if ( process.env.IS_GUTENBERG_PLUGIN ) {
if ( globalThis.IS_GUTENBERG_PLUGIN ) {
registerSyncConfigs( configs );
}
}
Expand All @@ -506,7 +506,7 @@ export const getOrLoadEntitiesConfig =

configs = await loader.loadEntities();
if ( window.__experimentalEnableSync ) {
if ( process.env.IS_GUTENBERG_PLUGIN ) {
if ( globalThis.IS_GUTENBERG_PLUGIN ) {
registerSyncConfigs( configs );
}
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core-data/src/resolvers.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export const getEntityRecord =
entityConfig.syncConfig &&
! query
) {
if ( process.env.IS_GUTENBERG_PLUGIN ) {
if ( globalThis.IS_GUTENBERG_PLUGIN ) {
const objectId = entityConfig.getSyncObjectId( key );

// Loads the persisted document.
Expand Down
4 changes: 4 additions & 0 deletions packages/customize-widgets/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Breaking Changes

- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)).

## 4.35.0 (2024-05-16)

## 4.34.0 (2024-05-02)
Expand Down
2 changes: 1 addition & 1 deletion packages/customize-widgets/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ export function initialize( editorName, blockEditorSettings ) {
} );
registerCoreBlocks( coreBlocks );
registerLegacyWidgetBlock();
if ( process.env.IS_GUTENBERG_PLUGIN ) {
if ( globalThis.IS_GUTENBERG_PLUGIN ) {
__experimentalRegisterExperimentalCoreBlocks( {
enableFSEBlocks: ENABLE_EXPERIMENTAL_FSE_BLOCKS,
} );
Expand Down
4 changes: 4 additions & 0 deletions packages/dataviews/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Breaking Changes

- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)).

## 1.2.0 (2024-05-16)

### Internal
Expand Down
1 change: 0 additions & 1 deletion packages/dataviews/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
"compilerOptions": {
"rootDir": "src",
"declarationDir": "build-types",
"skipLibCheck": true,
"checkJs": false
},
"references": [
Expand Down
6 changes: 5 additions & 1 deletion packages/e2e-tests/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Breaking Changes

- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)).

## 7.29.0 (2024-05-16)

## 7.28.0 (2024-05-02)
Expand Down Expand Up @@ -64,7 +68,7 @@

### Breaking Changes

- Started requiring Jest v29 instead of v27 as a peer dependency. See [breaking changes in Jest 28](https://jestjs.io/blog/2022/04/25/jest-28) and [in jest 29](https://jestjs.io/blog/2022/08/25/jest-29) ([#47388](https://github.com/WordPress/gutenberg/pull/47388))
- Started requiring Jest v29 instead of v27 as a peer dependency. See [breaking changes in Jest 28](https://jestjs.io/blog/2022/04/25/jest-28) and [in jest 29](https://jestjs.io/blog/2022/08/25/jest-29) ([#47388](https://github.com/WordPress/gutenberg/pull/47388))

## 6.5.0 (2023-03-01)

Expand Down
9 changes: 3 additions & 6 deletions packages/e2e-tests/config/is-gutenberg-plugin.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
global.process.env = {
...global.process.env,
// Inject the `IS_GUTENBERG_PLUGIN` global, used for feature flagging.
// eslint-disable-next-line @wordpress/is-gutenberg-plugin
IS_GUTENBERG_PLUGIN: process.env.npm_package_config_IS_GUTENBERG_PLUGIN,
};
// eslint-disable-next-line @wordpress/wp-global-usage
globalThis.IS_GUTENBERG_PLUGIN =
process.env.npm_package_config_IS_GUTENBERG_PLUGIN === 'true';
4 changes: 4 additions & 0 deletions packages/edit-post/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### Breaking Changes

- Variables like `process.env.IS_GUTENBERG_PLUGIN` have been replaced by `globalThis.IS_GUTENBERG_PLUGIN`. Build systems using `process.env` should be updated ([#61486](https://github.com/WordPress/gutenberg/pull/61486)).

## 7.35.0 (2024-05-16)

### Internal
Expand Down
2 changes: 1 addition & 1 deletion packages/edit-post/src/components/visual-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import { usePaddingAppender } from './use-padding-appender';

const { EditorCanvas } = unlock( editorPrivateApis );

const isGutenbergPlugin = process.env.IS_GUTENBERG_PLUGIN ? true : false;
const isGutenbergPlugin = globalThis.IS_GUTENBERG_PLUGIN ? true : false;

export default function VisualEditor( { styles } ) {
const {
Expand Down
2 changes: 1 addition & 1 deletion packages/edit-post/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ export function initializeEditor(
registerCoreBlocks();
registerLegacyWidgetBlock( { inserter: false } );
registerWidgetGroupBlock( { inserter: false } );
if ( process.env.IS_GUTENBERG_PLUGIN ) {
if ( globalThis.IS_GUTENBERG_PLUGIN ) {
__experimentalRegisterExperimentalCoreBlocks( {
enableFSEBlocks: settings.__unstableEnableFullSiteEditingBlocks,
} );
Expand Down
Loading

0 comments on commit 539b07c

Please sign in to comment.