Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include blocks manifest build process in Webpack config to fix create-block bug with missing blocks manifest file #69578

Merged
merged 4 commits into from
Mar 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions packages/create-block/lib/init-package-json.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ module.exports = async ( {
build:
( isDynamicVariant
? 'wp-scripts build --webpack-copy-php'
: 'wp-scripts build' ) +
' && wp-scripts build-blocks-manifest',
: 'wp-scripts build' ) + ' --blocks-manifest',
format: 'wp-scripts format',
'lint:css': 'wp-scripts lint-style',
'lint:js': 'wp-scripts lint-js',
Expand All @@ -55,8 +54,7 @@ module.exports = async ( {
start:
( isDynamicVariant
? 'wp-scripts start --webpack-copy-php'
: 'wp-scripts start' ) +
' && wp-scripts build-blocks-manifest',
: 'wp-scripts start' ) + ' --blocks-manifest',
} ),
...( wpEnv && { env: 'wp-env' } ),
...customScripts,
Expand Down
4 changes: 4 additions & 0 deletions packages/scripts/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

## Unreleased

### New Features

- Add `--blocks-manifest` CLI flag to generate a PHP file containing block metadata from all `block.json` files in the project ([#79321](https://github.com/WordPress/gutenberg/pull/79321)).

## 30.13.0 (2025-03-13)

## 30.12.0 (2025-02-28)
Expand Down
8 changes: 3 additions & 5 deletions packages/scripts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ This script automatically use the optimized config but sometimes you may want to
- `--webpack-bundle-analyzer` – enables visualization for the size of webpack output files with an interactive zoomable treemap.
- `--webpack-copy-php` – enables copying all PHP files from the source directory ( default is `src` ) and its subfolders to the output directory.
- `--webpack-no-externals` – disables scripts’ assets generation, and omits the list of default externals.
- `--blocks-manifest` – generates a PHP file containing block metadata from all `block.json` files in the project. This is useful for enhancing performance when registering multiple block types, as it allows you to use `wp_register_block_metadata_collection()` and `wp_register_block_types_from_metadata_collection()` in WordPress.
- `--source-path` – allows customization of the source directory. The default is the project root `.` when [entry points are listed](#listing-entry-points) in the command, or `src` otherwise.
- `--output-path` – allows customization of the output directory. The default is the `build` folder.

Expand All @@ -105,11 +106,7 @@ This script uses [webpack](https://webpack.js.org/) behind the scenes. It’ll l

### `build-blocks-manifest`

This script generates a PHP file containing block metadata from all
`block.json` files in the project. This is useful for enhancing performance
when registering multiple block types, as it allows you to use
`wp_register_block_metadata_collection()` and
`wp_register_block_types_from_metadata_collection()` in WordPress.
This script generates a PHP file containing block metadata from all `block.json` files in the project. This is useful for enhancing performance when registering multiple block types, as it allows you to use `wp_register_block_metadata_collection()` and `wp_register_block_types_from_metadata_collection()` in WordPress.

Usage: `wp-scripts build-blocks-manifest [options]`

Expand Down Expand Up @@ -426,6 +423,7 @@ This script automatically use the optimized config but sometimes you may want to
- `--webpack-copy-php` – enables copying all PHP files from the source directory ( default is `src` ) and its subfolders to the output directory.
- `--webpack-devtool` – controls how source maps are generated. See options at https://webpack.js.org/configuration/devtool/#devtool.
- `--webpack-no-externals` – disables scripts’ assets generation, and omits the list of default externals.
- `--blocks-manifest` – generates a PHP file containing block metadata from all `block.json` files in the project. This is useful for enhancing performance when registering multiple block types, as it allows you to use `wp_register_block_metadata_collection()` and `wp_register_block_types_from_metadata_collection()` in WordPress.
- `--source-path` – allows customization of the source directory. The default is the project root `.` when [entry points are listed](#listing-entry-points) in the command, or `src` otherwise.
- `--output-path` – allows customization of the output directory. The default is the `build` folder.

Expand Down
25 changes: 25 additions & 0 deletions packages/scripts/config/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const ReactRefreshWebpackPlugin = require( '@pmmmwh/react-refresh-webpack-plugin
const TerserPlugin = require( 'terser-webpack-plugin' );
const { realpathSync } = require( 'fs' );
const { sync: glob } = require( 'fast-glob' );
const { exec } = require( 'child_process' );

/**
* WordPress dependencies
Expand All @@ -36,6 +37,7 @@ const {
getBlockJsonModuleFields,
getBlockJsonScriptFields,
fromProjectRoot,
fromScriptsRoot,
} = require( '../utils' );

const isProduction = process.env.NODE_ENV === 'production';
Expand All @@ -45,6 +47,7 @@ if ( ! browserslist.findConfig( '.' ) ) {
target += ':' + fromConfigRoot( '.browserslistrc' );
}
const hasReactFastRefresh = hasArgInCLI( '--hot' ) && ! isProduction;
const hasBlocksManifest = getAsBooleanFromENV( 'WP_BLOCKS_MANIFEST' );
const hasExperimentalModulesFlag = getAsBooleanFromENV(
'WP_EXPERIMENTAL_MODULES'
);
Expand Down Expand Up @@ -260,6 +263,26 @@ if ( baseConfig.devtool ) {
} );
}

/**
* Build blocks manifest.
*/
class BlocksManifestPlugin {
/**
* Apply the plugin.
*
* @param {webpack.Compiler} compiler The compiler instance.
*/
apply( compiler ) {
compiler.hooks.afterEmit.tap( 'BlocksManifest', () => {
exec(
`node ${ fromScriptsRoot(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed here two things in d01a653.

  1. Use the local script rather than wp-scripts executable so it can run locally in non-standard way. The way I usually test changes is by running ../node_modules/.bin/wp-scripts start --blocks-manifest --output-path=dist from the scaffolded block without the npm packages installed. This way I can use the latest version of wp-scripts from the Gutenberg repository.
  2. I added a way to change the --input param in the case when someone decides the build folder should live in a different location.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for these fixes!

'build-blocks-manifest'
) } --input="${ compiler.options.output.path }"`
);
} );
}
}

/** @type {webpack.Configuration} */
const scriptConfig = {
...baseConfig,
Expand Down Expand Up @@ -397,6 +420,8 @@ const scriptConfig = {
} ),
// RtlCssPlugin to generate RTL CSS files.
new RtlCssPlugin(),
// Generate blocks manifest after changes.
hasBlocksManifest && new BlocksManifestPlugin(),
// React Fast Refresh.
hasReactFastRefresh && new ReactRefreshWebpackPlugin(),
// WP_NO_EXTERNALS global variable controls whether scripts' assets get
Expand Down
8 changes: 3 additions & 5 deletions packages/scripts/scripts/build-blocks-manifest.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,17 @@ const chalk = require( 'chalk' );
*/
const { getArgFromCLI } = require( '../utils' );

// Set default paths
// Parses command line arguments.
const defaultInputDir = 'build';
const defaultOutputFile = path.join( 'build', 'blocks-manifest.php' );

// Parse command line arguments
const inputDir = getArgFromCLI( '--input' ) || defaultInputDir;
const defaultOutputFile = path.join( inputDir, 'blocks-manifest.php' );
const outputFile = getArgFromCLI( '--output' ) || defaultOutputFile;

const resolvedInputDir = path.resolve( process.cwd(), inputDir );
if ( ! fs.existsSync( resolvedInputDir ) ) {
const ERROR = chalk.reset.inverse.bold.red( ' ERROR ' );
process.stdout.write(
`${ ERROR } Input directory "${ inputDir }" does not exist.\n`
`${ ERROR } Input directory "${ resolvedInputDir }" does not exist.\n`
);
process.exit( 1 );
}
Expand Down
5 changes: 5 additions & 0 deletions packages/scripts/utils/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,7 @@ const hasPostCSSConfig = () =>
const getWebpackArgs = () => {
// Gets all args from CLI without those prefixed with `--webpack`.
let webpackArgs = getArgsFromCLI( [
'--blocks-manifest',
'--experimental-modules',
'--source-path',
'--webpack',
Expand Down Expand Up @@ -146,6 +147,10 @@ const getWebpackArgs = () => {
process.env.WP_NO_EXTERNALS = true;
}

if ( hasArgInCLI( '--blocks-manifest' ) ) {
process.env.WP_BLOCKS_MANIFEST = true;
}

const hasWebpackOutputOption =
hasArgInCLI( '-o' ) || hasArgInCLI( '--output' );
if (
Expand Down
10 changes: 8 additions & 2 deletions packages/scripts/utils/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,22 @@ const {
hasPostCSSConfig,
hasPrettierConfig,
} = require( './config' );
const { fromProjectRoot, fromConfigRoot, hasProjectFile } = require( './file' );
const {
fromConfigRoot,
fromProjectRoot,
fromScriptsRoot,
hasProjectFile,
} = require( './file' );
const { getPackageProp, hasPackageProp } = require( './package' );
const {
getBlockJsonModuleFields,
getBlockJsonScriptFields,
} = require( './block-json' );

module.exports = {
fromProjectRoot,
fromConfigRoot,
fromProjectRoot,
fromScriptsRoot,
getAsBooleanFromENV,
getArgFromCLI,
getArgsFromCLI,
Expand Down
Loading