This article is about fixing You forgot to add 'mini-css-extract-plugin' plugin in stephencookdev Speed Measure Webpack Plugin
  • 07-Feb-2023
Lightrun Team
Author Lightrun Team
Share
This article is about fixing You forgot to add 'mini-css-extract-plugin' plugin in stephencookdev Speed Measure Webpack Plugin

“You forgot to add ‘mini-css-extract-plugin’ plugin” in stephencookdev Speed Measure Webpack Plugin

Lightrun Team
Lightrun Team
07-Feb-2023

Explanation of the problem

The webpack 5 build is failing with the following error message:

ERROR in ..../Error.scss
Module build failed (from ../../node_modules/mini-css-extract-plugin/dist/loader.js):
Error: You forgot to add 'mini-css-extract-plugin' plugin (i.e. `{ plugins: [new MiniCssExtractPlugin()] }`), please read https://github.com/webpack-contrib/mini-css-extract-plugin#getting-started
    at Object.pitch (.../node_modules/mini-css-extract-plugin/dist/loader.js:50:14)

This issue is due to a missing symbol, which is defined when the mini-css-extract-plugin module loads and assigned in a compilation hook. The missing symbol is defined in the following code block:

// mini-css-extract-plugin/dist/loader.js@50
  if (!this[_index.pluginSymbol]) {
    callback(new Error("You forgot to add 'mini-css-extract-plugin' plugin (i.e. `{ plugins: [new MiniCssExtractPlugin()] }`), please read https://github.com/webpack-contrib/mini-css-extract-plugin#getting-started"));
    return;
  }
// mini-css-extract-plugin/index.js@362
    compiler.hooks.compilation.tap(pluginName, compilation => {
      const normalModuleHook = typeof NormalModule.getCompilationHooks !== 'undefined' ? NormalModule.getCompilationHooks(compilation).loader : compilation.hooks.normalModuleLoader;
      normalModuleHook.tap(pluginName, loaderContext => {
        // eslint-disable-next-line no-param-reassign
        loaderContext[pluginSymbol] = true;
      });
    });

The issue occurs because the smp.wrap() method is preventing the inner callback from being run, causing the symbol to never be added to the loader’s context.

Environment

The following versions are used:

  • webpack: 5.21.0
  • mini-css-extract-plugin: 1.3.9
  • speed-measure-webpack-plugin: 1.5.0

Webpack Configuration

The webpack configuration file includes the following plugins:

