Updating Webpack to use WordPress editor blocks (Gutenberg blocks) on the front end (part 4 of 4)
Getting blocks running on the front end is, or should be, mainly a matter of updating Webpack to create the script to run on the front end, then enqueuing it so it does. However, I’ve always found it requires some fixing of things that don’t work quite right together, that I’ve misnamed or otherwise mismatched so I’ll go through those changes too.
Updating Webpack to build a front end script
Let me start with a caveat here: this may not be the best way to do it. It is definitely not the only way to do it. However. It works! I don’t know the internals of wp-scripts and it’s not super well documented . (This is one of the reasons it would be useful to be able to eject from wp-scripts – I’d love to have a dummy project and be able to tweak a setting and see what happens. The default Webpack config is here and I suppose I could copy and paste.)
The short of it
The short of it: I’ve put the out of the box editor config in a variable and then added in a front end config and exported both.
The long of it is explaining the front end config. 😊
frontEndConfig looks like this:
It uses the spread operator to add the default config as a starting point. There were a few things I had to change and I’ve added in stats for debugging purposes, you can remove that bit if you don’t like it.
I’ve made a new entry point for the front end, front-index.js:
It picks up everything with a class of “porchy” (this really should be way more specific), then iterates over the elements, going through this process for each one:
grabs the data-attr of the element to get the block’s attributes as a string
grabs the the data-block of the element to get the blockname
parses the attributes string into JSON
figures out which component to use by the blockname (additional blocks should be added to blockNameToComponents object with the full blockname as the key and the component as the value – remember to import the component)
renders the component into the element
For whatever reason wp-scripts helpfully cleans the build folder of anything it thinks is not supposed to be in there. So I’m using dist as the front end folder. Whatever. I’m bringing in the default config and then explicitly setting the folder and filename even though I found if I left "output" blank it worked the same way. (I’ve learned not to trust default behaviour with WordPress plugins and the block editor seems particularly unstable this way.) This is what is enqueued on the front end.
I like this, I love seeing things scroll down the terminal, but it’s not at all necessary.
Importing the default config here causes the front end build to fail so I’ve included what I want:
Browsersync plugin for front end syncing. It uses an update frontEndEnv variable – add this to local.json, mine ends up looking like the following – and you’ll also need to set the variable in your Webpack config.
DependencyExtractionWebpackPlugin (this needs to be explicitly required at the top of the file or it fails). This is the plugin which builds the php assets file which will end up in the output folder set previously, dist.
Including the built script on the front end
Once I had the script, I needed to include it on the front end. This is done the same way as including it in the editor, albeit on a different hook (there might be a better hook than init 😬). Here’s what that looks like:
You may notice in the diff that there is additional bits to make it work on Gatsby, ie here where you’re reading this (most likely). I’m not going to go over that now, this is too long already. I’ll try and post on that later.
I am incapable of keeping names straight the first time around and there were a number of issues I had to fix to make it all work happily together.
I moved the admin index.js entry file from the blocks directory. This is my preference. I would have renamed it decided against it. Writing this, I noticed my package.json has the wrong filename, argh, will fix that later. It still builds.
Delicateness and future changes
The way I’m picking up the elements in front-index.js isn’t robust at all and could easily break if someone else uses the same class of the elements picked up (in this case it’s “porchy”). Maybe next time I’ll add the version number to the class for something like porchy-ab7fb51d103d94d2f7f578f1674385ed, set the version number in a localised variable and then pick it up to build the class name in front-index.js.
Let me know what I’ve missed here or anything unclear.