Build Process

A build process is a method of converting source code files into a final build/production version that can be read by the computer. In particular, themes will most often be minifying or converting source code into CSS or JavaScript so that they can be read by the browser.

When creating a WordPress theme, you may find yourself in need of a build process to handle more complex projects. There are many systems to choose from, and you can use whatever you prefer. But WordPress also offers a standard package that you can be assured is continually updated and should cover most of your needs.

In this article, you will learn how to integrate with the @wordpress/scripts package to handle your theme’s build process.

Prerequisites

Most of WordPress theme development is pretty much plug and play. You just need a code editor and an install of WordPress in some type of development environment as outlined in Tools and Setup. But to work with a build process, there are some other requirements:

These are more advanced tools than what is normally required to build themes, but they are necessary if you want to work with the standard WordPress build process.

Setting up your files and folders

The @wordpress/scripts package was originally created for block development, but it evolved to also work with themes over time. By default, it expects that development files live in the /src folder and will output build files in the /build folder. Because most theme authors utilize a custom system for working with assets, this guide will show you how to do that.

For the examples that follow, you will use this structure within your theme folder:

  • public/
  • resources/
    • js/
      • editor.js
    • scss/
      • editor.scss
      • screen.scss
  • package.json
  • webpack.config.js

Installing the WordPress scripts package

Once you have your files and folders set up, you need to install the correct packages on your local machine.

First, open your theme’s package.json file and add the following code:

{
	"name": "your-project-name",
	"scripts": {
		"start": "wp-scripts start --webpack-src-dir=resources --output-path=public",
		"build": "wp-scripts build --webpack-src-dir=resources --output-path=public"
	}
}

The @wordpress/scripts package has several other available scripts that you can add, but you will definitely need start and build.

Now open your command line tool on your computer, navigate to your theme folder, and input the following command:

npm install @wordpress/scripts path webpack-remove-empty-scripts --save-dev

That command installs three packages:

  • @wordpress/scripts
  • path
  • webpack-remove-empty-scripts

The latter two are third-party packages, but they are useful for integrating with webpack in the next step.

Configuring webpack

The @wordpress/scripts package is built on top of webpack. If you were building a block, everything would already be in place for you. However, because you are building a theme, you need to overwrite some of the default configuration of the @wordpress/scripts package with your own.

That’s where your theme’s custom webpack.config.js file comes in. There two primary things you need to configure:

  • The entry points for your custom CSS and JavaScript files (those in the code below correspond to the file structure in this article).
  • The webpack-remove-empty-scripts plugin so that there are no leftover .js files mapped to your CSS.

Add the following code to your webpack.config.js file:

// WordPress webpack config.
const defaultConfig = require( '@wordpress/scripts/config/webpack.config' );

// Plugins.
const RemoveEmptyScriptsPlugin = require( 'webpack-remove-empty-scripts' );

// Utilities.
const path = require( 'path' );

// Add any new entry points by extending the webpack config.
module.exports = {
	...defaultConfig,
	...{
		entry: {
			'js/editor':  path.resolve( process.cwd(), 'resources/js',   'editor.js'   ),
			'css/screen': path.resolve( process.cwd(), 'resources/scss', 'screen.scss' ),
			'css/editor': path.resolve( process.cwd(), 'resources/scss', 'editor.scss' ),
		},
		plugins: [
			// Include WP's plugin config.
			...defaultConfig.plugins,

			// Removes the empty `.js` files generated by webpack but
			// sets it after WP has generated its `*.asset.php` file.
			new RemoveEmptyScriptsPlugin( {
				stage: RemoveEmptyScriptsPlugin.STAGE_AFTER_PROCESS_PLUGINS
			} )
		]
	}
};

Using the WordPress scripts package

To use the WordPress scripts package to process your assets, you can run one of two commands in your command line tool:

  • start: Builds the development version of your files and activates “watch” mode, which will process any code changes while enabled.
  • build: Builds the production version of your files.

Now open your command line tool and run the start command:

npm run start

It should automatically process your files from the /resources folder and place them in the /public folder with this structure:

  • public/
    • js/
      • editor.js
      • editor.asset.php
    • scss/
      • editor.scss
      • editor.asset.php
      • screen.scss
      • screen.asset.php

You’ll now see new *.asset.php files generated for each of your CSS and JavaScript files. These will contain metadata about each asset file that you can use when loading your files. This is covered in the “Loading scripts and styles” section below.

To disable the start command, type Ctrl + C (on either Windows or Mac) of your command line tool.

Once you’re ready to do a final production build of your files, run this command in your command line tool:

npm run build

Loading scripts and styles

The methods for loading scripts and styles are already covered in depth in the Including Assets documentation in this handbook. You should already be familiar with how to do this before proceeding with the next steps.

The documentation below is primarily geared towards teaching you how the *.asset.php file is generated for each asset. In each file, you will see an array that looks similar to the following snippet:

<?php return array('dependencies' => array('wp-block-editor'), 'version' => '2eae4c519afeff2a8c77');

In particular, the array will have two pieces of metadata that you can use in any wp_enqueue_*() functions:

  • dependencies: An array of dependencies that your script/style rely on.
  • version: A version number that you can use for cache busting.

Because the file returns the array, you can use PHP’s include to assign the array to a variable in your code. The following example shows getting the array for the screen.asset.php file:

$asset = include get_theme_file_path( 'public/css/screen.asset.php' );
// Returns: array( 'dependencies' => array(), 'version' => '0000' );

When loading a script or style using either wp_enqueue_script() or wp_enqueue_style(), you can pass $asset['dependencies'] and $asset['version'] to the corresponding parameters in the functions.

Try adding the following code to your theme’s functions.php file to load the assets that you’ve previously defined:

// Load front-end assets.
add_action( 'wp_enqueue_scripts', 'themeslug_assets' );

function themeslug_assets() {
	$asset = include get_theme_file_path( 'public/css/screen.asset.php' );

	wp_enqueue_style(
		'themeslug-style',
		get_theme_file_uri( 'public/css/screen.css' ),
		$asset['dependencies'],
		$asset['version']
	);
}

// Load editor stylesheets.
add_action( 'after_setup_theme', 'themeslug_editor_styles' );

function themeslug_editor_styles() {
	add_editor_style( [
		get_theme_file_uri( 'public/css/screen.css' )
	] );
}

// Load editor scripts.
add_action( 'enqueue_block_editor_assets', 'themeslug_editor_assets' );

function themeslug_editor_assets() {
	$script_asset = include get_theme_file_path( 'public/js/editor.asset.php'  );
	$style_asset  = include get_theme_file_path( 'public/css/editor.asset.php' );

	wp_enqueue_script(
		'themeslug-editor',
		get_theme_file_uri( 'public/js/editor.js' ),
		$script_asset['dependencies'],
		$script_asset['version'],
		true
	);

	wp_enqueue_style(
		'themeslug-editor',
		get_theme_file_uri( 'public/css/editor.css' ),
		$style_asset['dependencies'],
		$style_asset['version']
	);
}