Skip to main content
The ProgressPlugin reports compilation progress, showing you the current stage and module being processed. This is especially useful for long builds to understand what webpack is doing.

Usage

const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.ProgressPlugin()
  ]
};
With webpack-cli, you can also use:
webpack --progress

Configuration

handler
function
Custom progress handler function. Receives (percentage, message, ...args) as parameters.
profile
boolean
default:"false"
Enable profiling to capture timing information for each step
modulesCount
number
default:"5000"
Expected number of modules (improves progress accuracy)
dependenciesCount
number
default:"10000"
Expected number of dependencies
modules
boolean
default:"true"
Show active modules count
dependencies
boolean
default:"true"
Show dependencies count
activeModules
boolean
default:"false"
Show currently active modules
entries
boolean
default:"true"
Show entries count
percentBy
string
How to calculate progress: 'entries', 'modules', 'dependencies', or null (median)

Examples

Default Usage

new webpack.ProgressPlugin()
Output:
10% building
30% building 150/300 modules
50% building 300/300 modules
70% sealing
90% emitting
100%

Custom Handler

new webpack.ProgressPlugin((percentage, message, ...args) => {
  console.log(`${Math.round(percentage * 100)}%`, message, ...args);
})

With Profiling

new webpack.ProgressPlugin({
  profile: true
})
This logs timing information:
142 ms sealing
38 ms building
12 ms optimizing

Detailed Progress

new webpack.ProgressPlugin({
  activeModules: true,
  modules: true,
  dependencies: true,
  entries: true
})
Output:
30% building 150/300 modules 45 active ./src/index.js

Custom Message Formatting

const chalk = require('chalk');

new webpack.ProgressPlugin((percentage, message, ...args) => {
  const percent = Math.round(percentage * 100);
  const color = percent < 50 ? 'red' : percent < 90 ? 'yellow' : 'green';
  
  console.log(
    chalk[color](`[${percent}%]`),
    message,
    ...args
  );
})

With Progress Bar

const ProgressBar = require('progress');

const bar = new ProgressBar(':bar :percent :msg', { total: 100 });

new webpack.ProgressPlugin((percentage, message) => {
  bar.update(percentage, { msg: message });
})

Write to File

const fs = require('fs');
const logStream = fs.createWriteStream('build.log');

new webpack.ProgressPlugin((percentage, message, ...args) => {
  logStream.write(
    `${new Date().toISOString()} - ${Math.round(percentage * 100)}% ${message}\n`
  );
})

Minimal Output

new webpack.ProgressPlugin({
  modules: false,
  dependencies: false,
  activeModules: false,
  entries: false
})

Estimated Module Count

new webpack.ProgressPlugin({
  modulesCount: 2000,
  dependenciesCount: 5000
})
This improves progress estimation accuracy.

Progress Based on Entries

new webpack.ProgressPlugin({
  percentBy: 'entries'
})

Advanced Usage

Multi-Compiler Progress

For multiple configurations:
module.exports = [
  {
    name: 'client',
    plugins: [
      new webpack.ProgressPlugin((percentage, message, ...args) => {
        console.log('[Client]', Math.round(percentage * 100) + '%', message);
      })
    ]
  },
  {
    name: 'server',
    plugins: [
      new webpack.ProgressPlugin((percentage, message, ...args) => {
        console.log('[Server]', Math.round(percentage * 100) + '%', message);
      })
    ]
  }
];

Detailed Profiling

const logger = compiler.getInfrastructureLogger('webpack.Progress');

new webpack.ProgressPlugin({
  profile: true,
  handler: (percentage, message, ...args) => {
    logger.log(`${Math.round(percentage * 100)}%`, message, ...args);
  }
})

Integration with CI/CD

const isCI = process.env.CI === 'true';

new webpack.ProgressPlugin({
  handler: isCI
    ? (percentage, message) => {
        // Only log major milestones in CI
        if (percentage === 0 || percentage === 1 || percentage % 0.1 === 0) {
          console.log(`Build ${Math.round(percentage * 100)}% complete`);
        }
      }
    : undefined // Use default handler locally
})

Notification on Complete

const notifier = require('node-notifier');

new webpack.ProgressPlugin((percentage, message) => {
  if (percentage === 1) {
    notifier.notify({
      title: 'Webpack',
      message: 'Build complete!'
    });
  }
})

Handler Function Signature

type Handler = (
  percentage: number,    // 0 to 1
  message: string,       // Stage name: 'building', 'sealing', 'emitting'
  ...args: string[]      // Additional context: module counts, file names, etc.
) => void;

Build Phases

The plugin reports progress through these phases:
  1. Setup (0-10%)
    • Initializing compiler
    • Loading plugins
    • Setting up module factories
  2. Building (10-70%)
    • Processing entries
    • Building modules
    • Loading dependencies
  3. Sealing (70-95%)
    • Optimizing modules
    • Creating chunks
    • Optimizing chunks
    • Hashing
  4. Emitting (95-100%)
    • Writing files
    • Emitting assets

Performance Considerations

The ProgressPlugin has minimal performance impact:
  • Adds ~1-2% to build time
  • More noticeable in very fast builds
  • Profiling mode adds ~5% overhead

Optimize for CI

const isCI = process.env.CI === 'true';

module.exports = {
  plugins: [
    // Disable progress in CI for cleaner logs
    !isCI && new webpack.ProgressPlugin()
  ].filter(Boolean)
};

Debugging Slow Builds

Use profiling to identify bottlenecks:
new webpack.ProgressPlugin({
  profile: true,
  handler: (percentage, message, ...args) => {
    // Log slow operations
    console.log({
      percentage: Math.round(percentage * 100),
      message,
      details: args,
      timestamp: Date.now()
    });
  }
})

Custom Progress Reporters

Fancy Terminal Output

const ora = require('ora');
const spinner = ora('Building').start();

new webpack.ProgressPlugin((percentage, message, ...args) => {
  const percent = Math.round(percentage * 100);
  spinner.text = `Building: ${percent}% - ${message}`;
  
  if (percentage === 1) {
    spinner.succeed('Build complete!');
  }
})

JSON Progress Log

new webpack.ProgressPlugin((percentage, message, ...args) => {
  process.stdout.write(JSON.stringify({
    percentage: Math.round(percentage * 100),
    message,
    args,
    timestamp: new Date().toISOString()
  }) + '\n');
})

Web Dashboard

const WebSocket = require('ws');
const wss = new WebSocket.Server({ port: 8080 });

new webpack.ProgressPlugin((percentage, message, ...args) => {
  wss.clients.forEach(client => {
    client.send(JSON.stringify({
      percentage,
      message,
      args
    }));
  });
})

Best Practices

  • Use default settings for most cases
  • Enable profile only when debugging build performance
  • Disable or simplify in CI environments
  • Set accurate modulesCount for better progress estimation
  • Use percentBy to focus on bottlenecks
Enabling activeModules can produce verbose output and slow down the build slightly. Use only when debugging.