Gulp Development Environment

07 Jun 2015 by Ava Collins

Developing a website or web application can include any number of plugins and pre-processors that are tedious to manage. Enter Gulp.js, a build system that can automate repetitive tasks like compiling SASS into CSS, adding plugins, frameworks and libraries, checking your code for syntax errors and reloading the browser while you are editing content. This post should help you get started using Gulp to build your next project but it is not the only way or even the best way to use gulp, it’s just a starter, you may choose to organize your project very differently from the examples given here. If you haven’t already installed git and node.js please refer to previous posts Environment Setup for PC or Environment Setup for Mac depending on your operating system.

Overview

The example repository that we will be working from provides the following common things:

  • An entry point into your website or application, usually index.html.
  • A source folder for scripts, stylesheets and other html files, usually organized in a fashion that reflects your site structure.
  • A place to download third party plugins.
  • A way to compile SASS into CSS.
  • A local web server.
  • A way to automate repetitive tasks like updating CSS when adding new SASS, linting your code for mistakes and creating a minified build when you are ready to deploy to a live server.

Let’s start by cloning the example, open your console and navigate to your home directory.

  • cd "${HOME}"
  • git clone https://github.com/SeattleFeministJS/Gulp-Development-Environment.git
  • npm install
  • bower install
  • gulp serve

Using this repository as a guide let’s start a brand new repository on your own account and we will add each one of those things step by step.

Fork example repository

Sign into your Github account and go to our sample repository Gulp Development Environment. In the top right under your name you will see a button that says “Fork”, click that to copy the example repository to your github account.

Fork button

When the forking is complete you will be taken to your github copy of the respository, copy the URL that is shown in the quick setup area.

Copy to clipboard

In your home directory open a command line and enter git clone followed by the URL that you copied from github GUI.

git clone https://github.com/simplesthing/Gulp-Development-Environment.git

Change directories to be inside your “Gulp-Development-Environment” directory.

cd Gulp-Development-Environment/

Install dependencies.

  • npm install
  • bower install

Create a new Github repository

Sign into your Github account and go to /new, or click the + symbol next to your git username. Give your repository a name, add a small description and check the option to add a README. Now copy the URL that is shown in the quick setup area.

URL to clone git repo

In your home directory open a command line and enter git clone followed by the URL that you copied from github GUI.

git clone https://github.com/simplesthing/test.git

Copy the .gitignore, .editorconfig and .jshintrc files from example repository into your new repository. Now create a src folder in the root of your project and inside that add an index.html. Go ahead and add standard <html>, <head> and <body> tags and let’s also add message to ourselves like “Hello World”.

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <h1>Hello World</h1>
</body>
</html>

Automate all the things

Now we’re ready to start using Gulp to automate some development tasks. On the command line navigate into your new repository and if you have followed the setup instructions from previous post you should already have Bower and NPM installed globally and ready to use. We’re going to initialize an NPM package.json file by typing npm init. It will ask a few questions about the project, you can enter answers or hit enter to accept defaults, and save a package.json file to the root of your project. Now that we have a package.json we can start adding our development tools, the first thing we’re going to need is get Gulp, in your command line enter:

npm install --save-dev gulp

We’ll need to create gulpfile.js in our project root. Start that file by declaring a variable for gulp

var gulp = require('gulp');

This is a pattern which we would have to use for every node module that we add to the project and want to use in our gulpfile except we’re going to use a utility called gulp-load-plugins which will automate that repetitive task and require any module that begins with gulp- so that we don’t have to. In command line type

npm install --save-dev gulp-load-plugins

Now in our gulpfile add

var $ = require('gulp-load-plugins')();

Now whenever we want to use a gulp- module we can refer to using the $. to prefix followed by the name of the module, for example if we were to add a module called ‘gulp-example’ we could call that module from within our gulpfile by using $.example.

Adding third party libraries using Bower

