Using Gulp with Bootstrap 4

So with Bootstrap 4 on the cusp of beta, just wanted to go over setting up your Bootstrap source with Gulp, instead of the default Grunt.

So first off you're going to want to head off to the Boostrap 4 alpha site and pick youself up the alpha source and the go through the install guide.

Once you have a nice clean setup of the Bootstrap alpha, make sure you install Gulp to npm with

npm install --global gulp-cli
npm install --save-dev gulp

Next you're going to want to add these Gulp dependencies to your package.json. Edit your package.json and add these under your dev dependencies:

"devDependencies": {

"browser-sync": "^2.2.1",
"del": "^1.1.1",
"gulp-concat": "^2.6.0",
"gulp": "^3.9.0",
"gulp-uglify": "^1.1.0",
"gulp-cache": "^0.2.8",
"gulp-autoprefixer": "^2.3.1",
"gulp-eslint": "^0.13.2",
"gulp-load-plugins": "^0.10.0",
"gulp-util": "3.0.6",
"gulp-if": "^1.2.5",
"gulp-imagemin": "^2.2.1",
"gulp-minify-css": "^1.1.1",
"gulp-minify-html": "^1.0.0",
"gulp-plumber": "^1.0.1",
"gulp-sass": "^2.0.0",
"gulp-sourcemaps": "^1.5.0",
"gulp-rename": "^1.2.1",
"gulp-babel": "^5.2.1"
},

Run

npm install 

Next you're going to want to add a file called "gulpfile.babel.js" to the root directory of the Boostrap project. Open it up let's start with adding the npm dependencies to our gulpfile:

// Load Node Modules/Plugins
import gulp from 'gulp';
import gulpLoadPlugins from 'gulp-load-plugins';
import browserSync from 'browser-sync';
import del from 'del';
var gutil = require('gulp-util');

const reload = browserSync.reload;
const $ = gulpLoadPlugins();

So overall, we're binding a few pretty useful packages to Gulp. Browser sync allows for live reloads when we're running our gulpfile to watch files in the directory (more on that in a bit), del allows us to delete files and gulp util is a utility library for Gulp that does things like logging.

Then we use a little ES6 magic to make loading plugins a bit easier. We call two const's which is a new addition to JavaScript, the first being reload. Reload essentially allows us to initialize browser sync and watch any change in files, so gulp can recompile them.

Then we call another const $ to gulpLoadPlugins(). What this allows us to do is bind $ to our npm plugins, so we only have to call them as we need them and is a nice shorthand for loading in plugins. It also significantly shortens our import calls.

Next simply add

// Remove existing docs and dist build
gulp.task('clean', del.bind(null, ['docs/dist', 'dist']));

This is just a small task in Gulp than when we run it, it deletes anything from our dist folder, so we don't have to overwrite changes.

Next let's compile our sass. Add:

// Build LibSass files
gulp.task('styles', function() {
gulp.src('./scss/bootstrap.scss')
.pipe($.plumber())
.pipe($.sourcemaps.init())
.pipe($.sass().on('error', $.sass.logError))
.pipe($.sourcemaps.write('.'))
.pipe($.autoprefixer({browsers: ['last 1 version']}))
.pipe($.rename({ suffix: '.min' }))
.pipe(gulp.dest('dist/css'))
.pipe($.minifyCss())
.pipe(gulp.dest('dist/css'));
});

Essentially we write our sourcemaps on the uncompiled version of the Sass, next we use autoprefixer to prefix any of the CSS classes that need it. After that, we rename it and minify it. Nothing too complicated, and as you can see, we use the $ as shorthand to load our plugins, rather than manually specifying them.

Next let's add this to work with our Javascript:

// Build JavaScript files 
gulp.task('scripts', function() {
 return gulp.src(['js/src/util.js', 'js/src/alert.js', 'js/src/button.js', 'js/src/carousel.js', 'js/src/collapse.js', 'js/src/dropdown.js', 'js/src/modal.js', 'js/src/scrollspy.js', 'js/src/tab.js', 'js/src/tooltip.js', 'js/src/popover.js'])
.pipe($.babel())
.pipe($.concat('./bootstrap.js'))
.pipe(gulp.dest('dist/js'));

});

So here, we specify all of our smaller Javascript files in the order we want them to appear when we combine them. Next we use babel to turn any of the ES6 functions into cross browser compatible ES5. Finally we use concat() to combine all the Javascript files together, and pipe it into dist.

Next lets add our watch task:

// Watch tasks

 gulp.task('watch', function() {     
 gulp.watch('scss/*.scss', ['styles']);
 gulp.watch('js/src/*.js', ['scripts']);

});

Here we watch our Javascript and Sass for any changes and recompile if there are any. Great for if you're modifying Bootstrap with custom Sass, and want to see live changes. Also, you can use the watch task with any CLI. Browser sync is also working in the background reloading, to see any live changes as it's compiled.

Finally we have these tasks left to add. Add

gulp.task('dist', ['styles', 'scripts']);

gulp.task('default', ['clean'], () => {
gulp.start('dist');
});

Dist is the task that will just compile your Sass and JS into your dist directory.

The default task is running all our tasks, starting off with cleaning the dist directory, and running the Sass and JS compilation. Awesome! We have our Javascript and Sass minifying and watching any sort of modification we make to Boostrap.

Next post, I'll be updating this on how to compile images and icons, how to compile with Ruby sass (and toggling the environment variable). You can find the fully completed files mentioned in this article on my Github