19

In this repo AngularJS is implimented with RequireJS for AMD.

In this repo the AngularJS team seeds an AngularJS project with AMD that does not include RequireJS.

  • Am I thinking about this the wrong way - I.E. are they solving different problems?
  • Does the AngularJS libary support AMD now where it had not once before?
  • Is it no longer necessary to use RequireJS with AngularJS projects?
Dan Kanze
  • 18,485
  • 28
  • 81
  • 134
  • I guess the comment on this question might be useful http://stackoverflow.com/q/12529083/1236044 – jbl Apr 19 '13 at 16:10
  • 1
    @jbl It seems that question is a little dated `asked Sep 21 '12 at 10:49`. The example provided by the Angular team here: https://github.com/angular/angular-seed/blob/master/app/index-async.html speaks to my confusion. – Dan Kanze Apr 19 '13 at 16:20
  • here is a great video that shows how to use requireJS with angularJS https://www.youtube.com/watch?v=4yulGISBF8w#t=142 – gskalinskii Oct 17 '14 at 20:32

3 Answers3

27

Using RequireJS with AngularJS makes sense but only if you understand how each of them works regarding dependency injection, as although both of them injects dependencies, they inject very different things.

AngularJS has its own dependency system that let you inject AngularJS modules to a newly created module in order to reuse implementations. Let's say you created a "first" module that implements an AngularJS filter "greet":

angular
  .module('first', [])
  .filter('greet', function() {
    return function(name) {
      return 'Hello, ' + name + '!';
    }
  });

And now let's say you want to use the "greet" filter in another module called "second" that implements a "goodbye" filter. You may do that injecting the "first" module to the "second" module:

angular
  .module('second', ['first'])
  .filter('goodbye', function() {
    return function(name) {
      return 'Good bye, ' + name + '!';
    }
  });

The thing is that in order to make this work correctly without RequireJS, you have to make sure that the "first" AngularJS module is loaded on the page before you create the "second" AngularJS module. Quoting documentation:

Depending on a module implies that required module needs to be loaded before the requiring module is loaded.

In that sense, here is where RequireJS can help you as RequireJS provides a clean way to inject scripts to the page helping you organize script dependencies between each other.

Going back to the "first" and "second" AngularJS modules, here is how you can do it using RequireJS separating the modules on different files to leverage script dependencies loading:

// firstModule.js file
define(['angular'], function(angular) {
  angular
    .module('first', [])
    .filter('greet', function() {
      return function(name) {
        return 'Hello, ' + name + '!';
      }
    });
});
// secondModule.js file
define(['angular', 'firstModule'], function(angular) {
  angular
    .module('second', ['first'])
    .filter('goodbye', function() {
      return function(name) {
        return 'Good bye, ' + name + '!';
      }
    });
});

You can see that we are depending on "firstModule" file to be injected before the content of the RequireJS callback can be executed which needs "first" AngularJS module to be loaded to create "second" AngularJS module.

Side note: Injecting "angular" on the "firstModule" and "secondModule" files as dependency is required in order to use AngularJS inside the RequireJS callback function and it have to be configured on RequireJS config to map "angular" to the library code. You may have AngularJS loaded to the page in a traditional manner too (script tag) although defeats RequireJS benefits.

More details on having RequireJS support from AngularJS core from 2.0 version on my blog post.

Based on my blog post "Making sense of RequireJS with AngularJS", here is the link.

leog
  • 778
  • 10
  • 15
20

Yes, you can use RequireJS with angular. You need to do a bit of extra work to make it function, as in the link you included, but it's possible.

In general, though, I haven't found any need for AMD with Angular. The whole idea of AMD is that it allows you to declaratively specify the dependencies between your scripts and not worry about the order in which you include them on the page. However, Angular takes care of that for you with its dependency injection mechanism, so you're not really getting any benefit by using AMD on top of that.

tl;dr I haven't found a compelling reason to use AMD with Angular.js.

Nick Heiner
  • 119,074
  • 188
  • 476
  • 699
  • 2
    Are there "any" benefits you could think of or situations that you would run into that would make you want to use Requir.js with Angular.js? Here is a related link that contributes to this discussion: http://stackoverflow.com/questions/12529083/does-it-make-sense-to-use-require-js-with-angular-js – Dan Kanze Apr 21 '13 at 02:29
  • could you explain more/ give an example of how Angularjs dependency injection mechanism work? – Tri Nguyen Jun 11 '13 at 15:05
  • 2
    Is there a way to load angularjs modules asynchronously? – SaminatorM Jan 03 '14 at 07:12
  • 2
    AngularJS doesn't load modules in Asynchronous way like requireJS. Take a look at documentation http://docs.angularjs.org/tutorial/step_07. So for lazy loading you need requireJS. – Uday Sawant Feb 21 '14 at 12:20
  • 3
    Please refer to my answer as it totally makes sense to use RequireJS given a specific scenario. – leog Jun 17 '14 at 04:03
  • 2
    RequireJS and Angular inject different things. Require can be used to manage all of your third party scripts (think jQuery, underscore, bootstrap, and angular itself), and then inject those script dependencies into your angular app. – jetcom Dec 10 '14 at 23:07
  • With AMD you don't "include" them in the webpage. RequireJS asyncronously loads those (but you don't need to reference the .js files in the html manually). – Zorgatone Oct 19 '15 at 14:19
2

You can lazy load Angular.js components using providers. From the article:

Providers are essentially objects that are used to create and configure instances of AngularJS artefacts. Hence, in order to register a lazy controller, you would use the $controllerProvider. ...

In summary, you would first define your app module to keep instances of the relevant providers. Then you would define your lazy artefacts to register themselves using the providers rather than the module API. Then using a ‘resolve’ function that returns a promise in your route definition, you would load all lazy artefacts and resolve the promise once they have been loaded. This ensures that all lazy artefacts will be available before the relevant route is rendered. Also, don’t forget to resolve the promise inside $rootScope.$apply, if the resolution will be happening outside of AngularJS. Then you would create a ‘bootstrap’ script that first loads the app module before bootstrapping the app. Finally, you would link to the bootstrap script from your ‘index.html’ file.

http://ify.io/lazy-loading-in-angularjs/

luk3thomas
  • 2,512
  • 1
  • 18
  • 20