Does it make sense to use Require.js with Angular.js?

160,198

Solution 1

Yes it makes sense to use angular.js along with require.js wherein you can use require.js for modularizing components.

There is a seed project which uses both angular.js and require.js.

Solution 2

To restate what I think the OP's question really is:

If I'm building an application principally in Angular 1.x, and (implicitly) doing so in the era of Grunt/Gulp/Broccoli and Bower/NPM, and I maybe have a couple additional library dependencies, does Require add clear, specific value beyond what I get by using Angular without Require?

Or, put another way:

"Does vanilla Angular need Require to manage basic Angular component-loading effectively, if I have other ways of handling basic script-loading?"

And I believe the basic answer to that is: "not unless you've got something else going on, and/or you're unable to use newer, more modern tools."

Let's be clear at the outset: RequireJS is a great tool that solved some very important problems, and started us down the road that we're on, toward more scalable, more professional Javascript applications. Importantly, it was the first time many people encountered the concept of modularization and of getting things out of global scope. So, if you're going to build a Javascript application that needs to scale, then Require and the AMD pattern are not bad tools for doing that.

But, is there anything particular about Angular that makes Require/AMD a particularly good fit? No. In fact, Angular provides you with its own modularization and encapsulation pattern, which in many ways renders redundant the basic modularization features of AMD. And, integrating Angular modules into the AMD pattern is not impossible, but it's a bit... finicky. You'll definitely be spending time getting the two patterns to integrate nicely.

For some perspective from the Angular team itself, there's this, from Brian Ford, author of the Angular Batarang and now a member of the Angular core team:

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.

So, on the very specific question of AngularJS: Angular and Require/AMD are orthogonal, and in places overlapping. You can use them together, but there's no reason specifically related to the nature/patterns of Angular itself.

But what about basic management of internal and external dependencies for scalable Javascript applications? Doesn't Require do something really critical for me there?

I recommend checking out Bower and NPM, and particularly NPM. I'm not trying to start a holy war about the comparative benefits of these tools. I merely want to say: there are other ways to skin that cat, and those ways may be even better than AMD/Require. (They certainly have much more popular momentum in late-2015, particularly NPM, combined with ES6 or CommonJS modules. See related SO question.)

What about lazy-loading?

Note that lazy-loading and lazy-downloading are different. Angular's lazy-loading doesn't mean you're pulling them direct from the server. In a Yeoman-style application with javascript automation, you're concatenating and minifying the whole shebang together into a single file. They're present, but not executed/instantiated until needed. The speed and bandwidth improvements you get from doing this vastly, vastly outweigh any alleged improvements from lazy-downloading a particular 20-line controller. In fact, the wasted network latency and transmission overhead for that controller is going to be an order of magnitude greater than the size of the controller itself.

But let's say you really do need lazy-downloading, perhaps for infrequently-used pieces of your application, such as an admin interface. That's a very legitimate case. Require can indeed do that for you. But there are also many other, potentially more flexible options that accomplish the same thing. And Angular 2.0 will apparently take care of this for us, built-in to the router. (Details.)

But what about during development on my local dev boxen?

How can I get all my dozens/hundreds of script files loaded without needing to attach them all to index.html manually?

Have a look at the sub-generators in Yeoman's generator-angular, or at the automation patterns embodied in generator-gulp-angular, or at the standard Webpack automation for React. These provide you a clean, scalable way to either: automatically attach the files at the time that components are scaffolded, or to simply grab them all automatically if they are present in certain folders/match certain glob-patterns. You never again need to think about your own script-loading once you've got the latter options.

Bottom-line?

Require is a great tool, for certain things. But go with the grain whenever possible, and separate your concerns whenever possible. Let Angular worry about Angular's own modularization pattern, and consider using ES6 modules or CommonJS as a general modularization pattern. Let modern automation tools worry about script-loading and dependency-management. And take care of async lazy-loading in a granular way, rather than by tangling it up with the other two concerns.

That said, if you're developing Angular apps but can't install Node on your machine to use Javascript automation tools for some reason, then Require may be a good alternate solution. And I've seen really elaborate setups where people want to dynamically load Angular components that each declare their own dependencies or something. And while I'd probably try to solve that problem another way, I can see the merits of the idea, for that very particular situation.

But otherwise... when starting from scratch with a new Angular application and flexibility to create a modern automation environment... you've got a lot of other, more flexible, more modern options.

(Updated repeatedly to keep up with the evolving JS scene.)

Solution 3

Yes, it makes sense.

Angular modules don't try to solve the problem of script load ordering or lazy script fetching. These goals are orthogonal and both module systems can live side by side and fulfil their goals.

Source: Angular JS official website

Solution 4

This I believe is a subjective question, so I will provide my subjective opinion.

Angular has a modularization mechanism built in. When you create your app, the first thing you would do is

var app = angular.module("myApp");

and then

app.directive(...);

app.controller(...);

app.service(...);

If you have a look at the angular-seed which is neat starter app for angular, they have separated out the directives, services, controllers etc into different modules and then loaded those modules as dependancies on your main app.

Something like :

var app = angular.module("myApp",["Directives","Controllers","Services"];

Angular also lazy loads these modules ( into memory) not their script files.

In terms of lazy loading script files, to be frank unless you are writing something extremely large it would be an overkill because angular by its very nature reduces the amount of code you write. A typical app written in most other frameworks could expect a reduction in around 30-50% in LOC if written in angular.

Solution 5

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.

Share:
160,198
Admin
Author by

Admin

Updated on June 02, 2020

Comments

  • Admin
    Admin almost 4 years

    I'm a newbie to Angular.js and trying to understand how it's different from Backbone.js... We used to manage our packages dependencies with Require.js while using Backbone. Does it make sense to do the same with Angular.js?