webpackadvanced-custom-fieldswordpress-gutenberggutenberg-blocksacf-gutenberg

packaging block.json renderTemplate in basic webpack setup using @wordpress scripts


On a Wordpress install, I am using ACF Blocks with “block.json”, where my blocks are compiled from a /source directory to a /build directory, where they are registered via register_block_type. I’m using a relatively default variation of @wordpress/scripts/config/webpack.config for compiling/building.

My issue is that “render.php” will not copy over into my build directory unless I include the “render” property ("render": "file:./render.php") in block.json. But if I include that, then it overrides the ACF block render template (renderTemplate": "render.php"), and the template is interpreted as a standard block template and not an ACF block template.

Is there are straightforward workaround for this, or is this something I need to work out manually in my “webpack.config.js”? I’m pretty new to webpack configuration, and all I can think of is to create a new entry point in modules.exports for each of the render.php files, but I feel like that’s a really inefficient way to do it, since the default config already works as it should.

Would it make the most sense to use a webpack plugin such as replace-in-file-webpack-plugin to just remove the render property string in block.json from the build file?

Or there perhaps a function or filter that could force the ACF renderTemplate over the core “render”, even when “render” is present in block.json?

I feel like I can't be the first to encounter this, but I'm not seeing what the standard solution is.

Simple file structure:

src
|--blocks
| |-- carousel
| | |-- block.json
| | |-- render.php
| |-- anotherBlock
| | |-- block.json
| | |-- render.php
build
|--blocks
| |-- carousel
| | |-- block.json
| | |-- render.php
| |-- anotherBlock
| | |-- block.json
| | |-- render.php

Registration:

function my_register_acf_blocks() {
  register_block_type(dirname(__DIR__, 1) . '/build/blocks/carousel' );
  register_block_type(dirname(__DIR__, 1) . '/build/blocks/anotherBlock' );
}
add_action( 'init', 'my_register_acf_blocks' );

Relevant lines of block.json:

{
  "$schema": "https://schemas.wp.org/trunk/block.json",
  "apiVersion": 3,
  "name": "acf/carousel",
  "title": "Image or Video Carousel with Overlay",
  "render": "file:./render.php", //<-- webpack won't copy render.php to build without this line, but it breaks ACF block when present
  "script": "file:./index.js",
  "style":  ["splide", "file:./style-index.css"],
  "acf": {
    "mode": "edit",
    "renderTemplate": "render.php"
  }
}

webpack.config.js

const defaultConfig = require( '@wordpress/scripts/config/webpack.config' );

module.exports = {
    ...defaultConfig,
    entry: {
        ...defaultConfig.entry(),
        index: './src/index.js',
        loginStyles: './src/sass/login-styles.scss',
        splide: './src/js/splide.js'
    },
};

Solution

  • Based on your project structure, to copy the .php files to build as intended, for your build process, try:

    npm wp-scripts build --webpack-copy-php
    

    This will copy all .php files contained within blocks registered via your my_register_acf_blocks() function.

    If you created the original project with @wordpress/create-block, its good idea to update package.json with --webpack-copy-php for projects that contain multiple blocks with dynamic rendering, eg:

    package.json

    {
        "name": "my-blocks",
         ...
        "scripts": {
            ...
            "build": "wp-scripts build --webpack-copy-php",
            "start": "wp-scripts start --webpack-copy-php"
        },
    ...
    }
    

    Then when you run npm plugin-zip, all your files should be built and bundled correctly.