WordPress & Webpack – “Hey, that’s pretty easy!”

Webpack is awesome – and using it with wordpress is easy! Beyond performance increases – Webpack can greatly improve your development experience.

In this post I will demonstrate how I setup my WordPress theme to use Babel and BrowserSync.

This tutorial assumes you have a development environment setup. This blank storefront child theme is perfect for quick modifications and working through tutorials.

Setup

If you want to follow the tutorial, you’ll want a local wordpress installation and npm. If you want to use blank theme to follow the tutorial, cd into your themes folder and clone the repository above.

$ git clone https://github.com/gerrgg/storefront-child-theme-starter.git
$ cd storefront-child-theme-starter.git

Activate the theme and visit the site – you should see “hello” in the top left corner if the theme installed properly.

Webpack?

If you’ve never used Webpack – its a build tool which compiles your code into static optimized assets. Not only does Webpack greatly improve load times – it enables the use of tools like Babel to compile ES6 to ES5 or BrowserSync for automatic browser reloads on save.

$ npm install webpack

First install Webpack – (use npm init --yes if you dont have package.json file).

$ npm i --save-dev webpack webpack-cli

Next set the webpack scripts in your package.json file – this is what we will run to actually use webpack later.

{
  "name": "webpack-and-wordpress",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "dev-build": "webpack --mode development",
    "pro-build": "webpack --mode production",
    "watch": "webpack --watch --mode development"
  },
"keywords": [],
...
}

Webpack Configuration

Webpack is incredibly configurable and will work with just about anything – even WordPress.

First, we are going to create a the configuration file at the root of our project.

$ touch webpack-config.js

Next setup of the configuration file for configuring :D.

// webpack-config.js

// Require path.
const path = require("path");

const config = {
// do configuring here
}

// Export the config object.
module.exports = config;

Entry Points

First, we have to setup the entry points. The entry point is the file that imports in all your other files.

An entry point indicates which module webpack should use to begin building out its internal dependency graph.

https://webpack.js.org/concepts/#entry

In wordpress its helpful to separate your frontend and your backend – so we will have two entry points.

Setup the files & add the entry points

Create two files at /src/frontend/front-index.js and /src/admin/admin-index.js.

Then add the entry points to the configuration file.

// webpack-config.js
...
const path = require("path");

const config = {
  entry: {
    frontend: "./src/frontend/front-index.js",
    admin: "./src/admin/admin-index.js",
  },
}
...

Output

The output is where the bundled assets will be put and how to name them – these are the files we will be enqueuing into our wordpress theme or plugin.

The output property tells webpack where to emit the bundles it creates and how to name these files. It defaults to ./dist/main.js for the main output file and to the ./dist folder for any other generated file.

https://webpack.js.org/concepts/#output

Next configure where out bundled assets will be put – we have two so we use the [name] syntax which Webpack knows means “use the key from the entry points”.

We also set the path for these compiled files to end up in the ‘assets’ folder.

output: {
    filename: "js/[name].js",
    path: path.resolve(__dirname, "assets"),
  },

This results in all our frontend JavaScript being compiled to /assets/js/frontend.js and all our admin code at /assets/js/admin.js.

The finished webpack-config.js

So we built a webpack-config.js file at the root of our project – which lets Webpack know where our JavaScript files are now and where the compiled results should go.

The finished Webpack configuration looks like this:

// webpack-config.js

// Require path.
const path = require("path");

const config = {
  entry: {
    frontend: "./src/frontend/front-index.js",
    admin: "./src/admin/admin-index.js",
  },
  output: {
    filename: "js/[name].js",
    path: path.resolve(__dirname, "assets"),
  },
};

// Export the config object.
module.exports = config;

Use webpack with wordpress

As mentioned above – using Webpack has a massive net positive affect on your applications performance and your personal development experience. Webpack and wordpress work beautifully together and allow for massive gains in versatility in your wordpress development.

“Hello” from the front

First add a simple console.log() to our source JavaScript files (the before).

// /src/frontend/front-index.js

console.log('hello from the front')
// /src/admin/admin-index.js

console.log('hello from the back')

Enqueue compiled assets

Now we are ready to use wp_enqueue_script to hook up our compiled assests with out wordpress theme or plugin.

Note that frontend and admin scripts are enqueued on different hooks – you’ll need two functions in your functions.php file.

<?php

// Enqueue frontend scripts

add_action("wp_enqueue_scripts", "greg_bastianelli_enqueue_frontend_scripts");

function greg_bastianelli_enqueue_frontend_scripts()
{
  wp_enqueue_script(
    "frontend", // handle
    get_stylesheet_directory_uri() . "/assets/js/frontend.js", //uri
    ["jquery"], // dependencies
  );
}

// Enqueue admin scripts

add_action("admin_enqueue_scripts", "greg_bastianelli_enqueue_admin_scripts");

function greg_bastianelli_enqueue_admin_scripts()
{
  wp_enqueue_script(
    "admin",
    get_stylesheet_directory_uri() . "/assets/js/admin.js",
    ["jquery"]
  );
}

