How can I setup webpack to minify and combine scss and javascript like CodeKit?

Introduction

Webpack is mainly a JavaScript-bundler. Its “native” language is JavaScript and every other source requires a loader which transforms it to JavaScript. If you require() an html-file for example…

var template = require("./some-template.html");

…you’ll need the html-loader. It turns…

<div>
    <img src="https://stackoverflow.com/questions/26851120/./assets/img.png">
</div>

…into…

module.exports = "<div>\n    <img src=\"" + require("https://stackoverflow.com/questions/26851120/./assets/img.png") + "\">\n</div>";

If a loader doesn’t return JavaScript, it needs to be “piped” to another loader.


How to load SASS-files

Configure loaders

In order to use SASS you’ll need at least the sass-loader and the css-loader. The css-loader returns a JavaScript string. If you want to import the returned JavaScript string as StyleSheet, you’ll also need the style-loader.

Run npm i sass-loader css-loader style-loader --save

Now you need to apply these loaders on all files that match /\.scss$/:

// webpack.config.js
...
module: {
    loaders: [
        // the loaders will be applied from right to left
        { test: /\.scss$/, loader: "style!css!sass" }
    ]
}
...

You can also pass options to node-sass as query parameters:

{
    test: /\.scss$/, loader: "style!css!sass?includePaths[]=" + 
        path.resolve(__dirname, "./bower_components/bootstrap-sass/assets/stylesheets/"
}

Since bootstrap references icons via the url() statement, the css-loader will try to include these assets into the bundle and will throw an exception otherwise. That’s why you’ll also need the file-loader:

// webpack.config.js
...
module: {
    loaders: [
        { test: /\.scss$/, loader: "style!css!sass" },
        { test: /\.jpe?g$|\.gif$|\.png$|\.svg$|\.woff$|\.ttf$/, loader: "file" },
    ]
}
...

Configure entry

To include bootstrap into your bundle there are several ways. One is via the multi-entry option as you’ve already tried. I recommend to use a single entry where you require() your main sass-file:

// main.js
require("./main.scss");

Given that your includePaths are configured then you can do:

// main.scss
// Set the font path so that url() points to the actual file
$icon-font-path: "../../../fonts/bootstrap";

@import "bootstrap";

Please note that import statements inside scss-files are not touched by webpack because libsass has no api (yet) to provide custom resolvers.

To prevent code duplication it’s also important to have a single main sass-file, because webpack compiles every sass-file individually.

With the coffee-loader installed via npm your final webpack.config.js should look like:

module.exports = {
    entry: "./js/main.coffee",
    output: {
        path: __dirname,
        filename: "main.js"
    },
    module: {
        loaders: [
            { test: /\.scss$/, loader: "style!css!sass" },
            { test: /\.jpe?g$|\.gif$|\.png$|\.svg$|\.woff$|\.ttf$/, loader: "file" },
            { test: /\.coffee$/, loader: "coffee" }
        ]
    }
};

Webpack globally?

It’s best not to install webpack globally, because it’s a dependency of your project and thus should be controlled via npm. You can use the scripts-section of your package.json:

{
    ...
    "scripts": {
        "start": "webpack --config path/to/webpack.config.js & node server.js"
    }
}

Then you just need to run npm start

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)