A simpler way to add SVGs to custom WordPress (Gutenberg) blocks using SVGR

For the past several months I’ve been developing a new course about custom WordPress block development for LinkedIn Learning. Early on in the process I started looking for a simple way to add custom SVGs to custom blocks. The solution (or more specifically a solution) was found deep inside Create React App: SVGR.

From the SVGR documentation:

SVGR transforms SVG into ready to use components. It is part of create-react-app and makes SVG integration into your React projects easy.

SVGR documentation

Unifying custom block development with @wordpress/scripts

To take full advantage of the features of both the WordPress block editor and modern JavaScript, you need to use some combination of Webpack and Babel to introduce full support for ECMAScript 2015. Configuring Webpack and Babel and all the necessary WordPress packs and everything else can be a challenge. To make things simpler, the Gutenberg team has released @wordpress/scripts aka wp-scripts, a “collection of reusable scripts for WordPress development.” This package has now been updated to include configurations for Webpack and Babel to provide a unified build process for the WordPress community.

Using SVGR in WordPress (Gutenberg) block development

In my own block development I’d been using a custom Webpack + Babel + a bunch of other stuff setup. This setup included SVGR for simplified SVG inclusion. Last week I refactored my build process to using @wordpress/scripts and in the process had to figure out how to extend the pre-packaged webpack configuration to include my custom script.

Since there’s a good chance you’ll want to add some SVG magic to your WordPress blocks, I figured I’d share my findings with you here. I’ve also added a simplified code example to the official @wordpress/scripts documentation.

By the end of this process, you’ll be able to

  • turn any SVG into a React component
  • have that SVG output inline by calling the React component
  • add the SVG as a base64 encoded image element if you want to call it directly from the src attribute inside an <img> element

For this we need two packages: @svgr/webpack and url-loader.

Here’s the full breakdown (this assumes you are already using @wordpress/scripts):

From within your project folder where package.json resides, run the following commands in terminal:

npm install @svgr/webpack --save-dev 
npm install url-loader --save-dev 

Create a new webpack.config.js file.

Require the original webpack.config.js from @wordpress/scripts:

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

Extend the existing config with custom settings for @svgr/webpack and url-loader:

module.exports = {
  ...defaultConfig,
  module: {
    ...defaultConfig.module,
    rules: [
      ...defaultConfig.module.rules,
      {
        test: /\.svg$/,
        use: ["@svgr/webpack", "url-loader"]
      }
    ]
  }
};

Place your SVG(s) in the /src folder of your project.

In your index.js file (where you’re using registerBlockType()), import the SVG:

import customLogoURL, { ReactComponent as customLogo } from "./logo.svg"; 

Now you can call customLogoURL (the SVG transformed into a base64 encoded URI) and customLogo (the React component) from anywhere within your block definition. Example:

registerBlockType("block/myblock", {
  title: __("A Block", "myblocs"),
  icon: {
    src: customLogo // The React component
  },
  category: "regular",
  attributes: {
    blockImage: {
      type: "string",
      default: customLogoURL // The base64 encoded URI
    }
  },
  (...)
}

Cool, right? And clean and easy to read.

Stay tuned for my upcoming LinkedIn Learning course on WordPress Block Development where you’ll learn more about how to build your own custom blocks!


Cross-posted to LinkedIn Pulse.