Webpack: mini-css-extract-plugin not outputting css file
Asked Answered
S

4

19

I think I followed the documentation correctly, but it does not work at all.

What I want is to generate a css file, and do not load it in style tags with js.

In my src directory:: "scss/custom.scss" and "style.scss", and none of them is generated in output.

EDIT: src code: https://github.com/marcosroot/webpackexample

My settings are:

const path = require('path');
const BundleTracker = require('webpack-bundle-tracker');
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
const devMode = true;

module.exports = {
    entry: [
        './src/toggle_menu.js',
        './src/calls_apis.js'
    ],
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: devMode ? 'main.js' : 'main.[hash].js',
    },
    plugins: [
        new BundleTracker({
            filename: './webpack-stats.json'
        }),
        new MiniCssExtractPlugin({
            filename: devMode ? '[name].css' : '[name].[hash].css'
        })
    ],
    module: {
        rules: [{
                test: /\.js$/,
                exclude: /node_modules/,
                use: {
                    loader: 'babel-loader',
                }
            },
            {
                test: /\.scss$/,
                include: path.resolve(__dirname, 'scss/custom.scss'),
                use: [
                    MiniCssExtractPlugin.loader,
                    'css-loader',
                    'postcss-loader',
                    'sass-loader',
                ]
            }
        ]
    },
}
Sevastopol answered 3/4, 2019 at 23:50 Comment(1)
Looks like you need provide relative path to your output. I have a next config in my project new MiniCssExtractPlugin({filename: DEV ? '../css/_.css' : '../css/_-[contenthash].css'}), – Hays
L
6

I think your trouble is coming from a wrong path resolution in your configuration :

include: path.resolve(__dirname, 'scss/custom.scss'),

It means to webpack to include only a resource located under {root}/scss/custom.scss and, given your explanation, I presume the right path should be {root}/src/scss/custom.scss.

So to include your two files {root}/src/scss/custom.scss and {root}/src/styles.scss and any other scss files under src folder, you can use :

module: {
    rules: [{
            test: /\.js$/,
            exclude: /node_modules/,
            use: {
                loader: 'babel-loader',
            }
        },
        {
            test: /\.scss$/,
            include: /src/, // <-- Change here ---------------------
            use: [
                MiniCssExtractPlugin.loader,
                'css-loader',
                'postcss-loader',
                'sass-loader',
            ]
        }
    ]
},

You can also simply remove include option if you're pretty sure there's no other roaming scss files in your project or node modules that may be found and should not be bundled at the same time (that's probably the case).

You can also supply an array of the two files by adding src in the path resolution :

include: [
   path.resolve(__dirname, 'src/scss/custom.scss'),
   path.resolve(__dirname, 'src/styles.scss'),
]

****** EDIT *******

Following your comment and from your repo, there's another few mistakes :

  • postcss-loader is not included as dev dependency and no configuration for it as well
  • You mistake what is the include option of a rule. It does simply mean that only resources that are matching the include test will be processed like configured in that rule. You still need to require the scss files at some point in your script.

I've forked your repo and set up a correct configuration with scss import in call_api.js (one of your entry point). Build and you will see the css file in the dist folder (I've set up a dumb cssnano config for postcss, that will be parsed harsh)

Lait answered 4/4, 2019 at 0:14 Comment(0)
K
26

This question is relatively old but I ran into the same problem and I wanted to share my solution. This is probably very dependent on your configuration, but anyway, my mini-css-extract-plugin did not work because:

  • I ran it with webpack -p (which an alias for production mode + minify)
  • The css rule I had setup did not clarify that it made side effects.

As a result, when I ran the build in production mode (i.e. webpack -p), it did not produce an output because when webpack saw this…

import './my-css-file.css';

…and was like "that doesn't do anything, i'll remove it from your build".


So in order to tell webpack that this type of file matters, you have to mark the rule as sideEffects: true

