DEV Community

Cover image for A webpack.config.js for WordPress Projects
Sarah Siqueira
Sarah Siqueira

Posted on • Edited on

A webpack.config.js for WordPress Projects

That's another of those posts in which my main goal is to document it for my own future reference and with some hope can be useful for other developers. Configuring webpack manually can take a considerable amount of time, so I thought it's a good idea to keep things documented somewhere, and since I am 'documenting' why not share with others?

I would like to add that you can extend the webpack as you want, according to the needs of your project. That's a basic configuration that covers basic needs to starting a WordPress theme for example.

If you are reading and interested in setting webpack in a WordPress project, I am assuming you have some understanding about, obviously WordPress projects like custom themes or custom plugins. And I also believe that you know about setting up a WordPress development environment, either using a Docker or XAMPP, so I will not write about those topics. I will not write about how to enqueue/register the assets generated by webpack either. If necessaire, you can read more about it in this article or the official WordPress documentation.

About webpack

Some knowledge about webpack can be very handy, but I will do my best trying to explain one thing or another.

Webpack is a free and open-source module bundler based on Node.js for JavaScript. It is very "famous" in the modern javascript frameworks world, and although it was made primarily for JavaScript, it also can transform front-end assets such as CSS, and images if the corresponding loaders are included (this is the reason I will be using so many dependencies below).

In a WordPress project like this example theme, webpack avoids multiple requests, taking all our javascript and css files, and bundling all of them together in a minified file. It also increases my productivity, as, well, I don't need to manually compile and minify things.

Requirements

Creating the package.json

Create the package.json by typing the command npm init. Then install the required dependencies:

npm i @babel/cli @babel/core @babel/preset-env @babel/preset-react
@wordpress/dependency-extraction-webpack-plugin  
babel-loader clean-webpack-plugin copy-webpack-plugin 
cross-env css-loader css-minimizer-webpack-plugin 
file-loader mini-css-extract-plugin
sass-loader terser-webpack-plugin 
webpack webpack-cli -D
Enter fullscreen mode Exit fullscreen mode

or after creating your package.json, edit it and paste the following in the file:

