Basic Webpack 5 Project with CSS: Step-by-Step

October, 23rd 2024 3 min read

Webpack remains one of the most powerful bundlers for modern JavaScript applications. Even as tools like Vite and Parcel grow in popularity, Webpack continues to serve well for custom setups, enterprise environments, and fine‑grained control.
This guide walks through setting up a minimal but production-ready Webpack 5 project with CSS support, including improvements and best practices not found in typical tutorials.


1. Create the Project Structure

Begin by creating a new directory and initializing your project:

plaintext
mkdir my-webpack-project
cd my-webpack-project
npm init -y

After initialization, create a simple structure:

plaintext
my-webpack-project/
├── src/
│   ├── index.js
│   └── styles.css
├── dist/
├── package.json
└── webpack.config.js

The src/ folder holds your application code, while dist/ will contain the bundled output.


2. Install Webpack and CSS Loader Dependencies

Install Webpack and the essential loaders needed for CSS handling.

plaintext
npm install webpack webpack-cli css-loader style-loader --save-dev
  • css-loader: Reads @import and url() inside CSS files
  • style-loader: Injects CSS into the DOM at runtime

These together allow Webpack to bundle styles into your JavaScript output.


3. Add Sample JavaScript and CSS

src/index.js

js
import './styles.css';

console.log('Webpack 5 project with CSS is running!');

src/styles.css

css
body {
  margin: 0;
  padding: 0;
  background: #eef2f5;
  font-family: Arial, sans-serif;
}

h1 {
  color: #005bbb;
  text-align: center;
  margin-top: 40px;
}

4. Create the Webpack Configuration

Now configure Webpack to process both JavaScript and CSS files.

webpack.config.js

js
const path = require('path');

module.exports = {
  entry: './src/index.js',

  output: {
    filename: 'bundle.js',
    path: path.resolve(__dirname, 'dist'),
    clean: true  // Automatically clean dist/ before each build
  },

  module: {
    rules: [
      {
        test: /\.css$/i,
        use: ['style-loader', 'css-loader']
      }
    ]
  },

  mode: 'development'
};

Improvements added:

  • clean: true: Clears old build files automatically.
  • Regex /\.css$/i ensures case‑insensitive matching.

5. Add a Build Script

In package.json, add:

json
"scripts": {
  "build": "webpack"
}

You can now run:

plaintext
npm run build

Webpack will generate dist/bundle.js containing both your JavaScript and injected CSS.


6. Create a Test HTML File

Inside dist/index.html, add:

html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Webpack 5 Project</title>
</head>
<body>
  <h1>Webpack 5 + CSS Loaded Successfully</h1>
  <script src="bundle.js"></script>
</body>
</html>

Open the file in a browser and confirm the CSS and JS load correctly.


7. Optional Improvements

js
devtool: 'source-map'

Enable Watch Mode

plaintext
npm run build -- --watch

Support Images

Install:

plaintext
npm install file-loader --save-dev

Add rule:

js
{
  test: /\.(png|jpg|jpeg|gif|svg)$/i,
  type: 'asset/resource'
}

Extract CSS into a separate file (production-ready)

Install:

plaintext
npm install mini-css-extract-plugin --save-dev

Use instead of style-loader:

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

module.exports = {
  plugins: [
    new MiniCssExtractPlugin()
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader']
      }
    ]
  }
};

Conclusion

You now have a clean, modern Webpack 5 setup with support for JavaScript and CSS bundling.
From here, you can extend the configuration to support:

  • SCSS and PostCSS
  • TypeScript
  • image and font assets
  • development servers
  • multiple entry points

This starter configuration provides a solid foundation for building more advanced Webpack workflows.