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
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"
}
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:
file-loader Example of dependency that is deprecated for webpack v5, it's recommended migrate to asset modules dependency (which I still didn't).
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: {},
});
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,
});
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'
};
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'
};
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',
Rules
Yet in the module exports, let's add some rules:
module: {
rules: rules,
}
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"],
},
];
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",
}
),
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 ? "../" : "../../",
},
},
},
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,
}
),
Copy Files
new CopyPlugin({
patterns: [{ from: IMG_DIR, to: BUILD_DIR + "/img" }],
}),
Optimization
Require the dependencies on top of the webpack file:
const CssMinimizerPlugin = require( "css-minimizer-webpack-plugin" );
const TerserJsPlugin = require( "terser-webpack-plugin" );
And inside the module.exports:
optimization: {
minimizer: [
new CssMinimizerPlugin(),
new TerserJsPlugin()
],
minimize: true,
},
Externals for webpack
With external you can exclude some libraries from the bundler, for example, jquery:
externals: {
jquery: "jQuery",
},
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"
}
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)