ThomasBurleson / angularjs-Quizzler

The AngularJS Challenge: Create an online Quiz builder & testing application.
http://thomasburleson.github.io/angularjs-Quizzler
MIT License
414 stars 166 forks source link

Why use headjs + Require and not only RequireJS? #5

Closed edgarnadal closed 10 years ago

edgarnadal commented 10 years ago

Hi Thomas,

I was wondering if you can answer me that question please!

ThomasBurleson commented 10 years ago

HeadJS allows me to asynchronously load scripts and CSS without blocking the HTML page. And HeadJS will provide notifications when each script is loaded and ready. So I could use a non-AngularJS Splash Preloader while (1) all my vendor libraries load and (2) my NG SPA bootstraps.

In this way, my goal is to [ultimately] only use RequireJS to manage the package dependencies WITHOUT script loading. Once the packages are ready, I use RequireJS require() to configure and bootstrap my angularjs SPA.

To be fair, Quizzler has a development-mode, where we ask RequireJS to load our app scripts:

   head.js(
      { require    : "./vendor/requirejs/require.js",                  size: "80196"   },
      { underscore : "./vendor/underscore/underscore.js",              size: "43568"   },
      { angular    : "./vendor/angular/angular.js",                    size: "551057"  },
      { ngRoute    : "./vendor/angular-route/angular-route.js",        size: "30052"   },
      { ngSanitize : "./vendor/angular-sanitize/angular-sanitize.js",  size: "19990"   }
    )
    .ready("ALL", function() {

        require.config (
            {
            appDir  : '',
            baseUrl : './src',
            priority: 'angular',
            paths   :
            {
                // Configure alias to full paths
                'auth'         : './quizzer/authentication',
                'quiz'         : './quizzer/quiz',
                'utils'        : './mindspace/utils'
            },
            shim    :
            {
                'underscore':
                {
                    exports : '_'
                }
            }
        });

        require( [ "main" ], function( app )
        {
            // Application has bootstrapped and started...
        });

The require.config() settings enable RequireJS to dynamically load our scripts (from the baseUrl).

But in deploy-mode (@see grunt build file), the bootstrap.js file (shown above) changes to:

    head.js(
      { require    : "./vendor/requirejs/require.js",                  size: "80196"   },
      { underscore : "./vendor/underscore/underscore.js",              size: "43568"   },
      { angular    : "./vendor/angular/angular.js",                    size: "551057"  },
      { ngRoute    : "./vendor/angular-route/angular-route.js",        size: "30052"   },
      { ngSanitize : "./vendor/angular-sanitize/angular-sanitize.js",  size: "19990"   },

      { quizzler   : "./assets/js/quizzler.js"                                         }
    )
    .ready("ALL", function()
    {
        require( [ "main" ], function( app )
        {
            // Application has bootstrapped and started...
        });
    });

All application code is concat/uglified in one file: quizzler.js. And require.config() is no longer used. And [equally important] RequireJS is no longer performing on-demand loading of external script files.

Since each define() outputs some value, which is stored in an internal registry by a key that corresponds to the scripts resolved path + filename. When grunt concatenates all the scripts, these keys are generated and injected/prepended as the first argument for each define( key, dependencies, factory ) call.

Now RequireJS is only used to build a dependency tree and inject the define() factory values.

edgarnadal commented 10 years ago

Thanks for your answer.

I liked your idea of the different boot.js