Kickstarting Angular with Gulp and Browserify, Part 2 - Browserify
Hello. Welcome to the second half. Last time, we built a nice Angular starter project, utilizing Gulp and Bower. Let’s take this a step further and add the power of Browserify into the mix. Before you read any further, check out the Introduction to the Browserify Handbook to learn about the problems that Browserify solves.
Just want the code? Get it here.
Contents
Install Dependencies
Let’s get Browserify installed…
First, install Browserify globally
$ npm install -g browserify
Then install the Gulp dependencies locally
$ npm install gulp-browserify gulp-concat --save
The former dependency allows you to run Browserify from Gulp, while the latter concatenates all the Bowerserify dependencies into a single JS file.
Update the Gulpfile
Update the requirements
var browserify = require('gulp-browserify');
var concat = require('gulp-concat');
Add the following tasks
gulp.task('browserify', function() {
gulp.src(['app/js/main.js'])
.pipe(browserify({
insertGlobals: true,
debug: true
}))
.pipe(concat('bundled.js'))
.pipe(gulp.dest('./app/js'))
});
Now update the default task
// default task
gulp.task('default',
['lint', 'browserify', 'connect']
);
Update the HTML
Change the included JS file in index.html.
From:
<script src="./js/main.js"></script>
To:
<script src="./js/bundled.js"></script>
Test
To recap:
- We added Browserify
- Updated the build process so that a single JS file named bundled.js is created
- Updated index.html to include that new JS file
$ gulp
Navigate to http://localhost:8888/ and you should still see:
Angular-Gulp-Browserify-Starter
Testing...
Notice the bundled.js file. Again, this is generated by concat('bundled.js')
. If you kill the server, then try to run it again, you’ll get an error. Essentially, the bundled.js file needs to be removed before each run. So update the clean
task:
gulp.task('clean', function() {
gulp.src('./dist/*')
.pipe(clean({force: true}));
gulp.src('./app/js/bundled.js')
.pipe(clean({force: true}));
});
Browserify
Remember all those Bower components in the index.js file? Let’s clean up that mess by requiring our app’s dependencies with Browserify.
Update the HTML (again)
<!DOCTYPE html>
<html ng-app="SampleApp">
<head lang="en">
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<title>Angular-Gulp-Browserify-Starter</title>
<!-- styles -->
<link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css"/>
<link rel="stylesheet" href="bower_components/fontawesome/css/font-awesome.css"/>
<link rel="stylesheet" href="bower_components/animate.css/animate.css"/>
<link rel="stylesheet" href="css/main.css"/>
</head>
<body>
<div class="container">
<h1>Angular-Gulp-Browserify-Starter</h1>
<!-- views -->
<div ng-view></div>
</div>
<!-- scripts -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
<script src="./js/bundled.js"></script>
</body>
</html>
Now, we need to use Browserify to require the following dependencies in our app:
- angular.js
- angular-route.js
- angular-animate.js
Why don’t we replace all of our Bower components? It’s good to use both Bower and Browserify in case NPM does not have a certain dependency that Bower may have. The point of this example is to show you how to use both.
Install Requirements
Go ahead and install the requirements we need via NPM:
$ npm install angular angular-route angular-animate --save
Update JS
(function () {
'use strict';
require('angular');
require('angular-route');
require('angular-animate');
angular.module('SampleApp', ['ngRoute', 'ngAnimate'])
.config([
'$locationProvider',
'$routeProvider',
function($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!');
// routes
$routeProvider
.when("/", {
templateUrl: "./partials/partial1.html",
controller: "MainController"
})
.otherwise({
redirectTo: '/'
});
}
]);
//Load controller
angular.module('SampleApp')
.controller('MainController', [
'$scope',
function($scope) {
$scope.test = "Testing...";
}
]);
}());
Now we can include various modules the “Node-way” using require()
calls, giving you access to nearly 90,000 modules.
Controller
Let’s abstract out the controller to a file of its own.
First, update main.js again:
(function () {
'use strict';
require('angular');
require('angular-route');
require('angular-animate');
var mainCtrl = require('./controllers/mainctrl');
angular.module('SampleApp', ['ngRoute', 'ngAnimate'])
.config([
'$locationProvider',
'$routeProvider',
function($locationProvider, $routeProvider) {
$locationProvider.hashPrefix('!');
// routes
$routeProvider
.when("/", {
templateUrl: "./partials/partial1.html",
controller: "MainController"
})
.otherwise({
redirectTo: '/'
});
}
])
//Load controller
.controller('MainController', ['$scope', mainCtrl]);
}());
Now create a new folder called “controllers” within “app/js”. In the new folder add a new file called mainctrl.js:
module.exports = function($scope) {
$scope.test = "Testing...";
console.log("required!");
};
This syntax should look familiar if you’ve worked with Node before. We use exports
to expose the function, which we then have access to in main.js since it’s part of the requirements.
Test Again
$ gulp clean
$ gulp
Navigate to http://localhost:8888/ to make sure everything still works.
Update the Build
Now that we have the default
task working, let’s update the build process so we can create a deployable build.
Update the Gulpfile
Add the following task to the gulpfile:
gulp.task('browserifyDist', function() {
gulp.src(['app/js/main.js'])
.pipe(browserify({
insertGlobals: true,
debug: true
}))
.pipe(concat('bundled.js'))
.pipe(gulp.dest('./dist/js'))
});
This task simply updates where the bundled.js is stored after creation.
Finally, update the build
task itself adding in the above task:
// build task
gulp.task('build', function() {
runSequence(
['clean'],
['lint', 'minify-css', 'browserifyDist', 'copy-html-files', 'copy-bower-components', 'connectDist']
);
});
Create a Build
$ gulp build
Check out the live app at http://localhost:9999/. Deploy your app, if you’d like.
Conclusion
Let’s recap. Over the past two posts, we’ve created a sample app that can be used as a seed for all of your Angular projects. Want to use this in your own projects?
- Clone the repo
- Install the global requirements:
npm install -g gulp bower browserify
- Install the local requirements:
npm install
- Install the Bower components:
bower install
- Run locally:
gulp
- Create a build:
gulp build
I encourage you to add your favorite libraries and modules, which is easy to do. Looking for a client side dependency? Be sure to check NPM first before relying on Bower so you can take advantage of the simple require
calls, via Browserify, which reduces code clutter and enables you to write modular, re-usable code.
As always, I’d love to hear your feedback. How are you using Browserify in your projects? Comment below.
Thanks for reading.