Almost every web application uses some third party libraries to enhance functionality, so let’s add some to ours we’ll start off with three very common ones jQuery, Bootstrap SASS, and Fontawesome. Back on the command line enter bower init this will initialize bower and create a bower.json by asking you a few questions about your project. Now we have a bower.json file we can use the command line to add packages and save them to bower.json which can be used to install your project anywhere.

Adding these libraries enter the following commands

  • bower install jquery --save
  • bower install fontawesome --save
  • bower install bootstrap-sass --save

You should see that a directory named /bower_coponents has been added to your project and plugins have been installed. but we need to have them added to our index.html for us whenever we add new ones. So let’s install wiredep to do this for us.

“How it works Installing a Bower package with –save will add the package as a dependency in your project’s bower.json file. This library reads that file, then reads the bower.json files for each of those dependencies. Based on these connections, it determines the order your scripts must be included before injecting them between placeholders in your source code.”

npm install --save-dev wiredep

Since this is not a ‘gulp-‘ prefixed package we are going to have to require the package ourselves by adding a new var at the top of our gulpfile.

var wiredep = require('wiredep').stream;

To create a new task for gulp to execute we use the gulp library function call gulp.task(name[, deps], fn) where we pass in task name, optional array of dependencies, and a callback function. Now we can add a new task called wiredep below our styles task.

gulp.task('wiredep', function(){

});

Inside the wiredep callback we are going to return our source which is our index.html file.

return gulp.src(['src/index.html'])

gulp.task('wiredep', function(){
  return gulp.src(['src/index.html'])
});

Pipe the source to the wiredep function and write to our src directory destination.

.pipe(wiredep())
.pipe(gulp.dest('build'));

gulp.task('wiredep', function(){
  return gulp.src(['src/index.html'])
    .pipe(wiredep())
    .pipe(gulp.dest('build'));
});

Lastly we’ll need to add placeholders in our index.html to tell wiredep where to add our plugin files, add the following to the head section of your index.html.

<!-- bower:css -->
<!-- endbower -->

<!-- bower:js -->
<!-- endbower -->

Go ahead and run gulp wiredep and you should now see that the index.html file has added fontawesome.css in between the css placeholders and added jquery.js and bootstrap.js between the js placeholders.

Get Sassy

Now let’s add some style to our site by creating a /styles directory to our /src and inside that add a styles.scss and a _main.scss file to that same directory.

Inside _main.scss and add a body style with a background color and a text color, for example.

