Load AngularJS app async

I'm trying to load an AngularJS app asynchronously, but I fear that this might just not be possible.

I've mostly followed the examples of this guide by CSS tricks, unfortunately without any success.

The closes attempt was to first load jQuery only, and then use it to load other scripts with an ajax call:

<script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script>
        jQuery.cachedScript = function( url, options ) {
            options = $.extend( options || {}, {
              dataType: "script",
              cache: true,
              url: url
            });

            return jQuery.ajax( options );
        };
        $.cachedScript( "https://code.angularjs.org/1.5.3/angular.min.js" )
        .done(function() {
            return $.cachedScript( "scripts/vendor.js")
        })
        .done(function() {
            $.cachedScript( "scripts/app.js", { cache : false } );
        });
</script>

In this way all scripts are loaded correctly. However, I get this error:

Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.5.3/$injector/modulerr?p0=app&p1=Error%3A%20%?0c%20(https%3A%2F%2Fcode.angularjs.org%2F1.5.3%2Fangular.min.js%3A20%3A463)

I've then tried this:

<script src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script src="https://code.angularjs.org/1.5.3/angular.min.js"></script>
<script src="scripts/vendor.js"></script>
<script>
        jQuery.cachedScript = function( url, options ) {
            options = $.extend( options || {}, {
              dataType: "script",
              cache: true,
              url: url
            });

            return jQuery.ajax( options );
        };
        $.cachedScript( "scripts/app.js", { cache : false } );

</script>

But the same error is thrown.

It seems that the problem is caused by the fact that angularjs is loaded before the app.js file, which however seems quite strange.

Thus the question, isn't it possible to load angularjs files async?

PS I did also try other ways, but they won't work as the order in which files must be loaded is mandatory (depencencies...).

For example, I've also tried the html async attribute:

<script async src="https://code.jquery.com/jquery-2.2.2.min.js"></script>
<script async src="https://code.angularjs.org/1.5.3/angular.min.js"></script>
<script async src="scripts/vendor.js"></script>
<script async src="scripts/app.js"></script>

But that fails as in this way scripts are loaded in an unpredictable order.

I've also tried to manually inject the links (without the async attribute)

(function() {
    var urls = [
        "scripts/app.js",
        "scripts/vendor.js",
        "https://code.angularjs.org/1.5.3/angular.min.js",
        "https://code.jquery.com/jquery-2.2.2.min.js",
    ];
    for (var i = 0; i < urls.length; i++) {
        var po = document.createElement('script'); po.type = 'text/javascript'; po.async = false;
        po.src = urls[i];
        var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);
    }
})();

But still without success, as they are still loaded in an unpredictable order.

Answers 1

  • If, as you said, you're using the ng-app directive, when angular parses the DOM in order to find the ngApp directive it tries to automatically bootstrap the application and, because the app.js isn't loaded yet, angular throws.

    So, you need to remove that attribute and, in your app.js add the following lines:

    angular.bootstrap(document.getElementById('ngAppContainer'), ['app']);


Related Articles