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
- 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