Webpack 4: mini-css-extract-plugin + sass-loader + splitChunks

42,419

im doing someting like this in my Webpack 4 configuration.

const MiniCssExtractPlugin = require("mini-css-extract-plugin")

module: {
rules: [ {
    test: /\.scss$/,
    use: [
      MiniCssExtractPlugin.loader,
      {
        loader: "css-loader",
        options: {
          modules: true,
          sourceMap: true,
          importLoader: 2
        }
      },
      "sass-loader"
    ]}
  ]
},

plugins: [
  new MiniCssExtractPlugin({
    // Options similar to the same options in webpackOptions.output
    // both options are optional
    filename: "style.css",
    chunkFilename: "[name].css"
  })
]

I also give output.publicPath -configuration object to point into my build dir, example ->

output: {
   filename: "[name]-min.js",
   path: path.resolve(__dirname, "dist"),
   publicPath: "/static/react/dist/"
},

edit If you are interested in code splitting, Webpack 4 can do this "out of the box" for you. This will split .js and as well .css -files for you in case you use dynamic imports.

optimization: {
  splitChunks: {
    chunks: 'all'
  }
}

If you other hand would like to merge only your .css into one file you could add as follow.

optimization: {
    splitChunks: {
      chunks: 'all'
      cacheGroups: {
        styles: {
          name: 'styles',
          test: /\.s?css$/,
          chunks: 'all',
          minChunks: 1,
          reuseExistingChunk: true,
          enforce: true,
        },
      }
    },
}
Share:
42,419
Andrea Moraglia
Author by

Andrea Moraglia

Updated on July 09, 2022

Comments

  • Andrea Moraglia
    Andrea Moraglia almost 2 years

    I've the follow example configuration to use mini-css-extract-plugin with Webpack 4:

    entry: {
       a: ['./js/a.js', './scss/a.scss'],
       b: ['./js/b.js', './scss/b.scss']
    },
    module: {
        rules: [
           [...],
           {
            test: /\.(css|sass|scss)$/,
            use: [
                MiniCssExtractPlugin.loader,
                {
                    loader: 'css-loader',
                    options: {
                        importLoaders: 2,
                        sourceMap: true
                    }
                },
                {
                    loader: 'postcss-loader',
                    options: {
                        plugins: () => [
                            require('autoprefixer')
                        ],
                        sourceMap: true
                    }
                },
                {
                    loader: 'sass-loader',
                    options: {
                        sourceMap: true
                    }
                }
            ]
    },
    optimization: {
        splitChunks: {
            cacheGroups: {
                js: {
                    test: /\.js$/,
                    name: "commons",
                    chunks: "all",
                    minChunks: 7,
                },
                css: {
                    test: /\.(css|sass|scss)$/,
                    name: "commons",
                    chunks: "all",
                    minChunks: 2,
                }
            }
        }
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: "dist/[name].css",
        }),
    ]
    

    And the following sass files:

    // a.scss
    @import 'libA.scss';
    @import 'libB.css';
    [...] 
    
    // b.scss
    @import 'libA.scss';
    @import 'libB.css';
    [...]
    

    When I run webpack libB.css is inserted in in commons.css bundle while libA.scss not.

    In general every import of .css file get processed by splitChunks option (only if extension css is specified in the name) while sass import not.

    I have a project with multiple sass entry point and many @import of sass component and I'd like to create a common bundle with shared sass modules.