body { background: #FF05DE; color: #05FF26; }

In our styles.scss we can import our main file by adding following.

@import "main";

Let’s add some bootstrap by copying the file at

/bower_components/bootstrap-sass/assets/stylesheets/_bootstrap.scss

into a file in your /src/styles directory named _bootstrap.scss. Then update all the @import paths to add ../../bower_components/bootstrap-sass/assets/stylesheets/ to the beginning of the file paths so they look like this

@import "../../bower_components/bootstrap-sass/assets/stylesheets/bootstrap/variables";

Now add @import "bootstrap"; to your styles.scss file at the very top, above your main.

We’ll be using a few different packages to compile, minify, create sourcemaps and watch our sass files while we are developing them. On the command line type the following.

  • npm install --save-dev gulp-sass
  • npm install --save-dev gulp-sourcemaps
  • npm install --save-dev gulp-autoprefixer

In our gulpfile let’s start adding a task to compile our sass into css called ‘styles’, add the following above the ‘serve’ task.

gulp.task('styles', function(){

});

Inside the callback we need to acquire our source sass files in order to return them back to the gulp stream by calling the gulp src function gulp.src(globs[, options]) and passing in an array of globs, filepaths that can use ‘wildcards’ characters, followed by an optional options object, which we won’t be using this time. Since we are using the style.scss to import all of our sass files we don’t need to pass in anything other than this file.

gulp.task('styles', function(){
  return gulp.src(['src/styles/styles.scss'])
});

Now we want to pipe those files to the next process ‘gulp-sourcemaps’, which will add inline references to the sass source code that was used to create the final CSS output which is used when debugging in the browser to find the location in you source SASS files of compiled CSS. We will pass our source files stream into the next step by calling

$.sourcemaps.init().

gulp.task('styles', function(){
  return gulp.src(['src/styles/styles.scss'])
    .pipe($.sourcemaps.init())
});

To compile our SASS we want to call gulp-sass and pass in a options object by adding

.pipe($.sass({precision: 10,errLogToConsole: true})).

gulp.task('styles', function(){
  return gulp.src(['src/styles/styles.scss'])
    .pipe($.sourcemaps.init())
    .pipe($.sass({
      precision: 10,
      errLogToConsole: true
    }))
});

The first option precision tells the compiler how many digits after a decimal place will be allowed when calculating values in CSS measurement such as pixels or em’s. The second option is called if an error occurs during compilation and will log that error to the console.

Now that we have our SASS converted to CSS we’d like gulp to add our browser prefixes for us by using gulp-autoprefixer but first we need to tell it which browsers we are interested in adding prefixes for by adding a configuration object. In our gulpfile near the top where we declare our vars add the following, which adds support for most major browsers.

var AUTOPREFIXER_BROWSERS = [
  'ie >= 10',
  'ie_mob >= 10',
  'ff >= 30',
  'chrome >= 34',
  'safari >= 7',
  'opera >= 23',
  'ios >= 7',
  'android >= 4.4',
  'bb >= 10'
];

Back in our ‘styles’ task callback add the following line to add our browser prefixes.

.pipe($.autoprefixer({browsers: AUTOPREFIXER_BROWSERS}))

gulp.task('styles', function(){
  return gulp.src(['src/styles/styles.scss'])
    .pipe($.sourcemaps.init())
    .pipe($.sass({
      precision: 10,
      errLogToConsole: true
    }))
    .pipe($.autoprefixer({browsers: AUTOPREFIXER_BROWSERS}))
});

Now that our CSS is finished we can call to gulp-sourcemaps to write our sourcemap files.

.pipe($.sourcemaps.write())

gulp.task('styles', function(){
  return gulp.src(['src/styles/styles.scss'])
    .pipe($.sourcemaps.init())
    .pipe($.sass({
      precision: 10,
      errLogToConsole: true
    }))
    .pipe($.autoprefixer({browsers: AUTOPREFIXER_BROWSERS}))
    .pipe($.sourcemaps.write())
});

Finally we want to write our CSS to a file in our build/styles directory. Note that we are adding a /build directory to our project using gulp which is where we will be moving files to as we add them to the project

.pipe(gulp.dest('src/styles'))

gulp.task('styles', function(){
  return gulp.src(['src/styles/styles.scss'])
    .pipe($.sourcemaps.init())
    .pipe($.sass({
      precision: 10,
      errLogToConsole: true
    }))
    .pipe($.autoprefixer({browsers: AUTOPREFIXER_BROWSERS}))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest('./build/styles'));
});

Give it a try by running gulp styles in your command line you will see the output is executing styles then creating a new directory structure /build/styles and writing you CSS in there along with sourcemap comments pointing back to original SASS code files.

Checking your JavaScript for Errors

Add a new directory inside your /src directory called scripts and inside there add a new JavaScript file called main.js. Inside that file let’s add a a simple script to append a message to index on page load using jQuery.

$(document).ready(function(){
  $('body').append('<h2>It works!</h2>');
});

Now we are going to want to run jshint to check for errors in JavaScript. To setup jshint we will be using the rules from the .jshintrc file that we copied over from example repository, next we need to install the jshint module and a reporter module for printing reports to console.

  • npm install --save-dev gulp-jshint
  • npm install --save-dev jshint-stylish

Now we can add a new task to our gulpfile for linting our code to check for errors, we’ll call it ‘scripts’.

