Search code examples
webpackwebpack-2extract-text-plugin

How to use 'extract-text-plugin' in my webpack setup


I've been attempting to understand "production mode" in webpack. From what I gether now in webpack 2 you can run webpack -p but that doesn't seem as feature rich. My setup I carried over from Webpack 1 is like so:

var config = {
context: __dirname + '/app',
entry: './index.js',
output: {
    path: __dirname + '/app',
    filename: 'bundle.js'
},
plugins: [
    new CompressionPlugin({
        asset: "[path].gz[query]",
        algorithm: "gzip",
        test: /\.js$|\.html$/,
        threshold: 10240,
        minRatio: 0.8
    }),
    new webpack.ProvidePlugin({
        moment: "moment"
    }),
    new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery"
    })
],
module: {
    loaders: [
        {
            test: /\.js$/,
            loader: 'babel-loader',
            exclude: /node_modules/
        },
        {
            test: /\.scss$/,
            loader: 'style-loader!css-loader!sass-loader',
            exclude: /node_modules/
        },
        {
            test: /\.html$/,
            loader: 'raw-loader',
            exclude: /node_modules/
        }
    ]
}
};

if (process.env.NODE_ENV === 'production') {
    config.output.path = __dirname + '/dist';
    config.plugins.push(new webpack.optimize.UglifyJsPlugin());
    config.plugins.push(new ExtractTextPlugin("styles.css"));
    config.module.loaders({
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
            fallback: "style-loader",
            use: "style-loader!css-loader!sass-loader"
        })
    })
}

module.exports = config;

What I really want to so is use the extract-text-plugin in production mode, I have attempted the following:

if (process.env.NODE_ENV === 'production') {
    config.output.path = __dirname + '/dist';
    config.plugins.push(new webpack.optimize.UglifyJsPlugin());
    config.plugins.push(new ExtractTextPlugin("styles.css"));
    config.module.loaders({
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
            fallback: "style-loader",
            use: "style-loader!css-loader!sass-loader"
        })
    })
}

I'm getting the following error:

config.loaders({
           ^
TypeError: config.loaders is not a function

Solution

  • config.module.loaders is an array, so you would need to push just as you did with the plugins. But then you would end up with two loader configurations for .scss, which is clearly not what you desire. Instead you could define a variable which you pass to the config, like so:

    // Default SCSS loader
    var scssLoader = 'style-loader!css-loader!sass-loader';
    if (process.env.NODE_ENV === 'production') {
      // Overwrite it with the extract-text loader
      scssLoader = ExtractTextPlugin.extract({
        fallback: "style-loader",
        use: "style-loader!css-loader!sass-loader"
      })
    }
    

    And then the .scss rule in your config would become:

    {
      test: /\.scss$/,
      loader: scssLoader,
      exclude: /node_modules/
    },