Webpack 3 Sass cssnano Autoprefixer Workflow II

This follow up to the basic Webpack 3 Sass preprocessor workflow I wrote about here includes how to handle processing of relative URLs in the Sass for things like fonts and images. Ken Wheeler’s popular Slick carousel contains these asset types in its Sass, so let’s use that for this exercise.

Getting Started

Prerequisite: Node.js with npm.

Navigate to the project root in your CLI, such as Terminal, Cygwin or PowerShell.

Enter npm init to interactively create a package.json file. Accepting the default options is okay for now. The metadata in this file can be updated later as needed.

npm init

A package.json file should now exist in the root of the project. This json file is used to manage the project dependencies, set configuration options for supported modules and run npm scripts.

Create an index.html file in the project root with an unordered list of placeholder images. Include the dist/style.css link in the document head and dist/app.js link before the closing body tag. Add a class attribute with the value slider to the unordered list element. This sets it apart for selecting with our script and style code: <ul class="slider">

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <link rel="stylesheet" media="all" href="dist/style.css">
</head>
<body>
    <ul class="slider">
        <li>
            <h3>Slide 1</h3>
            <img src="http://placehold.it/800x600" />
        </li>
        <li>
            <h3>Slide 2</h3>
            <img src="http://placehold.it/800x600" />
        </li>
        <li>
            <h3>Slide 3</h3>
            <img src="http://placehold.it/800x600" />
        </li>
        <li>
            <h3>Slide 4</h3>
            <img src="http://placehold.it/800x600" />
        </li>
        <li>
            <h3>Slide 5</h3>
            <img src="http://placehold.it/800x600" />
        </li>
    </ul>
    <script async src="dist/app.js"></script>
</body>
</html>

Using Emmet, which is built into VS Code, you can create the index.html content by entering an exclamation mark on the first line then select the tab key.

Slick

Install jQuery and Slick carousel using npm.

npm install --save jquery slick-carousel

In the src/js folder, create an index.js JavaScript file to import the Sass entry file and the jQuery and Slick carousel modules.

index.js
import style from '../sass/main.scss'
import $ from 'jquery'
import 'slick-carousel'

$('ul.slider').slick({
    dots: true
});

Before we can build this JavaScript a Webpack configuration and npm script will need to be defined.

Webpack & Babel

Install Webpack

npm install --save-dev webpack

Create a webpack.config.js file in the project root to transpile our ES6 JavaScript into ES5 for the browser using babel.

webpack.config.js
const path = require('path')
const webpack = require('webpack')

module.exports = {
context: path.resolve(__dirname, './src'),
  entry: {
    app: './js/index.js'
  },
  output: {
    path: path.resolve(__dirname, './dist'),
    publicPath: '/dist/',
    filename: '[name].js'
  },
  module: {
    rules: [
    {
      test: /\.js$/,
      exclude: /node_modules/,
      use: 'babel-loader'
    }
    ]
  },
  devtool: '#eval-source-map'
}

Install Babel

npm install --save-dev babel-core babel-loader babel-preset-env

Create a .babelrc configuration file in the project root.

.babelrc
{
  "presets": ["env"]
}

Here is how the project is structured so far.

  • project
    • .babelrc
    • index.html
    • package.json
    • webpack.config.js
    • src
      • js
        • index.js

Build

Install cross-dev for a consistent NODE_ENV variable when running NPM scripts on Windows and OS X.

npm install --save-dev cross-env

Define dev and build commands for npm-run-script in package.json.

package.json
...

  ],
  "scripts": {
    "dev": "cross-env NODE_ENV=development webpack --watch --progress --colors",
    "build": "cross-env NODE_ENV=production webpack --progress --hide-modules",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  ...
}

At the bottom of the webpack configuration, add the respective dev and build npm scripts using the NODE_ENV settings.

webpack.config.js
...

if (process.env.NODE_ENV === 'production') {
  module.exports.devtool = '#source-map'
  module.exports.plugins = (module.exports.plugins || []).concat([
    new webpack.DefinePlugin({
      'process.env': {
        NODE_ENV: '"production"'
      }
    }),
    new webpack.optimize.UglifyJsPlugin({
      sourceMap: true,
      compress: {
        warnings: false
      }
    }),
    new webpack.LoaderOptionsPlugin({
      minimize: true
    })
  ])
}

Note that the ellipsis … in the code snippet above is not a part of the actual code and is there only to denote code that is being skipped and not applicable to the example. Keep this in mind when you encounter an ellipsis in the remaining snippets. To view the entire file, examine the source code.

Using the npm-run-scripts alias npm run to execute the build.

npm run build

For development, use npm run dev to watch for changes and build incrementally when changes are saved.

You should now have a new dist folder in the root of the project where the Webpack bundle is output.

The next page covers:

  • installing Webpack loaders to process Sass
  • installing Extract Text Plugin to output a style.css file
  • installing Autoprefixer PostCSS plugin
  • creating and importing Sass files
  • re-building and verifying the application output

Part 2 of 3 in the Webpack 3 Sass cssnano Autoprefixer Workflow series.

Webpack 3 Sass cssnano Autoprefixer Workflow | Webpack 3 Sass cssnano Autoprefixer Workflow II - Page 2

comments powered by Disqus