AngularJS - Using RequireJS or something built in for modular development?

I have been writing a angularjs app and i have a number of controllers which I have placed in a 1 JS file. I was hoping for something a little more modular and separating my controllers into there own files.

I thought of RequireJS but is this the recommended way? or does angularjs provide something else and any clue on where it is explained?

Also having all these files is great for debugging but once a production build is required does angularJS provide some sort of merging of of the modules into 1 file and minimizing the results?

If anyone can explain the best way to go about it it would be very helpful.

Thanks

Angular dependencies injection is really great and you should create a lot of small modules.

When it comes to file organization it's way easier to have a lot a small files (one per module maybe), but then you face the issue you're talking about: what do I do with all these files? How do I load them all?

It is worth taking a look at these 2 sources: Brian Ford's blog and this Github repo. It helped me a lot improving my workflow and better understand/use Angular modules.

TL;DR

What I do for my projects is using Grunt to concat (minify if needed) all the js files (and way more: less css compilation, assets management, javascript templates compilation).
A good example is given in the Github repo above.

I don't recommend using RequireJS with AngularJS. Although it's certainly possible, I haven't seen any instance where RequireJS was beneficial in practice. [Brian Ford]

Files organization

My app folder looks like this:

www
|-dist/         = Created by Grunt. Generated files (served by my web server).
|-node_modules/ = node modules (ie. Grunt modules. Grunt is based on NodeJS)
|-src/          = My workspace
|-test/         = Some tests
|-vendor        = External libraries (AngularJS, JQuery, Bootstrap, D3, ... Whatever you need)
|-gruntFile.js  = The Grunt configuration file: contains all the jobs for Grunt.
|-package.json  = App infos + dependencies (Grunt modules) I use (concat, uglify, jshint, ...)

So all the different files I work on are in the src folder which then looks like this:

www/src
|-app              = Folder for my controllers
| |-Controller1.js
| |-Controller2.js
| |-...
|-assets           = Folder for the static assets (img, css, ...)
| |-img/
| |-css/
| |-favicon.ico
|-common           = Folder for the shared modules (directives, resources, services, ...)
| |-directives
| | |-chart.js
| | |-map.js
| | |-...
| |-resources
| | |-users.js
| | |-another-cool-resource.js
| | |-...
| |-services
| | |-service1.js
| | |-...
|-views            = Folder for my templates
| |-profile.tpl.html
| |-search.tpl.html
| |-...
|-index.html       = The main and unique html file.

Grunt

Then I use Grunt to 'compile' everything into the dist folder.
An example of a gruntFile can be found here. I have a one-time job for deployment and some watchers for development.

Do you need more explanation?

Angular allows you to define modules which can be injected into your controllers see here:

http://docs.angularjs.org/api/angular.module

These modules can be dependent on other modules which can be injected like this:

app.factory('module2', ['module1', function (module1) {
   var functions = {
       myModule2Function: function (variable) {
          return  module1.testfunction(variable);
       }
   }
    return functions;
}]);

then in the controller:

function MyController($scope, module2) { 
      $scope.aControllerFunction = function (variable) {
         return module2.myModule2Function(variable);
     }

}

Load modules on demand is what we need for really huge apps, like a trading application for instance. I think that's a smart way to handle behaviors at least on mobile devices where we don't want to load the entire app on a 3G connection. In those cases, RequireJS fits best.

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.