Search code examples
javascriptnpmwebpackwebpack-2

Combining SCSS and CSS Into A Single File With WebPack


I'm a newbie to webpack and I'm having trouble understanding how I can take a bunch of scss files and css files and merge them together with webpack (After transpiling the sass of course).

With gulp, it was really obvious, as I can have 1 step the transpile the sass to css and then a step after that to concatenate them together. However with webpack, it looks like everything happens at the same time.

This is a pretty basic requirement that I'm sure has an obvious answer to those more experienced.

I've got to the point where I can successfully output a transpiled scss to css and seperately output a css file from css input, but I can't figure out how to stick them together using webpack.

Below is my webpack.config.js file:

const path = require('path');
const webpack = require('webpack');

var ExtractTextPlugin = require('extract-text-webpack-plugin');

const extractCSS = new ExtractTextPlugin('extractedCSS.css');

const extractSass = new ExtractTextPlugin({
    filename: "extractedSASS.css",
    disable: process.env.NODE_ENV === "development"
});

module.exports = function (env) {
    return {
        context: path.resolve(__dirname, './wwwroot/app'),
        entry: {
            main: './index.js',
            vendor: 'moment'
        },
        output: {
            filename: '[name].[chunkhash].js',
            path: path.resolve(__dirname, './wwwroot/mytempdist')
        },
        module: {
            rules: [{
                test: /\.css$/,
                use: extractCSS.extract({
                    use: 'css-loader'
                })
            },
            {
                test: /\.scss$/,
                use: extractSass.extract({
                    use: [{
                        loader: "css-loader"
                    }, {
                        loader: "sass-loader"
                    }],
                    // use style-loader in development
                    fallback: "style-loader"
                })
            }
            ]
        },
        plugins: [
            new webpack.optimize.CommonsChunkPlugin({
                name: 'vendor',
                minChunks: function (module) {
                    // this assumes your vendor imports exist in the node_modules directory
                    return module.context && module.context.indexOf('node_modules') !== -1;
                }
            }),
            //CommonChunksPlugin will now extract all the common modules from vendor and main bundles
            new webpack.optimize.CommonsChunkPlugin({
                name: 'manifest' //But since there are no more common modules between them we end up with just the runtime code included in the manifest file
            }),
            //new webpack.optimize.UglifyJsPlugin({
            //    sourceMap: options.devtool && (options.devtool.indexOf("sourcemap") >= 0 || options.devtool.indexOf("source-map") >= 0)
            //}),
            extractSass,
            extractCSS
        ],
        devtool: 'inline-source-map'
    }
}

How can I modify the above to make both the sass and css go into the file css output file?

Incase it makes a difference, below is an exerpt from my index.js file (entry point) toastr is an npm package and pace is just a normal downloaded css file:

var toastr = require('toastr');
import 'toastr/toastr.scss';

import pace from './../lib/pace/pace.min.js';
import './../lib/pace/pace.css';


Solution

  • You have 2 instances of ExtractTextPlugin defined with explicit names and you use those separate instances to load css and scss files respectively.

    What you need is only 1 instance of the plugin which will accumulate all the CSS and only one rule for both scss and css files.

    {
        test: /\.s?css$/,
        use: ExtractTextPlugin.extract({
            fallback: 'style-loader',
            use: ['css-loader', 'sass-loader']
        })
    }
    

    This will handle both scss and css files and put it all in one single output CSS file.