npm run watch && visit site

Now time to see all your hard work pay off – if we’ve done everything correctly all we gotta do is run our watch script and see the compiled results.

Go to your command line and type npm run watch

Visit your site and see your console.log().

What did that do?

That was alot of work – and all we did was console.log a silly message – why did I even bother writing this?

Setting up Webpack with our theme has provided us limitless potential.

Cuts down on HTTP Requests

First – by bundling our JavaScript files we no longer suffer from having to make 100 different HTTP requests all our JS files. This DRAMATICALLY cuts down on load times if you’ve chosen the sane route of modularization your code.

Promotes better code

Second – if by chance you are a maniac such as myself at one point (this year) you went for performance over sanity and stuffed thousands of code into a single file which fueled your entire project.

By using webpack – you dont have to do this. You can have a beautifully organized project with lots of different files & functionality automatically compiled into easy-to-digest static files for the browser to munch on.

Your quality of your code greatly improves by modularizing your code into little bits – improving bug resistance, readability and your sanity.

Loaders and plugins

Loaders and plugins multiply the vast number of opportunities provided by webpack * 11.I wont get into the nitty-gritty right now – click those links if your interested.

I’m most interested in installing Babel and BrowserSync

Babel

What is BabelJS?

Babel is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments.

https://babeljs.io/docs/en/#babel-is-a-javascript-compiler

Essentially – babel lets us write code in higher level forms for developer enjoyment and automatically converts it into more compatible code all browsers can understand.

Install Babel

First we are going to Install babel and a few of its dependencies.

$ npm install --save-dev babel-loader @babel/core @babel/cli @babel/preset-env

Next create a babelrc.json file at the root of your project – this is where babel will automatically look for any configurations we’ve added.

{
  "presets": ["@babel/preset-env"]
}

Finally add a module to your webpack configuration file to run all Javascript through the babel-loader we installed and setup.

Add this after output in webpack-config.js.

...
},  

module: {
    rules: [
      {
        // Look for any .js files.
        test: /\.js$/,
        // Exclude the node_modules folder.
        exclude: /node_modules/,
        // Use babel loader to transpile the JS files.
        loader: "babel-loader",
      },
    ],
  },
...

Test Babel

To test babel all we need to do is run npm run watch and cat assets/js/frontend.js to see the compiled results – but if all we have is a console.log('hello') babel’s not going to have much to do – lets do something ES6(-y).

Create a file at src/frontend/hello.js

// /src/frontend/hello.js

const hello = () => console.log("hello");

export default hello;

If this looks funky – all we are doing is using some new ES6 syntax and setting up the default export to be the hello function we created.

Now in your frontend entry point file src/frontend/front-index.js delete the console.log statement and import in our hello module we just created.

Your front-index.js file should look like this now:

// /src/frontend/front-index.js

import hello from "./hello";

hello();

Run npm run watch (if your not already) to compile your code.

The browser friendly compiled results

The output is what you might expect – a simple “hello” logged to the console, but if you look at assets/js/frontend.js you’ll see that babel did quite alot.

And that is just one small example of how awesome BabelJS – It allows us to write ES6 and automatically converts it to a more compatible version of JavaScript.

But you know whats annoying? Saving and CTRL+R everytime we make a modfication – and if you’ve used something like Create React App you know exactly what your missing.

Automatic/Hot Reload with BrowserSync

Hot reload is one of the coolest things I’ve ever done to up my DEV game and its surprisingly easy to setup with Webpack.

We are going to use something called BrowserSync. Essentially all it does is automatically reload the browser EVERYTIME we CTRL+S our files.

Install BrowserSync and setup webpack-config

First install BrowserSync and the browser-sync-webpack-plugin.

$ npm install --save-dev browser-sync browser-sync-webpack-plugin

Next require the plugin in your webpack-config.js file at the root of your project.

// webpack-config.js

// Require path.
const path = require("path");

const BrowserSyncPlugin = require('browser-sync-webpack-plugin')

const config = {

At the bottom of the config file (just before the end of the config object) add BrowserSync as a Webpack plugin.

...

 },
  plugins: [
    new BrowserSyncPlugin({
      files: "**/*.php",
      proxy: "http://your.devserver.here", // your dev server here
    }),
  ],
};

// Export the config object.
module.exports = config;

Above we are adding BrowserSync to Webpack.

Files

We set files: "**/*.php" – telling webpack to watch for changes in our .php files and reload the browser when they do.

Proxy

We set proxy: "http://your.devserver.here"so browser sync knows which server to proxy all the files from.

Essentially this is where your local wordpress environment is setup – mine was at "http://one.wordpress.test" and I am using VVV.

“Hello automatic browser refresh”

Run Webpack npm run watch and a tab should open at http://localhost:3000/ with your wordpress installation running.

Go ahead – write something in the functions.php file to test it out like: “Hello automatic browser refresh”

Webpack is awesome

As you can see Webpack is awesome – this just the surface of awesomeness presented by the tool. As I learn more about webpack I will try to add what I learn and share how to create the ultimate Webpack setup.

Table of Contents