gulp.task('scripts', function(){

});

Inside that callback we return a source glob of all JS files in src.

return gulp.src('src/**/*.js')

gulp.task('scripts', function(){
  return gulp.src('src/**/*.js')
});

Then we can call to jshint to run it’s linter.

.pipe($.jshint())

gulp.task('scripts', function(){
  return gulp.src('src/**/*.js')
    .pipe($.jshint())
});

We tell jshint to pipe results to the reporter

.pipe($.jshint.reporter('jshint-stylish'));

gulp.task('scripts', function(){
  return gulp.src('src/**/*.js')
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
}); And finally to write the files to the build directory.

.pipe(gulp.dest('build'));

gulp.task('scripts', function(){
  return gulp.src('src/**/*.js')
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe(gulp.dest('build'));
});

If you try running your new task, gulp scripts you should see that jshint has found some issues that we need to fix, the first line tells you which file the issues are in and then each issue with line numbers.

/Users/avacollins/test/src/scripts/main.js
line 2  col 3  Missing "use strict" statement.
line 1  col 1  '$' is not defined.
line 2  col 3  '$' is not defined.

We did not add the use strict directive at the top of the file and we did not declare the global varaible $ which is added to the global object by jQuery. Inside main.js let’s add

"use strict;"

to the very top of the file and below add

/* global $ */

This instruct jshint that $ is a global variable added to window by jQuery. Now re-run gulp scripts and everything should check out as well as you should now see a /build/scripts directory with your main.js copied.

Injecting CSS and JavaScript

Now we’re can use gulp-inject to add our CSS and JS to our index.html, in the command line let’s install the package.

npm install --save-dev gulp-inject

Now in our gulpfile in near the top add the gulp-inject options object as a variable.

var INJECT_OPTS = {
      addRootSlash : false,
      relative     : true
};

Below the styles task add the following inject task.

gulp.task('inject', function(){

});

Inside the inject task callback start by declaring a variable for our assets to be injected, note that this is an array which you can add additional file globs to as your project grows and all of them will be injected.

var assets = gulp.src(['build/**/*.css', 'build/**/*.js']);

gulp.task('inject', function(){
  var assets = gulp.src(['build/**/*.css', 'build/**/*.js']);
});

Then we acquire and return the source html which we will be adding our assets to, again note that source is an array and you can add additional files here as needed also.

return gulp.src(['build/index.html'])

gulp.task('inject', function(){
  var assets = gulp.src(['build/**/*.css', 'build/**/*.js']);
  return gulp.src(['build/index.html'])
});

Pipe our source to gulp-inject passing in our assets variable and our inject options.

.pipe($.inject(assets, INJECT_OPTS))

gulp.task('inject', function(){
  var assets = gulp.src(['build/**/*.css', 'build/**/*.js']);
  return gulp.src(['build/index.html'])
    .pipe($.inject(assets, INJECT_OPTS))
});

Now return our source back into src directory as well as into our distribution directory.

.pipe(gulp.dest('build/'))

gulp.task('inject', function(){
  var assets = gulp.src(['build/**/*.css', 'build/**/*.js']);
  return gulp.src(['build/index.html'])
    .pipe($.inject(assets, INJECT_OPTS))
    .pipe(gulp.dest('build'));
});

Lastly we need to tell gulp-inject where in our index.html we want to inject our assets, so inside our index.html file we need to add the following in the head area, below our bower placeholders that were added earlier.

<!-- inject:css -->
<!-- endinject -->

<!-- inject:js -->
<!-- endinject -->

Before we can try out our new inject task , we first have to run our wiredep task which will copy over our index.html with the new inject placeholders, in the command line first run gulp wiredep then gulp inject. Now open up your src/index.html you will see that your styles.css and main.js has been added.

Copy images and other assets

