Sass/SCSS Build Process Tutorial

In this Sass/SCSS tutorial we learn all the steps to a typical Sass project build process.

We cover compiling Sass code, concatenating third party code with ours, adding vendor prefixes and minifying our final CSS file.

Lastly we create an NPM task to perform the full build process with a single, short command.

What is a build process

A build process is a sequence of tasks that we perform automatically after we’ve finished developing to produce the final CSS file that will be used in our website or application.

The build process includes things like the compiling, concatenating, minifying etc.

We will use NPM scripts and Node packages for the example build process in this lesson, so open up your package.json file. It should look similar to the following example.

Example:
{
  "name": "LearningSass",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "watch:sass": "sass --watch sass/main.scss:css/style.css",
    "devserver": "@gerhobbelt/live-server",
    "start": "npm-run-all --parallel devserver watch:sass"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "live-server": "^1.2.1",
    "npm-run-all": "^4.1.5",
    "sass": "^1.26.8"
  }
}

Step 1: Compile Sass to CSS

So far in our package.json file we have 3 scripts that allow us to watch for changes in our Sass and HTML.

As the first step in our build process, we want to compile the Sass to CSS without watching for changes.

So, we can add another compile command without the --watch flag. We also want to change the file name it compiles into.

Script:
"compile:sass": "sass sass/main.scss:css/style.comp.css"

The package.json file will now look like this.

Example:
{
  "name": "LearningSass",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "watch:sass": "sass --watch sass/main.scss:css/style.css",
    "devserver": "@gerhobbelt/live-server",
    "start": "npm-run-all --parallel devserver watch:sass",

    "compile:sass": "sass sass/main.scss:css/style.comp.css"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "live-server": "^1.2.1",
    "npm-run-all": "^4.1.5",
    "sass": "^1.26.8"
  }
}

Step 2: Concatenating (combining) third party styles

The next step is to concatenate our CSS with any third party CSS files. For example, if we were using an icon-font CSS file or a reset.

For this example, we’ll use normalize.css that we downloaded into our ‘css’ folder, and concatenate it with our compiled CSS file.

To concatenate CSS files, we can install the NPM concat package and save it as a dev dependency.

Command:
npm install concat --save-dev

Now that everything’s installed, we can create the NPM task.

Script:
"concat:css": "concat -o css/style.concat.css css/normalize.css css/style.comp.css"
  • -o is to indicate the output file follows.
  • css/style.concat.css is the output file itself.
  • css/normalize.css css/style.comp.css are the two files we want to combine.

The package.json file should now look like this.

Example:
{
  "name": "LearningSass",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "watch:sass": "sass --watch sass/main.scss:css/style.css",
    "devserver": "@gerhobbelt/live-server",
    "start": "npm-run-all --parallel devserver watch:sass",

    "compile:sass": "sass sass/main.scss:css/style.comp.css",
    "concat:css": "concat -o css/style.concat.css css/normalize.css css/style.comp.css"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "concat": "^1.0.3",
    "live-server": "^1.2.1",
    "npm-run-all": "^4.1.5",
    "sass": "^1.26.8"
  }
}

Step 3: Adding vendor prefixes to CSS

Different browsers handle CSS differently in some situtations. Sometime we need browser or version specific prefixes for some of our styles, like flexbox, shadows or animations for example.

Instead of manually finding and adding these prefixes, we can let a NPM package do that for us automatically.

To prefix our CSS, we need two additional NPM packages called autoprefixer and postcss . The reason we need both is because Autoprefixer is part off PostCSS.

Command: postcss
npm install postcss-cli --save-dev

note We’re using the CLI (Command Line Interface) version of PostCSS. You can find more information about their entire ecosystem on the PostCSS website .

Command: autoprefixer
npm install autoprefixer --save-dev

Now that everything’s installed, we can create the NPM task.

Script:
"prefix:css": "postcss css/style.concat.css --use autoprefixer -o css/style.prefix.css"
  • css/style.concat.css is the input file from step 2.
  • --use autoprefixer tells postcss that we want to use the autoprefixer.
  • -o is to indicate the output file follows.
  • css/style.prefix.css is the output file.

By default, autoprefixer will look at the current and previous browser versions for prefixes. We can tell it to look further back if by adding an extra key below the ‘scripts’ entry.

Example:
"browserslist": "last 4 versions"

We target the last 4 versions in this example, but it could just as easily be 2 or 10.

