Skip to content
Tutorial

Webpack and WordPress – The Missing Documentation

Making the move from gulp to Webpack for WordPress development – don't do it
Summary: Webpack is not the best fit for WordPress development. It may sound like a little thing, but I can’t go back to waiting for a page to reloads. I’ve been spoiled by Browsersync's CSS injection in Gulp, and Webpack's hot media replacement in React development, neither of which work in this environment.

If you want to skip the explanation, you can view the full source code for the package file and the three build environment Webpack config files.

Why I switched to Webpack

For some time, each new project I started has begun by passing along the same trusty gulp config and package file from one WordPress development project to the next. I modify it slightly here and there along the way, and sure, maybe it is a little bloated now, but it has got all the build tools I need. Until recently, it has served me well.

I recently had to install OCaml on my machine. This meant I needed to update Homebrew, which then required me to update Node. Of course, after doing that, I found out gulp 3 no longer works with the newest Node version. Upgrading to gulp 4 would mean I'd have to rewrite my config file and update several of my dependencies.

This all happened while starting a new plugin development project that looked to be more javascript dependent than usual—specifically, in its reliance on external libraries.

Between my dependency hell and my fondness for new toys, I figured if I was rebuilding anyway, why not try it in Webpack. I had been working with Webpack on some React projects and appreciated the cleanliness of module imports.

Simple build requirements

My requirements were simple, I needed an SCSS compiler and post-processor, a javascript importer/concatenator for development, and I needed it to watch for changes and recompile and reload. Being a WordPress project, the CSS and JS had to build to separate files, and the page had to preview from my local webserver for development. A pretty basic requirement list, but nowhere on the internet could I find documentation on how to do this.

Webpack build scripts in the package file

There are three environment modes I need Webpack to run in:

  1. Dev Mode: A fast and lean build that runs the CSS compilation, js concatenation, and starts up a Browsersync server.
  2. Testing mode: adds backward browser compatibility via post CSS and babel.
  3. And finally, the build version adds in the minification layer.

Each is handled by its own config file, called via scripts in the package.json file.

Add these "scripts" to your package.json file.

"scripts": {
  "build": "webpack --config webpack.config.prod.js",
  "start": "webpack --config webpack.config.dev.js --progress --watch",
  "test": "webpack --config webpack.config.test.js --progress --watch"
},

From here I’m just going to look at the dev file because that’s where I found the internet documentation lacking, but I’ll include all the files at the end.

Steps to Setting up Webpack 4 plugins to work with WordPress – The missing documentation

My focus will be on the dev file because that is where I found the internet documentation to be most lacking, but I will include all the files at the end.

Webpack works by loading everything into Javascript and then using file type handlers to parse the content. The first thing you will need to do is save the CSS back out to a separate file after being imported into Javascript. In Webpack 4, the way to do this is by using the MiniCssExtract Plugin. Include an instance of the plugin in your plugin definition.

Also in the plugin definitions, you will want to define the Browsersync options. In addition to watching for changes to JS and CSS files, a line is added to define watching for changes in PHP files.

Finally, define the server and port number as a proxy for our PHP server address. Now when Browsersync runs u dev mode, it will watch for changes in files and reload the browser on a change event. (small caveat, the injectChanges line is wishful thinking, I haven’t managed to get that to work).

Plugin definitions for your config file

Don't forget to change yourlocalserver.dev to your local server address.

plugins: [
  new MiniCssExtractPlugin({
    filename: "css/[name].css"
    }),
    new BrowserSyncPlugin(
    // BrowserSync options
    {
      files: "**/*.php",
      // browse to http://localhost:3000/ during development
      host: "localhost",
      port: 3000,
        proxy: "http://yourlocalserver.dev/",
    },
    // plugin options
    {
      injectChanges: true,
    }
  ),
],

Enqueue your individual CSS and JS files

The final piece is to enqueue the Webpack outputs. Because this isn’t a js app, we will have to enqueue the CSS and JS separately.

Throw this into your WordPress plugin's PHP file to enqueue the CSS files. Change the plugin and CSS file names to match your project.

If you're curious about the "filetime", check out cache busting

function enqueue_styles() {
  wp_register_style(
    'my_plugin_css_file',
    plugins_url('my-plugin/assets/css/my-app.css', dirname( __FILE__ )),
    null,
    filemtime(plugin_dir_path( __DIR__ ) . 'my-plugin/assets/css/my-app.css')
  );
wp_enqueue_style('my_plugin_css_file');

function enqueue_scripts() {
  wp_register_script(
    'my-script',
    plugins_url( 'my-plugin/assets/js/my-app.js', dirname( __FILE__ ) ),
    null,
    '1',
    true
  );
}
wp_enqueue_script('my-script');

Now we have a WordPress dev environment that uses Webpack to watch for changes to javascript, CSS (automatically compiled from SCSS), and PHP files and automatically reloads them in the browser to reflect those changes.

Further, in the testing environment, we add in legacy browser support via babble and post CSS browser prefixing, while in the production environment, we add in all of Webpack’s concatenation, uglification, and minification features.

Final thoughts

Webpack is not the best fit for WordPress development. It may sound like a little thing, but I can’t go back to waiting for a page to reloads. I’ve been spoiled by Browsersync's CSS injection in Gulp, and Webpack's hot media replacement in React development, neither of which work in this environment.