Last thing that we need to do before starting up server is to copy any images, or other assets, that aren’t getting moved into the build folder. Go ahead and add an images directory to your /src directory and copy over any image into that directory. Let’s also add the image to our src/index.html after our message.

<img src="images/adaTheFirst.jpg" alt="Ada Lovelace, The first Programmer">

This task is simple and no npm packages are required. Add the following task to your gulpfile.

gulp.task('copy', function(){

});

Inside the callback we start by returning our source globs, looking for everything in /src except for the processed files which are already in /build.

return gulp.src(['src/**/*.*', '!src/**/*.scss', '!src/**/*.js', '!src/index.html'])

gulp.task('copy', function(){
   return gulp.src(['src/**/*.*', '!src/**/*.scss', '!src/**/*.js', '!src/index.html'])
}); And piping that into it's destination `/build`.

.pipe(gulp.dest('build'));

gulp.task('copy', function(){
   return gulp.src(['src/**/*.*', '!src/**/*.scss', '!src/**/*.js', '!src/index.html'])
    .pipe(gulp.dest('build'));
});

Now you can run gulp copy and you shoudl see that your images directory has been moved over to the build directory.

Build

Now that we have individual tasks to process all our code let’s put it all together to create a build of our files in one step. Here is where JavaScript gets tricky, node.js and gulp.js are asynchronous, which means that tasks will execute in which ever order your computer processes the fastest, they most likely will not execute in the order in which you called them. This issue can break our injects and copies and wreak havoc on our development environment. To fix this we’ll use run-sequence.

npm install --save-dev run-sequence

Since this is not a ‘gulp-‘ prefixed package we are going to have to require the package ourselves by adding a new var at the top of our gulpfile.

var runSequence = require('run-sequence');

Now we can add our build task.

gulp.task('build', function(){

});

And inside our build task callback let’s make a call to runSequence and pass in all of our tasks. Tasks that are included in an Array are tasks that can be run in paralell safely, tasks that are passed in a a String should run to completion, before the next task can start. In our example we have two sets of parallel tasks.

runSequence(['styles', 'wiredep', 'scripts'], ['inject', 'copy']);

gulp.task('build', function(){
  runSequence(['styles', 'wiredep', 'scripts'], ['inject', 'copy']);
});

Go ahead and run gulp build and you should see your tasks executing in console output.

Adding a local web server

Now we ready for a server to run our code, instead of setting up Apache, or use node’s connect middleware we’ll be using Browsersync a tool which will run a local server while you develop and will reload files that change as you change them. There are a ton of great features and examples that can be found through the browsersync.io website. First add the Browsersync module to our project through command line and npm.

npm install --save-dev browser-sync

Back in our gulpfile we need to require the module and assign it to a variable.

var browserSync = require('browser-sync');

Since we are using RunSequence to order our tasks we can take advantage of a feature which allows us to pass in a callback as the last parameter in a sequence, which means that we will be calling BrowserSync as a function instead of a gulp task. Add the following function to your gulpfile.

function serveCallback() {
   browserSync({
    server: ['build', './']
  });
}

Here we are telling BrowserSync to start a new server and to serve files from the /build and root ./ directory of our project. We are using a very simple implementation of BrowserSynce, there are many possible options that you use and can read more about here.

Now let’s create a task to serve our build files.

gulp.task('serve',  function(){

});

And very simply we add a runSequence with the same tasks as the build task, and a callback to our server.

gulp.task('serve', function(){
  runSequence(['styles', 'wiredep', 'scripts'], ['inject', 'copy'], serveCallback);
});

Let’s give it try, on the command line type gulp serve you should see output as gulp processes the command and Browsersync launches a new web server, it should also open your index.html for you. After we verify that it is working we can tell BroswerSync to quit by typing ctrl c (on Mac).

Watch it!

Now let’s add some functions to listen for changes in our source code and re-run our tasks and reload the browser for us so that we don’t have to stop and manually do those things. First let’s install the gulp-watch module from npm.

