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?




=  ??

+

We are a design-driven company

We bring a unique experience to our clients through visually pleasing features



    What does that mean?

    There's a greater emphasis on browsers to render  features through HTML5, CSS 3, and JavaScript.

    But there's a problem...

    1. Our HTML templates continue to grow as we add more DOM elements.  Specifically <script> tags to import JS code.
    2. JavaScript code starts to get cluttered and harder to maintain.
    3. 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




    Questions?

    Made with Slides.com