What is grunt?
Grunt is a JavaScript task runner based on Node.js
Think of it as a Makefile, but for JavaScript web apps.
Why use grunt?
- It automates mundane tasks for web apps through plugins such as:
- Compiling SASS and LESS files
- Unit testing
- Module loading via Require.js
- Uglification
- And many more!
- Customizable
- There's a large open source community
Why use Grunt with Zensey?
= ??
+
But there's a problem...
-
Our HTML templates continue to grow as we add more DOM elements. Specifically <script> tags to import JS code.
- JavaScript code starts to get cluttered and harder to maintain.
- Adding more CSS classes increases the size of our CSS files, which creates a longer load time.
too many script tags!!!
Each script tag which points to a JavaScript file is a separate HTTP request.

profile/index.html
Angularjs
AngularJS helps developers modularize their JS code , but at the cost of separating out modules by files.
** Note that it's not necessary to modularize by files, but it was easier to navigate our JS code base.
Quirks Of angularjs
- You have to add the String literal dependencies when declaring your dependencies.
- Why?
- Because minification would rename the parameters, which then AngularJS would not know what service it's using.
angular.module('myApp')
.controller(['$scope', '$location', 'barService', 'fooService',
function($scope, $location, barService, fooService) { //something happens... }]);
Grunt to the rescue!
Let Grunt do the injection of string dependencies for you!
Developers can write their Angular components as:
angular.module('myApp')
.controller(function($scope, $location, barService, fooService) { //something happens... });
And the ng-min task will do the rest:
angular.module('myApp')
.controller(['$scope', '$location', 'barService', 'fooService',
function($scope, $location, barService, fooService) { //something happens... }]);
Quirks of Angularjs (cont)
-
The concept of controllers, directives, services, modules, and templates can be confusing when developing a large scale app like Zensey.
- We separated each AngularJS component into it's own separate folder and file.
More scripts Tags??!!
base.html ..... NOOooOOoo!!!!!
Grunt to the rescue!
Because Grunt is a task runner, it can basically do whatever you want for your web application.
The Usemin Grunt task plugin by the Yeoman team seems to do the trick!
Profile
Before Grunt
<!-- build:js /scripts/profile.js -->
<script src="/scripts/feed/activityFeed.js"></script>
<script src="/scripts/feed/controllers/feedController.js"></script>
<script src="/scripts/feed/controllers/post-activity.js"></script>
<script src="/scripts/feed/directives/add-link.js"></script>
<script src="/scripts/feed/directives/comment-ui.js"></script>
<script src="/scripts/feed/directives/toggle-comments.js"></script>
<script src="/scripts/feed/filters/twoDecimals.js"></script>
<script src="/scripts/feed/filters/replaceSpaces.js"></script>
<script src="/scripts/profile/connect-button.js"></script>
<script src="/scripts/profile/zen.profile.js"></script>
<script src="/scripts/profile/controllers/AchievementPodCtrl.js"></script>
<script src="/scripts/profile/controllers/AchievementsCtrl.js"></script>
<script src="/scripts/profile/controllers/AdminCtrl.js"></script>
<script src="/scripts/profile/controllers/ConnectionsCtrl.js"></script>
<script src="/scripts/profile/controllers/DeactivateCtrl.js"></script><!-- endbuild -->
Profile
After running the usemin Grunt task
<script src="/scripts/profile.js"></script>
Other cool things Grunt provide?
- Uglify (minification)
- Our old minifier was fragile. Needed to always specify type="text/javascript" in the <script> tags or the JS file would not get minified
- Applying hashes to minified JS and CSS files (grunt-rev)
- Concating files (CSS and JS)
- Unit Testing via Karma
- Compiling SASS files
REsults
Dashboard
Production: 69 HTTP requests with avg. 2.26 s load time
Staging (Grunt): 19 HTTP requests with avg. 1.87 s load time
Results
Paths
Production: 61 HTTP requests with avg. 1.76 s load time
Staging (Grunt): 19 HTTP requests with avg. 1.28 s time
Results
Profile (when cache was cleared)
Production: 77 HTTP requests in 7.23 s
Staging: 21 HTTP requests in 3.14 s
There's still more work to be done
We cut our HTTP requests by 3x and load time by an average of .5 seconds depending on the feature, but there's still a lot of things we can do to improve our site.
- Leverage browsing caching through response headers (https://developers.google.com/speed/docs/best-practices/caching)
- Use AngularJS template caching
- Minify CSS
- Integrate Unit Testing