npm install --save-dev gulp-watch

Also let’s add a variable to the top of our gulpfile to call BrowserSync’s reload function so we can manually trigger a reload.

var reload = browserSync.reload;

Let’s start by adding a new task called watch:html.

gulp.task('watch:html', function(){

});

Now add a sequence to run wiredep and inject and finally reload the browser with new content.

gulp.task('watch:html', function(){
  runSequence('wiredep', 'inject', reload);
});

Inside our serve task let’s add a line below runSequence that will handle watching our html by first passing a glob of files to watch and then tasks to be run when changes are detected.

gulp.watch(['src/**/*.html'], ['watch:html']);

Now let’s add a watch for our styles to compile and reload the css file in the browser so you can immediately see the changes.

gulp.watch(['src/**/*.scss'], ['styles', reload]);

Finally add a watch for our JavaScript files to be linted and copied when we make changes.

gulp.watch(['src/**/*.js'], ['scripts', 'copy', reload]);

Restart your serve task and change your background color in main.scss, change your message in your main.js, add some new text to your index.html, all of these changes should trigger the tasks to be re-run and you should see the changes immediately reflected in the browser. Prett nifty huh?

Distribute

Well now it feels like we have a pretty good development environment setup, but what about when we are ready to publish our code to a live server? We’re going to need to add a few more tasks that will create a web ready distribution of our code. Let’s add some new tasks similar to our build tasks but add the suffix :dist to tell us that this is the distribution version of building.

Starting with wiredep, we are gong to need to do some extra steps for our bower_components because we do not want to publish the entire bower repository to our web server, just the code that we need. We’ll also need to copy over component assets like fonts. Let’s start by adding a new fonts task.

Fonts

gulp.task('fonts', function(){

});

Since we have fontawesome we start by returning the source fonts.

return gulp.src(['bower_components/fontawesome/fonts/**/*.*'])

gulp.task('fonts', function(){
  return  gulp.src(['bower_components/fontawesome/fonts/**/*.*'])
});

And pipe those over to our /dist directory, where all of our final build will go.

.pipe(gulp.dest('dist/fonts'));

gulp.task('fonts', function(){
  return  gulp.src(['bower_components/fontawesome/fonts/**/*.*'])
    .pipe(gulp.dest('dist/fonts'));
});

Go ahead and run gulp fonts to test it out, also we can add an icon to our index.html to verify that things are working when we run our final build.

<i class="fa fa-diamond"></i>

Minify

Next we are going to want to concatenate all our bower components into a single file and then run a minifier to remove comments and whitespace to optimize download speeds.

  • npm install --save-dev gulp-concat
  • npm install --save-dev gulp-uglify

Now let’s add a task for our bower JavaScript dependencies below our wiredep task.

gulp.task('wiredep:js:dist', function(){

});

Return our source, which is a function of the wiredep library to get all JavaScript.

return gulp.src(require('wiredep')().js)

gulp.task('wiredep:js:dist', function(){
  return gulp.src(require('wiredep')().js)
});

Pipe that over to gulp-concat and tell it to create a file named vendor.js from the all the files.

.pipe($.concat('vendor.js'))

gulp.task('wiredep:js:dist', function(){
  return gulp.src(require('wiredep')().js)
    .pipe($.concat('vendor.js'))
});

Pipe again to gulp-uglify.

gulp.task('wiredep:js:dist', function(){
  return gulp.src(require('wiredep')().js)
    .pipe($.concat('vendor.js'))
    .pipe($.uglify())
});

And finally write our file to our /dist directory.

gulp.task('wiredep:js:dist', function(){
  return gulp.src(require('wiredep')().js)
    .pipe($.concat('vendor.js'))
    .pipe($.uglify())
    .pipe(gulp.dest('dist/scripts'));
});

Let’s test by running gulp wiredep:js:dist. You should see a minified file named vendor.js creates and saved in your /dist/scripts directory.