{
  "devDependencies": {
    "@babel/cli": "^7.22.9",
    "@babel/core": "^7.22.9",
    "@babel/preset-env": "^7.22.9",
    "@babel/preset-react": "^7.22.5",
    "@wordpress/dependency-extraction-webpack-plugin": "^4.21.0",
    "babel-loader": "^9.1.2",
    "clean-webpack-plugin": "^4.0.0",
    "copy-webpack-plugin": "^11.0.0",
    "cross-env": "^7.0.3",
    "css-loader": "^6.8.1",
    "css-minimizer-webpack-plugin": "^5.0.1",
    "file-loader": "^6.2.0",
    "mini-css-extract-plugin": "^2.7.6",
    "sass-loader": "^13.3.2",
    "terser-webpack-plugin": "^5.3.9",
    "webpack": "^5.86.0",
    "webpack-cli": "^5.1.4"
  }
Enter fullscreen mode Exit fullscreen mode

Then, run npm install. The dependencies will be installed.

This project was updated in May 2023 and maybe necessaire to replace some dependencies in the future. So it's important you know more about each dependency to be able to solve any issue that may arise (I am also assuming you know the term dependency hell).

You can read about each dependency used in this article in the links below:

The webpack.config.js

Now let's set up our webpack.config.js file. See the complete file on Gist.

We will need export modules:

/**
 * Webpack configuration.
 */

module.exports = (env, argv) => ({
    entry: {},
    output: {},
});
Enter fullscreen mode Exit fullscreen mode

Entry and Output points

We need to define an entry point and an output. Let's place those out for the sake of readability:

const entry = {};
const output = {};

module.exports = (env, argv) => ({
    entry: entry,
    output: output,

});
Enter fullscreen mode Exit fullscreen mode

Our entry/output paths:

const entry = {
    main : require('path').resolve(__dirname, 'src/js' ) + '/index.js'
};

const output = {
    path: require('path').resolve(__dirname, 'build'),
    filename: 'js/[name].js'
};
Enter fullscreen mode Exit fullscreen mode

Rewriting:

const path = require('path');
const JS_DIR = path.resolve(__dirname, 'src/js' );
const BUILD_DIR = path.resolve(__dirname, 'build');

const entry = {
    main : JS_DIR + '/index.js'
};
const output = {
    path: BUILD_DIR,
    filename: 'js/[name].js'
};
Enter fullscreen mode Exit fullscreen mode

devtool

Let's set our devtool in the module exports, this option controls if and how source maps are generated. For more information and options you can choose, please refer to the documentation. I choose the 'source-map'

devtool: 'source-map',
Enter fullscreen mode Exit fullscreen mode

Rules

Yet in the module exports, let's add some rules:

    module: {
        rules: rules,
    }
Enter fullscreen mode Exit fullscreen mode

Those are "my rules" for Javascript and CSS:

const rules = [
    {
        test: /\.js$/,
        include: [JS_DIR],
        exclude: /node_modules/,
        use: "babel-loader",
    },
    {
        test: /\.scss$/,
        exclude: /node_modules/,
        use: [MiniCssExtractPlugin.loader, "css-loader", "sass-loader"],
    },
];
Enter fullscreen mode Exit fullscreen mode

Plugins

CSS

Webpack doesn't understand CSS by default, so we will need some plugins, in this case, the MiniCssExtractPlugin already installed above.

Require it at the top of our webpack.config adding:

const MiniCssExtractPlugin = require( "mini-css-extract-plugin" );

Add plugins in the module exports:

plugins: plugins(argv) => [];

And then the CSS plugin itself:

 new MiniCssExtractPlugin(
        {
            filename: "css/[name].css",
        }
    ),

Enter fullscreen mode Exit fullscreen mode

Images

Webpack doesn't understand images either. The chosen plugin for handling it was the file-loader, yes, that one I am considering replacing as soon as I find time.

  {
        test: /\.(png|jpg|svg|jpeg|gif|ico)$/,
        use: {
            loader: "file-loader",
            options: {
                name: "[path][name].[ext]",
                publicPath: "production" === process.env.NODE_ENV ? "../" : "../../",
            },
        },
    },
Enter fullscreen mode Exit fullscreen mode

Clean weppack plugin

A webpack plugin to remove/clean your build folder(s).

const { CleanWebpackPlugin } = require( "clean-webpack-plugin" );

Create a plugin (only for production mode):

new CleanWebpackPlugin(
    {
        cleanStaleWebpackAssets: "production" === argv.mode,
    }
),
Enter fullscreen mode Exit fullscreen mode

Copy Files

new CopyPlugin({
    patterns: [{ from: IMG_DIR, to: BUILD_DIR + "/img" }],
  }),
Enter fullscreen mode Exit fullscreen mode

Optimization

Require the dependencies on top of the webpack file:

const CssMinimizerPlugin = require( "css-minimizer-webpack-plugin" );
const TerserJsPlugin = require( "terser-webpack-plugin" );
Enter fullscreen mode Exit fullscreen mode

And inside the module.exports:

optimization: {
    minimizer: [
                new CssMinimizerPlugin(), 
                new TerserJsPlugin()
],
    minimize: true,
        },
Enter fullscreen mode Exit fullscreen mode

Externals for webpack

With external you can exclude some libraries from the bundler, for example, jquery:

externals: {
    jquery: "jQuery",
},
Enter fullscreen mode Exit fullscreen mode

Scripts

To help us work with all this, let's set some scripts in the package.json:

scripts: {
"prod": "cross-env NODE_ENV=production webpack --mode production
        --progress",
"watch": "cross-env NODE_ENV=development webpack --watch 
         --mode development --progress"
}
Enter fullscreen mode Exit fullscreen mode

The complete webpack.config.js and devDependencies are available on this GitHub Gist. If it was useful for you, please comment below and consider star the gist.

Top comments (0)