Our package.json file should now look like this.

Example:
{
  "name": "LearningSass",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "watch:sass": "sass --watch sass/main.scss:css/style.css",
    "devserver": "@gerhobbelt/live-server",
    "start": "npm-run-all --parallel devserver watch:sass",

    "compile:sass": "sass sass/main.scss:css/style.comp.css",
    "concat:css": "concat -o css/style.concat.css css/normalize.css css/style.comp.css",
    "prefix:css": "postcss css/style.concat.css --use autoprefixer -o css/style.prefix.css",
    "compress:css": "node-sass css/style.prefix.css css/style.css --output-style compressed",
    "build": "npm-run-all compile:sass prefix:css compress:css"
  },
  "browserslist": "last 4 versions",
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^9.8.4",
    "concat": "^1.0.3",
    "live-server": "^1.2.1",
    "npm-run-all": "^4.1.5",
    "postcss-cli": "^7.1.1",
    "sass": "^1.26.8"
  }
}

Step 4: Minify and compress CSS

The next step is to minify and compress our CSS code into the final output file.

Luckily, Sass already provides us with the ability to minify and compress our code, so we don’t have to install another package. We can create the NPM task directly.

Script:
"compress:css": "node-sass css/style.prefix.css css/style.css --output-style compressed"
  • css/style.prefix.css is the input file from step 3.
  • css/style.css is the output file.
  • --output-style compressed tells Sass we don’t want to compile, just compress.

The package.json file should now look like this.

Example:
{
  "name": "LearningSass",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "watch:sass": "sass --watch sass/main.scss:css/style.css",
    "devserver": "@gerhobbelt/live-server",
    "start": "npm-run-all --parallel devserver watch:sass",

    "compile:sass": "sass sass/main.scss:css/style.comp.css",
    "concat:css": "concat -o css/style.concat.css css/normalize.css css/style.comp.css",
    "prefix:css": "postcss --use autoprefixer -b 'last 10 versions' css/style.concat.css -o css/style.prefix.css",
    "compress:css": "node-sass css/style.prefix.css css/style.css --output-style compressed"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^9.8.4",
    "concat": "^1.0.3",
    "live-server": "^1.2.1",
    "npm-run-all": "^4.1.5",
    "postcss-cli": "^7.1.1",
    "sass": "^1.26.8"
  }
}

Step 5: Putting it all together

Instead of going through each of the commands above one by one, we can create a script to run all of them at once.

To do that we’re going to use the npm-run-all package that we used in the First Script lesson.

If you don’t have the package, it can be installed with the following command.

Command:
npm install npm-run-all --save-dev

We want to run the scripts in the build process one by one, instead of concurrently, so we don’t include the --parallel flag like we did before.

note It’s important that we specify the scripts to execute in the correct order. Trying to concatenate a compressed script for example, may cause our CSS to break.

Script:
"build": "npm-run-all compile:sass concat:css prefix:css compress:css"

The package.json file should now look like this.

Example:
{
  "name": "LearningSass",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "watch:sass": "sass --watch sass/main.scss:css/style.css",
    "devserver": "@gerhobbelt/live-server",
    "start": "npm-run-all --parallel devserver watch:sass",

    "compile:sass": "sass sass/main.scss:css/style.comp.css",
    "concat:css": "concat -o css/style.concat.css css/normalize.css css/style.comp.css",
    "prefix:css": "postcss --use autoprefixer -b 'last 10 versions' css/style.concat.css -o css/style.prefix.css",
    "compress:css": "node-sass css/style.prefix.css css/style.css --output-style compressed",
    "build": "npm-run-all compile:sass concat:css prefix:css compress:css"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "autoprefixer": "^9.8.4",
    "concat": "^1.0.3",
    "live-server": "^1.2.1",
    "npm-run-all": "^4.1.5",
    "postcss-cli": "^7.1.1",
    "sass": "^1.26.8"
  }
}

All we need to do now is to run the following command when we want to build our final CSS file.

Command:
npm run build

Summary: Points to remember

  • A build process is the steps we take to at the end of development to produce the final CSS file.
    • A typical build process for Sass to CSS is compiling > concatenating > prefixing > minifying
  • To combine third party styles to our CSS file we use the Concat NPM package.
  • To add vendor prefixes we use the PostCSS with its AutoPrefixer module.
  • To minify our CSS we use the built in compression from Node Sass.
  • To run all multiple tasks in sequence we use the NPM Run All package.