12

I am fairly new to WebPack, and I want to be able to take a directory of CSS files (.app/styles/[css files...]) and output them into one CSS file (dist/styles.css).

Currently, all the JavaScript files is compiled into one single "index_bundle.js" file, which is perfect, but I want to achieve the same for my CSS files.

After a lot of "Googling", I found that the ExtractTextPlugin for WebPack should be able to help with this, but this only works for one CSS file that is added to the "entry" property (eg: entry: {style: "./app/styles/style.css"}) which is then added to the html's head as a link tag, which is fine, but I want all my css files to go into one styles.css file and then use that in the html's head as a link.

My current WebPack config looks like this:

var HtmlWebpackPlugin = require('html-webpack-plugin');
var HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
    template: __dirname + '/app/index.html',
    filename: 'index.html',
    inject: 'body'
});

var ExtractTextPlugin = require('extract-text-webpack-plugin');
var ExtractTextPluginConfig = new ExtractTextPlugin(
    "styles.css", 
    {
        allChunks: false
    }
);

module.exports = {
    entry: {
        index: "./app/index.js"//,
        //styles: "./app/styles/style1.css" // I don't want one file, I want to use a directory eg: "./app/styles/"
    },
    output: {
        path: __dirname + '/dist',
        filename: 'index_bundle.js'
    },
    module: {
        loaders: [
            {
                test: /\.js$/, 
                exclude: /node_modules/, 
                loader: 'babel-loader'
            },
            { 
                test: /\.css$/, 
                loader: ExtractTextPlugin.extract("style-loader", "css-loader")
            }
        ]
    },
    plugins: [
        HtmlWebpackPluginConfig,
        ExtractTextPluginConfig
    ]
}

Can someone please point me in the right direction? Even if it is another plugin or a different approach. Any help will be greatly appreciated!

EDIT: My new WebPack config looks like this:

var HtmlWebpackPlugin = require('html-webpack-plugin');
var HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
    template: __dirname + '/app/index.html',
    filename: 'index.html',
    inject: 'body'
});

var ExtractTextPlugin = require('extract-text-webpack-plugin');
var ExtractTextPluginConfig = new ExtractTextPlugin(
    "index_bundle.css"
);

module.exports = {
    entry: [
        './app/index.js',
        './app/index.css'
    ],
    output: {
        path: __dirname + '/dist',
        filename: 'index_bundle.js'
    },
    module: {
        preloaders: [
            {
                test: /\.css/,
                exclude: /styles/, 
                loader: 'import-glob-loader'
            }
        ],
        loaders: [
            {
                test: /\.js$/, 
                exclude: /node_modules/, 
                loader: 'babel-loader'
            },
            { 
                test: /styles\.css$/, 
                loader: ExtractTextPlugin.extract("style-loader", "css-loader")
            },
            { 
                test: /\.json$/, 
                loader: 'json' 
            }
        ]
    },
    devServer: {
        historyApiFallback: true
    },
    plugins: [
        HtmlWebpackPluginConfig,
        ExtractTextPluginConfig
    ]
}
4
  • 2
    The way webpack works is to walk the dependency tree (imports) of a main entry file. So, usually, to bundle all css in a directory, you would make an index styles.css and @import all the other css files (in the order you'd like them to appear in the bundle. Commented Nov 1, 2016 at 8:27
  • So does that mean that I will have to remember to put all the @imports every time I add new css files? Commented Nov 1, 2016 at 8:46
  • 1
    No, you need an glob import: @import './mydir/**/*.css' Commented Nov 1, 2016 at 9:12
  • I am using "import-glob-loader" but now WebPack fails when running the webpack dev server with: "Unexpected character '@'". When I take out the css entry it works, so seems like it fails on syntax even with the glob preloader... Commented Nov 1, 2016 at 10:34

2 Answers 2

9

Ok, so it seems to have been a camel-case problem.

With the help of Davin Tryon, I was able to resolve my issue - thanks!

If you look at: https://www.npmjs.com/package/import-glob-loader they have the following:

preloaders: [{
    test: /\.scss/,
    loader: 'import-glob-loader'
}]

It should be:

preLoaders: [{
    test: /\.scss/,
    loader: 'import-glob-loader'
}]

So in the end, my whole webpack.config.json looks like this:

var HtmlWebpackPlugin = require('html-webpack-plugin');
var HtmlWebpackPluginConfig = new HtmlWebpackPlugin({
    template: __dirname + '/app/index.html',
    filename: 'index.html',
    inject: 'body'
});

var ExtractTextPlugin = require('extract-text-webpack-plugin');
var ExtractTextPluginConfig = new ExtractTextPlugin(
    "index_bundle.css"
);

module.exports = {
    entry: [
        './app/index.js',
        './app/index.css'
    ],
    output: {
        path: __dirname + '/dist',
        filename: 'index_bundle.js'
    },
    module: {
        preLoaders: [
            {
                test: /\.css$/,
                exclude: /styles/, 
                loader: 'import-glob-loader'
            }
        ],
        loaders: [
            {
                test: /\.js$/, 
                exclude: /node_modules/, 
                loader: 'babel-loader'
            },
            { 
                test: /\.css$/, 
                loader: ExtractTextPlugin.extract("style-loader", "css-loader")
            },
            { 
                test: /\.json$/, 
                loader: 'json' 
            }
        ]
    },
    devServer: {
        historyApiFallback: true
    },
    plugins: [
        HtmlWebpackPluginConfig,
        ExtractTextPluginConfig
    ]
}

And my index.css file looks like this:

@import './styles/**/*';

This is working for me and I get a single css output file "index_bundle.css". The style and scripts also automatically gets injected into the html template.

index.html before injection:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Admin - Login</title>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css"/>
    </head>
    <body>
        <div id="app"></div>
    </body>
</html>

index.html after injection in /dist folder:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Admin - Login</title>
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/latest/css/bootstrap.min.css"/>
    <link href="index_bundle.css" rel="stylesheet"></head>
    <body>
        <div id="app"></div>
    <script type="text/javascript" src="index_bundle.js"></script></body>
</html>
Sign up to request clarification or add additional context in comments.

1 Comment

Note: module.preLoaders has been removed in Webpack 2
0

I had a similar problem because I had a typo in a file name in my webpack.config.js file.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.