Let’s do essentially the same thing for our CSS now. Start by installing gulp-csso, a package to minify CSS.

npm install --save-dev gulp-csso

Add a new task.

gulp.task('wiredep:css:dist', function(){

});

Return our source.

return gulp.src(require('wiredep')().css)

gulp.task('wiredep:css:dist', function(){
   return gulp.src(require('wiredep')().css)
});

Pipe that to gulp-concat and name final file vendor.css.

gulp.task('wiredep:css:dist', function(){
   return gulp.src(require('wiredep')().css)
    .pipe($.concat('vendor.css'))
});

Pipe into gulp-csso to do it’s thing.

gulp.task('wiredep:css:dist', function(){
   return gulp.src(require('wiredep')().css)
    .pipe($.concat('vendor.css'))
    .pipe($.csso())
});

Finally write our output to /dist/styles directory.

gulp.task('wiredep:css:dist', function(){
   return gulp.src(require('wiredep')().css)
    .pipe($.concat('vendor.css'))
    .pipe($.csso())
    .pipe(gulp.dest('dist/styles'));
});

Go ahead and run gulp wiredep:css:dist to test.

Let’s do the same for our own JavaScript and styles. Below our styles task add a new task.

gulp.task('styles:dist', function(){

});

Start by returning our source, which is our compiled CSS in the build directory.

return gulp.src(['build/styles/styles.css'])

gulp.task('styles:dist', function(){
  return gulp.src(['build/styles/styles.css'])
});

Pipe that into the minifier.

.pipe($.csso())

gulp.task('styles:dist', function(){
  return gulp.src(['build/styles/styles.css'])
    .pipe($.csso())
});

And write our final file to the /dist/styles directory.

 gulp.task('styles:dist', function(){
  return gulp.src(['build/styles/styles.css'])
    .pipe($.csso())
    .pipe(gulp.dest('dist/styles'));
});

Test it out, gulp styles:dist.

And for our JavaScript let’s add a task.

gulp.task('scripts:dist', function(){

});

Return our source from the build directory.

return gulp.src(['build/**/*.js'])

gulp.task('scripts:dist', function(){
  return gulp.src(['build/**/*.js'])
});

Concatenate into a single file app.js.

.pipe($.concat('app.js'))

gulp.task('scripts:dist', function(){
  return gulp.src(['build/**/*.js'])
    .pipe($.concat('app.js'))
});

Minify code.

.pipe($.uglify())

gulp.task('scripts:dist', function(){
  return gulp.src(['build/**/*.js'])
    .pipe($.concat('app.js'))
    .pipe($.uglify())
});

Write to our dist/scripts directory.

.pipe(gulp.dest('dist/scripts'));

gulp.task('scripts:dist', function(){
  return gulp.src(['build/**/*.js'])
    .pipe($.concat('app.js'))
    .pipe($.uglify())
    .pipe(gulp.dest('dist/scripts'));
});

Test it out gulp scripts:dist

Copy assets

Copying our assets is the same process as it was for our development build, we just have different sources and destinations. Add your task.

gulp.task('copy:dist', function(){

});

Return source globs from /build directory

gulp.task('copy:dist', function(){
  return gulp.src(['build/**/*.*','!build/**/*.css', '!build/**/*.js', '!build/index.html', 'src/index.html'])
});

Pipe to /dist destination.

.pipe(gulp.dest('dist'));

gulp.task('copy:dist', function(){
  return gulp.src(['build/**/*.*','!build/**/*.css', '!build/**/*.js', '!build/index.html', 'src/index.html'])
    .pipe(gulp.dest('dist'));
});

Test it out gulp copy:dist

Injecting

Injecting our assets is exactly the same as before with the exception of our source values which need to be injected in a specific order, meaning third party assets first. To do that we need to install stream-series to manage the order for us.

npm install --save-dev stream-series