plugins: [
  ...
  MiniCssExtractPlugin {
    _sortedModulesCache: WeakMap { <items unknown> },
    options: {
      filename: [Function: filename],
      ignoreOrder: false,
      chunkFilename: 'chunk-[name].[contenthash].css'
    },
    runtimeOptions: {
      insert: undefined,
      linkType: 'text/css',
      attributes: undefined
    }
  },
  ...
  SpeedMeasurePlugin {
    options: {},
    timeEventData: {},
    smpPluginAdded: true,
    wrap: [Function: bound wrap],
    getOutput: [Function: bound getOutput],
    addTimeEvent: [Function: bound addTimeEvent],
    apply: [Function: bound apply],
    provideLoader

Troubleshooting with the Lightrun Developer Observability Platform

Getting a sense of what’s actually happening inside a live application is a frustrating experience, one that relies mostly on querying and observing whatever logs were written during development.
Lightrun is a Developer Observability Platform, allowing developers to add telemetry to live applications in real-time, on-demand, and right from the IDE.

  • Instantly add logs to, set metrics in, and take snapshots of live applications
  • Insights delivered straight to your IDE or CLI
  • Works where you do: dev, QA, staging, CI/CD, and production

Start for free today

Problem solution for “You forgot to add ‘mini-css-extract-plugin’ plugin” in stephencookdev Speed Measure Webpack Plugin

The issue at hand is that webpack users may face difficulty in using both speed-measure-webpack-plugin and mini-css-extract-plugin at the same time. By default, these plugins may not work well together, which can cause unexpected behavior in the build process.

To overcome this challenge, the proposed solution is to wrap the webpack configuration object with speed-measure-webpack-plugin and then append mini-css-extract-plugin. This ensures that the two plugins are used together in a controlled manner. Here is the code for this solution:

const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const config = {
  // ...
  plugins: [
    // Whatever other plugins you may have
  ]
};

const configWithTimeMeasures = new SpeedMeasurePlugin().wrap(config);
configWithTimeMeasures.plugins.push(new MiniCssExtractPlugin({}));

module.exports = configWithTimeMeasures;

By following the above steps, webpack users can effectively use both speed-measure-webpack-plugin and mini-css-extract-plugin in their build process. The wrapping of the webpack configuration object with speed-measure-webpack-plugin allows for the accurate measurement of build times, while the use of mini-css-extract-plugin ensures that the extracted CSS files are organized and easy to manage.

Other popular problems with Speed Measure Webpack Plugin

Problem: Incorrect Measurement Results

One of the common issues with speed-measure-webpack-plugin is that it might produce incorrect measurement results. This happens when the plugin is unable to correctly measure the build time of the dependencies or when it measures the build time of other plugins that are not related to the build process.

Solution:

To resolve this issue, you can use the exclude option to exclude the plugins that are not related to the build process.

const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const config = {
  // ...
  plugins: [
    // Whatever other plugins you may have
  ]
};

const smp = new SpeedMeasurePlugin({
  exclude: [/other-plugin/]
});
const configWithTimeMeasures = smp.wrap(config);

module.exports = configWithTimeMeasures;

Problem: Slow Build Time with SpeedMeasurePlugin

Another common issue with speed-measure-webpack-plugin is that it might slow down the build process. This happens when the plugin adds an additional layer of computation that slows down the build process.

Solution:

To resolve this issue, you can use the outputFormat option to choose a more lightweight output format or you can use the quiet option to disable the plugin output completely.

const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const config = {
  // ...
  plugins: [
    // Whatever other plugins you may have
  ]
};

const smp = new SpeedMeasurePlugin({
  outputFormat: 'json',
  quiet: true
});
const configWithTimeMeasures = smp.wrap(config);

module.exports = configWithTimeMeasures;

Problem: Incompatible with Other Plugins

Another common issue with speed-measure-webpack-plugin is that it might be incompatible with other plugins. This happens when the plugin interferes with the functioning of other plugins that are crucial to the build process.

Solution:

To resolve this issue, you can append the conflicting plugin after wrapping with speed-measure-webpack-plugin.

const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');

const config = {
  // ...
  plugins: [
    // Whatever other plugins you may have
  ]
};

const configWithTimeMeasures = new SpeedMeasurePlugin().wrap(config);
configWithTimeMeasures.plugins.push(new MiniCssExtractPlugin({}));

module.exports = configWithTimeMeasures;

A brief introduction to Speed Measure Webpack Plugin

The stephencookdev Speed Measure Webpack Plugin is a tool that helps optimize the performance of webpack builds. It measures the time taken by each module to compile and provides detailed statistics on the performance of the build. The plugin is essential for developers who need to understand the performance characteristics of their webpack builds and make informed decisions on how to optimize them.

The Speed Measure Plugin integrates into the webpack build process by wrapping the webpack configuration object. It uses the wrap method to create a new configuration object that contains the measurement information. The plugin can be added to an existing webpack configuration by requiring the module and instantiating it, then wrapping the configuration with the instantiated object. The resulting configuration can be exported and used as the default webpack configuration. Here’s an example of how to add the Speed Measure Plugin to a webpack configuration:

const SpeedMeasurePlugin = require('speed-measure-webpack-plugin');
const config = {
  // webpack configuration
};

const smp = new SpeedMeasurePlugin();
module.exports = smp.wrap(config);

Most popular use cases for Speed Measure Webpack Plugin

  1. Measuring Build Performance: The stephencookdev Speed Measure Webpack Plugin can be used to measure the build performance of a webpack configuration. By wrapping the webpack configuration in the plugin, it outputs the time taken by each plugin and module in the build process, allowing developers to identify performance bottlenecks and optimize their build.
const SpeedMeasurePlugin = require("speed-measure-webpack-plugin");
const smp = new SpeedMeasurePlugin();

module.exports = smp.wrap({
  // Your webpack configuration
});
  1. Debugging Build Process: The plugin can also be used for debugging the build process. By measuring the time taken by each plugin and module, developers can identify which plugins and modules are taking the most time to execute, helping them to resolve any issues in the build process.
  2. Optimizing Build Process: In addition to measuring and debugging the build process, the stephencookdev Speed Measure Webpack Plugin can also be used to optimize the build process. By identifying performance bottlenecks and optimizing slow plugins and modules, developers can significantly improve the overall performance of their build.
Share

It’s Really not that Complicated.

You can actually understand what’s going on inside your live applications.

Try Lightrun’s Playground

Lets Talk!

Looking for more information about Lightrun and debugging?
We’d love to hear from you!
Drop us a line and we’ll get back to you shortly.

By submitting this form, I agree to Lightrun’s Privacy Policy and Terms of Use.