31

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.

Andrea Moraglia
  • 505
  • 2
  • 5
  • 9
  • I never worked with mini-css-extract-plugin, but I have worked with ExtractTextPlugin for css, and one thing that might help you is to put the loaders together in order to process your css. ExtractTextPlugin.extract(['css-loader', 'sass-loader']) Could be an idea to follow for your problem. – Italo Borges Mar 21 '18 at 17:27
  • I think that mini-css-extract-plug has no method call "extract". In the documentation the loader are written all on the same array like my example (`MiniCssExtractPlugin.loader` then `css-loader`, etc...) – Andrea Moraglia Mar 22 '18 at 10:10
  • I'm not sure if this is a similar issue, but this post helped me a lot - basically just using the @next version (the rest of my set up was similar to yours) https://stackoverflow.com/questions/50803260/how-to-use-webpack-4-splitchunksplugin-with-htmlwebpackplugin-for-multiple-page – Sia Nov 04 '19 at 22:05

1 Answers1

28

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,
        },
      }
    },
}
Ingo Steinke
  • 766
  • 3
  • 11
  • 30
Jimi Pajala
  • 2,358
  • 11
  • 20
  • 8
    With this config webpack will merge all css in one but also will generate `styles.js` which is needed in order to make everything working (all the bundled js). Any way to get rid of that file? – nass600 Jul 03 '18 at 19:25
  • Does this handle `@import 'md/variables'` where the expected resolved file is `./md/_variables.scss`? – Gio Oct 17 '18 at 18:20
  • 3
    Wrong api schema. cacheGroups goes inside splitChunks. – llobet Dec 03 '18 at 17:21
  • 1
    @nass600 Use `webpack-fix-style-only-entries` webpack plugin, works fine. – Jan Peša Jan 11 '19 at 12:20
  • 1
    `importLoader` should be `importLoaders` and should probably be 1 not 2 in the initial config example – El Yobo Jun 20 '19 at 02:34
  • @ElYobo if you do NOT wish to use `SASS` 1 is correct value, 2 is used with `SASS`. It seems that `importLoaders` key is documented but seems to work either way. – Jimi Pajala Jun 20 '19 at 08:37
  • 1
    0 would be no loaders, 1 would be sass... presumably like with the importLoader typo they're also handling too many loaders being specified? See the documented example here if there's confusion - https://github.com/webpack-contrib/css-loader#importloaders – El Yobo Jun 20 '19 at 21:36