• Migrating block based plugins from webpack to wp-scripts

    Migrating block based plugins from webpack to wp-scripts

    When WordPress 5.8 was released I discovered that some of my block based plugins caused messages in the new block based widget editor.

    I decided that I needed to update my block based plugins so that they were built using the latest version of the block API. Some of the plugins needed migrating from a hand cranked webpack build. Others just needed the changes for apiVersion:2.

    In this post:

    Problems with the new Widget block editor in WordPress 5.8

    In a number of plugins I have wp-editor listed as a dependency on the wp_register_script() for the blocks. This is the old style of registering blocks. The new Widgets block editor doesn’t care for this and issues a _doing_it_wrong Notice.

    The blocks required wp-editor in order to use Server Side Rendering. For webpack build they accessed ServerSideRender using

    const { ServerSideRender } = wp.editor;

    For wp-scripts using version 1 of the API they were using

    import { ServerSideRender } from '@wordpress/editor';

    If Server Side Rendering is needed then the code needs to be changed as below, otherwise the import, and therefore the dependency, can be removed.

     import ServerSideRender from '@wordpress/server-side-render';

    In order to implement this change the blocks that are built using webpack need to be converted to use wp-scripts and to use apiVersion:2 for block registration.


    Steps to migrate to wp-scripts

    • Change the JavaScript from const to import
    • Remove unnecessary files
    • Change package.json
    • Change / create  block.json for each block
    • Change each block’s Server Side Registration to register the block from block.json
    • Change each block’s index.js to register the block
    • Change each block’s outer wrapper
    • Update node_modules and rebuild
    • Internationalize and localize

    Change the JavaScript from const to import

    Change the references to functions

    Fromconst { __ } = wp.i18n;
    const { registerBlockType } = wp.blocks;
    const { ServerSideRender } = wp.editor;
     
    Toimport {__} from "@wordpress/i18n";
    import { registerBlockType } from '@wordpress/blocks';
    import ServerSideRender from '@wordpress/server-side-render';

    Add other imports for apiVersion 2

    import { useBlockProps } from '@wordpress/block-editor';

    Remove unnecessary files

    Delete the files used by the original webpack build that aren’t needed by wp-scripts.

    • webpack.config.js 
    • .babelrc

    Change package.json

    Update package.json to implement the wp-scripts commands. The standard scripts are:

    "scripts": {
            "build": "wp-scripts build",
            "format": "wp-scripts format",
            "lint:css": "wp-scripts lint-style",
            "lint:js": "wp-scripts lint-js",
            "start": "wp-scripts start",
            "packages-update": "wp-scripts packages-update"
            "dev": "wp-scripts start"
    },

    Note: dev is an alias of start.

    Additionally, for internationalization, translation and localization, I add the following commands. Here they’re customized for the sb-starting-block plugin.

    "makepot": "wp i18n make-pot . languages/sb-starting-block.pot --exclude=node_modules,vendor,src/*.js",
    "makejson": "wp i18n make-json languages --no-purge",
    "l10n": "l10n sb-starting-block"

    dependencies and devDependencies will also need updating. These are the latest entries in the package.json file created by npx @wordpress/create-block.

    "dependencies": {
            "@wordpress/block-editor": "^7.0.2",
            "@wordpress/blocks": "^11.1.0",
            "@wordpress/i18n": "^4.2.2"
    },
    "devDependencies": {
            "@wordpress/scripts": "^18.0.1"
    }

    To update an existing plugin to the latest versions run the packages-update command.

    npm run packages-update

    Change / create block.json for each block

    For a multi-block plugin put the block.json file for each block in its own folder within the src folder. For a single block plugin the file can be in the plugin’s root directory.

    For example the file src/starting-block/block.json might be:

    {
            "apiVersion": 2,
            "name": "oik-sb/sb-starting-block",
            "title": "Starting block",
            "category": "widgets",
            "icon": "megaphone",
            "description": "Starting block - Server Side Rendered",
            "supports": {   },
            "textdomain": "sb-starting-block",
            "editorScript": "file:../../build/index.js",
            "editorStyle": "file:../../build/index.css",
            "style": "file:../../build/style-index.css"
    }

    Notes:

    • apiVersion set to 2.
    • supports may contain many attributes. See below.
    • editorScript, editorStyle and style indicate the directory for the build files.
    "supports": {
            "align": true,
            "html": false,
            "customClassName": true,
            "className": true,
            "color": {
              "gradients": true,
              "text": true,
              "background": true
            },
            "typography": {
              "fontSize": true,
              "lineHeight": true
            },
            "padding":  true
      },

    The supports structure provides many configurable settings. If you include color and typography then, for Server Side Rendered blocks, additional fields need to be defined in attributes where the setting is true.

    Note: The block’s supports attributes can be overriden by the theme’s theme.json file.

    Change each block’s Server Side Registration to register the block from block.json

    Register the block using the metadata loaded from the block.json file. For a dynamic block the callback function is passed in the $args array.

    function oik_sb_sb_starting_block_block_init() {
            $args = [ 'render_callback' => 'oik_sb_sb_starting_block_dynamic_block'];
            register_block_type_from_metadata( __DIR__ . '/src/starting-block', $args );
    }
    add_action( 'init', 'oik_sb_sb_starting_block_block_init' );

    Change each block’s index.js to register the block

    Change the block registration to use the definition from the server registration. The settings parameter doesn’t include values that are now defined in block.json.

    registerBlockType( 'oik-sb/sb-starting-block', {
            edit: Edit,
            save
    } );

    Change each block’s outer wrapper

    In the JavaScript code change the Edit function to use useBlockProps(). This function will set class names for the supports settings defined in block.json.

    export default function Edit ( { attributes, className, isSelected, setAttributes } ) {
            const { textAlign } = attributes;
            const blockProps = useBlockProps( {
                    className: classnames( {
                            [ `has-text-align-${ textAlign }` ]: textAlign,
                    } ),
            } );
            return (
                    <div { ...blockProps}>
                       <ServerSideRender block="oik-sb/sb-starting-block" attributes={attributes}
                        />
                    </div>
            );
    }

    In this example the value of the textAlign control is also being taken into account.

    For Server Side rendered code the equivalent logic is implemented using get_block_wrapper_attributes().

    function oik_sb_sb_starting_block_dynamic_block( $attributes ) {
            $classes = '';
            if ( isset( $attributes['textAlign'] ) ) {
                    $classes .= 'has-text-align-' . $attributes['textAlign'];
            }
            $wrapper_attributes = get_block_wrapper_attributes( array( 'class' => $classes ) );
            $content = __( 'Starting block.', 'sb-starting-block');
            $html = sprintf( '<div %1$s>%2$s</div>', $wrapper_attributes, $content );
            return $html;
    }

    For some blocks it may also be necessary to apply this wrapper during save. In this case you need to use useBlockProps.save().

    save: props => {
            const blockProps = useBlockProps.save();
                return(
                    <div {...blockProps} >
                        <Dashicon icon={props.attributes.dashicon} />
                    </div>
                );
    }

    Update node_modules and rebuild

    The node_modules used in the webpack build need to be replaced by the modules needed by wp-scripts. To get a working version of wp-scripts use the following steps.

    1. Change to the plugin’s root directory.
    2. Remove the existing node_modules folder
    3. npm install
    4. npm install @wordpress/scripts --save-dev

    Once installed the blocks can be rebuilt

    • npm run dev – for the development build
    • npm run build – for a production release

    Internationalize and localize

    When the blocks have been rebuilt and tested in the widget block editor then the internationalization ( i18n ), translation and localization ( l10n ) can be implemented. See Internationalizing and localizing block based plugins.


    Summary of plugins and GitHub issues

    If you want to read more about my implementation then you’ll find it’s fairly well annotated in my GitHub issues. Some of these plugins are multi-block plugins, others are single block. All of them are available from oik-plugins.com, several are on wordpress.org.

    Plugins Original build GitHub issue(s)
    oik webpack bobbingwide/oik#177
    oik-blocks webpack bobbingwide/oik-blocks#47
    oik-bob-bing-wide webpack bobbingwide/oik-bob-bing-wide#42
    oik-css webpack bobbingwide/oik-css#16
    oik-magnetic-poetry webpack bobbingwide/oik-magnetic-poetry#4
    oik-squeeze wp-scripts bobbingwide/oik-squeeze#13
    sb-breadcrumbs-block wp-scripts bobbingwide/sb-breadcrumbs-block#7
    sb-chart-block wp-scripts bobbingwide/sb-chart-block#13
    sb-children-block wp-scripts bobbingwide/sb-children-block#5
    sb-coming-up wp-scripts bobbingwide/sb-coming-up#2
    sb-field-block wp-scripts
    sb-post-edit-block wp-scripts bobbingwide/sb-post-edit-block#5
    sb-prevnext-block wp-scripts
    sb-starting-block wp-scripts bobbingwide/sb-starting-block#2
    sb-toolicons-block wp-scripts
    uk-tides webpack bobbingwide/uk-tides#9

    References



    Published:

    Last updated:

    October 16, 2021

Categories

Tide times from tidetimes.org.uk

Tide Times & Heights for Langstone Harbour on
28th March 2023
04:31 High Tide ( 4.23m )
09:38 Low Tide ( 1.66m )
16:58 High Tide ( 4.06m )
21:59 Low Tide ( 1.94m )

Tide times from tidetimes.org.uk

Tide Times & Heights for Northney on
28th March 2023
04:51 High Tide ( 4.02m )
09:45 Low Tide ( 1.26m )
17:24 High Tide ( 3.79m )
22:09 Low Tide ( 1.6m )
WordPress version:6.1.1
Gutenberg version:15.2.0

Summary file