// ...
module.exports = {
  // ...
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [MiniCssExtractPlugin.loader, 'css-loader'],
        include: [/* fill this in */],
        exclude: /node_modules/,
        // πŸ‘‡πŸ‘‡πŸ‘‡
        sideEffects: true, // πŸ‘ˆ ADD THIS
        // πŸ‘†πŸ‘†πŸ‘†
      },
    ],
  },
  // ...
}
Kenlee answered 2/3, 2020 at 4:19 Comment(2)
Thank you for adding this. I was dealing with this same issue when managing a rule for css modules and a rule for non css modules. The non css module rule was essentially removed the bundle and I couldn't figure out why. Sure enough this worked as expected. – Pecten
Thank you. This is exactly what I needed as well. – Physiology
L
6

I think your trouble is coming from a wrong path resolution in your configuration :

include: path.resolve(__dirname, 'scss/custom.scss'),

It means to webpack to include only a resource located under {root}/scss/custom.scss and, given your explanation, I presume the right path should be {root}/src/scss/custom.scss.

So to include your two files {root}/src/scss/custom.scss and {root}/src/styles.scss and any other scss files under src folder, you can use :

module: {
    rules: [{
            test: /\.js$/,
            exclude: /node_modules/,
            use: {
                loader: 'babel-loader',
            }
        },
        {
            test: /\.scss$/,
            include: /src/, // <-- Change here ---------------------
            use: [
                MiniCssExtractPlugin.loader,
                'css-loader',
                'postcss-loader',
                'sass-loader',
            ]
        }
    ]
},

You can also simply remove include option if you're pretty sure there's no other roaming scss files in your project or node modules that may be found and should not be bundled at the same time (that's probably the case).

You can also supply an array of the two files by adding src in the path resolution :

include: [
   path.resolve(__dirname, 'src/scss/custom.scss'),
   path.resolve(__dirname, 'src/styles.scss'),
]

****** EDIT *******

Following your comment and from your repo, there's another few mistakes :

  • postcss-loader is not included as dev dependency and no configuration for it as well
  • You mistake what is the include option of a rule. It does simply mean that only resources that are matching the include test will be processed like configured in that rule. You still need to require the scss files at some point in your script.

I've forked your repo and set up a correct configuration with scss import in call_api.js (one of your entry point). Build and you will see the css file in the dist folder (I've set up a dumb cssnano config for postcss, that will be parsed harsh)

Lait answered 4/4, 2019 at 0:14 Comment(0)
S
5

Not for Op's case. But in My Case:
(I dont have sufficient knowledge on the reason)

it seems you must remove 'style-loader', when you use MiniCssExtractPlugin.loader.

  • (Also, if you place MiniCssExtractPlugin.loader before 'style-loader', no Error will show & you wont notice it.)
Sweeny answered 17/5, 2023 at 18:39 Comment(2)
This was my issue too! I was following a tutorial for adding mini css extract and didn't notice that they removed style-loader from the configuration in the end. Thanks for pointing this out. – Bacchanalia
it worked, but documentation explicitly mentions to use style-loader; I'm confused – Splashdown
H
0

You need to provide relative path in your filename or specify publicPath: '../' in your loader config https://www.npmjs.com/package/mini-css-extract-plugin#minimal-example

In my project I have

new MiniCssExtractPlugin({filename: DEV ? '../css/styles.css' : '../css/styles-[contenthash].css'}),

Documentation provides example with public path

const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
  plugins: [
    new MiniCssExtractPlugin({
      // Options similar to the same options in webpackOptions.output
      // both options are optional
      filename: "[name].css",
      chunkFilename: "[id].css"
    })
  ],
  module: {
    rules: [
      {
        test: /\.css$/,
        use: [
          {
            loader: MiniCssExtractPlugin.loader,
            options: {
              // you can specify a publicPath here
              // by default it use publicPath in webpackOptions.output
              publicPath: '../'
            }
          },
          "css-loader"
        ]
      }
    ]
  }
}
Hays answered 4/4, 2019 at 20:46 Comment(0)

© 2022 - 2024 β€” McMap. All rights reserved.