Since it is not a gulp- prefixed package we need to add our variable reference to the top of our gulpfile.

var series = require('stream-series');

We’re also going to want to minify our html after injecting our assets, so we’ll need to get gulp-minify-html from npm.

npm install --save-dev gulp-minify-html

Let’s add our task.

gulp.task('inject:dist', function(){

});

We need to add a couple variables one for each source.

var vendor = gulp.src(['dist/scripts/vendor.js', 'dist/styles/vendor.css']);
var app = gulp.src(['dist/scripts/app.js', 'dist/styles/styles.css']);

gulp.task('inject:dist', function(){
  var vendor = gulp.src(['dist/scripts/vendor.js', 'dist/styles/vendor.css']);
  var app = gulp.src(['dist/scripts/app.js', 'dist/styles/styles.css']);

});

Return our source index.html from the /dist directory, you will need to have run gulp copy prior to this to ensure that your source is in the /dist directory.

return gulp.src(['dist/index.html'])

gulp.task('inject:dist', function(){
  var vendor = gulp.src(['dist/scripts/vendor.js', 'dist/styles/vendor.css']);
  var app = gulp.src(['dist/scripts/app.js', 'dist/styles/styles.css']);

  return gulp.src(['dist/index.html'])
});

Pipe that into gulp-inject using stream-series to manage the ordering.

.pipe($.inject(series(vendor, app), INJECT_OPTS))

gulp.task('inject:dist', function(){
  var vendor = gulp.src(['dist/scripts/vendor.js', 'dist/styles/vendor.css']);
  var app = gulp.src(['dist/scripts/app.js', 'dist/styles/styles.css']);

  return gulp.src(['dist/index.html'])
    .pipe($.inject(series(vendor, app), INJECT_OPTS))
});

Minify the html

.pipe($.minifyHtml())

gulp.task('inject:dist', function(){
  var vendor = gulp.src(['dist/scripts/vendor.js', 'dist/styles/vendor.css']);
  var app = gulp.src(['dist/scripts/app.js', 'dist/styles/styles.css']);

  return gulp.src(['dist/index.html'])
    .pipe($.inject(series(vendor, app), INJECT_OPTS))
    .pipe($.minifyHtml())
});

And write the out put to the /dist directory.

.pipe(gulp.dest('dist'));

gulp.task('inject:dist', function(){
  var vendor = gulp.src(['dist/scripts/vendor.js', 'dist/styles/vendor.css']);
  var app = gulp.src(['dist/scripts/app.js', 'dist/styles/styles.css']);

  return gulp.src(['dist/index.html'])
    .pipe($.inject(series(vendor, app), INJECT_OPTS))
    .pipe($.minifyHtml())
    .pipe(gulp.dest('dist'));
});

Test it out gulp inject:dist

Serve your distribution build

Almost done! Last step to building and deploying your project is to serve your distribution build, which is very similar to what we’ve done with the development build. Add your distribution serve callback function, just like before but we are now serving files only from the /dist directory.

function serveDistCallback() {
    browserSync({
    server: ['dist']
  });
}

Add your distribution serve task.

gulp.task(‘serve:dist’, function(){

});

Call runSequence and pass in your build steps, and end with your serve callback. ` runSequence([‘styles’, ‘scripts’],’copy’, [ ‘wiredep:css:dist’, ‘wiredep:js:dist’, ‘styles:dist’, ‘scripts:dist’,’copy:dist’, ‘fonts’], ‘inject:dist’, serveDistCallback);`

gulp.task('serve:dist', function(){
  runSequence(['styles', 'scripts'],'copy', [ 'wiredep:css:dist', 'wiredep:js:dist', 'styles:dist', 'scripts:dist','copy:dist', 'fonts'], 'inject:dist', serveDistCallback);
});

Test it out gulp serve:dist

##Links for further reading

What is Gulp

What are Streams

What’s So Great About Bower?