(This post is part of my “from scratch” AngularJS project. If you are feeling lost, the first post is here.)
We’ve created quite a lot of files in just our application so far. Unfortunately, for every one of those files, it means we need to add an include to our index.html file and increase the request count for visitors just to load the app. Wouldn’t it be nice if we could just package all of our code into one file and just load that file in the application? That’s exactly what we’ll set out to do here.
There are a TON of applications that will get us the end result we are looking for: browserify, require, webpack, etc. Although, in my opinion, the simplest and easiest to understand is gulp-concat. At its very basic form, gulp-concat literally merges the files you give it into one output file. To get it going, we’ll need to have gulp installed, and get to gulp installed, we really should know what it is doing first!
Gulp (or gulp) is a javascript powered task runner. You define your tasks in a gulpfile.js file and run them from the command line. It is easiest to run gulp when installed globally, so we’ll install gulp via npm globally and also add it to our developer dependencies. We’ll also install two different gulp plugins: “gulp-concat” and “gulp-ng-annotate”. “ng-annotate” provides us with a safeguard for dependency injection. If it comes across code with a missing injection, while it is processing it will put those in.
npm install --global gulp npm install --save-dev gulp gulp-concat gulp-ng-annotate
Let’s configure our file concatenation task in our gulpfile.js:
var gulp = require('gulp'); var concat = require('gulp-concat'); var ngAnnotate = require('gulp-ng-annotate'); gulp.task('concat', function () { return gulp.src(['src/app/**/*.module.js', 'src/app/**/*.js', '!src/app/**/*.spec.js']) .pipe(concat('app.js')) .pipe(ngAnnotate()) .pipe(gulp.dest('src/app/')); });
We’ve created a task called ‘concat’ that can be run from the command line with ‘gulp concat’. Inside this task, we are loading source files with the ‘src’ command and then piping those files into a flow of commands. Since all of our angular configuration modules need to be loaded before the ‘run’ code is loaded, we will put them first. We also don’t want our tests in there, so we’ll tell it to ignore all the ‘spec’ files in those paths. The first task is to merge them together with the ‘concat’ command. We are merging these into a file called app.js. Next, we’ll fix any issues with our injections via ‘ngAnnotate()’. Finally, we’ll tell the task to output the file into the ‘src/app’ directory.
If you run this task now, you’ll see our new ‘app.js’ file get created. We can now load our single app.js file in the index.html file instead of the multiple files we were loading before. This will help reduce the amount of requests each page load will make and keep our html source cleaner. You should now be able to run http-server and have it load only the app.js file.
<!DOCTYPE html> <html data-ng-app="blackjack"> <head lang="en"> <meta charset="UTF-8"> <title>Blackjack</title> <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no" /> <style> /* This helps the ng-show/ng-hide animations start at the right place. */ /* Since Angular has this but needs to load, this gives us the class early. */ .ng-hide { display: none!important; } </style> <!-- Begin: Vendor CSS --> <link href="bower_components/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet"> <!-- End: Vendor CSS --> <!-- Begin: Source CSS --> <link href="content/blackjack.css" rel="stylesheet"> <!-- End: Source CSS --> </head> <body> <div data-ng-include="'app/layout/shell.html'"></div> <!-- Begin: Vendor JS --> <script src="bower_components/angular/angular.min.js"></script> <script src="bower_components/bootstrap/dist/js/bootstrap.min.js"></script> <script src="bower_components/jquery/dist/jquery.min.js"></script> <!-- End: Vendor JS --> <!-- Begin: Source JS --> <script src="app/app.js"></script> <!-- End: Source JS --> </body> </html>
Now that we have gulp ready for tasks, our next step (and blog post) will be to automate some of our development activities.
Here is our project up to this point:
https://github.com/adamweeks/angular-blackjack/tree/blog-post-7
Up Next: More Gulp Tasks!