Requiring vs Browserifying Angular

angular_blueprint_header

One of the aspects of Angular that seems to appeal to a multitude of people is its opinions on how you structure an application. Usually we consider opinions to be bad, since developers don’t want your ideas on what constitutes “correct” application architecture thrust upon them.

In the case of JavaScript, it seems that there was a mass of folks waiting for someone – anyone – to have a strong opinion on which enterprises could standardize and applications could be built, scaled and maintained by large and ever changing teams. In the end, we needed more than a foundation, we needed building plans.

blueprints

Angular’s Blueprint For Applications

The blueprint Angular offers is fundamentally quite simple – JavaScript doesn’t have a module system, so Angular provides one for you. Angular ensures that all of your JavaScript code is ready, loaded and available when your application runs. It does this primarily via dependency injection.

Consider a hypothetical, super simple application. There is one partial view. It has a corresponding controller. This controller in turn has a service injected into it for data access. Whenever the application runs, Angular makes sure that all of these “string” representations of actual modules are injected as objects.

// using Angular Kendo UI for UI components and data layer abstraction
(function () {

  var app = angular.module('app', ['ngRoute']);

  // the routeProvider is injected here (Requires Angular.Route)
  app.config(['$routeProvider', function ($routeProvider) {
    $routeProvider.when('/home',
    {
      templateUrl: 'partials/home.html',
      controller: 'HomeController'
    })
    .otherwise(
    {
      redirectTo: '/home'
    })
  }]);

  app.controller('HomeController', ['$scope', 'productsDataSource', function($scope, $productsDataSource) {

    $scope.title = 'Home';
    $scope.productsDataSource = $productsDataSource;

    $scope.listViewTemplate = '<p>{{ ShipCity }}</p>';

  }]);

  app.factory('productsDataSource', function () {
    new kendo.data.DataSource({
      type: 'odata',
      transport: {
        read: 'http://demos.telerik.com/kendo-ui/service/Northwind.svc/Orders'
      },
      pageSize: 20,
      serverPaging: true
    });
  });

}());

There is a lot going on here:

  • Declare the application module;
  • Create a factory which returns a Kendo UI DataSource;
  • Create controllers for partials injecting the DataSource into HomeCon.troller;
  • Define routes and match partials with controllers

The brilliant thing about Angular is that it mostly doesn’t matter in what order you do these things.

As long as the first app module exists, you can create any of the subsequent factories, controllers, routes or any of the rest in any order. Angular is then smart enough to look at your dependencies and load them for you, even if you specified the dependency after the dependent module. If you have been writing JavaScript for any amount of time, you know what a huge problem this solves.

Application Structure vs Physical Project Structure

At this point it at least appears as though we can create an application with some actual sanity in JavaScript. However, this app is already pretty verbose, and it does virtually nothing. Can you imagine what our file would look like in a real world app? Yikes!

The next logical step would be to break these controllers, services, and anything else we can out into separate files. This would be the physical project structure that mimics the coded one. We generally have two options here – Browserify and RequireJS

Browserifying Angular

That “app” object is really the key to everything that Angular is going to be doing. In normal usage, Angular assumes that the document will be ready by the time the application is “bootstrapped”. According to the documentation, Angular does “automatic initialization” on the DOMContentLoaded event.

It also says, “or when the angular.js script is evaluated if at that time document.readyState is set to complete“. Is it just me, or does that last sentence make zero sense? In any event, the steps Angular typically goes through whenever the DOM is ready are:

  • loads the module specified by the ng-app attribute;
  • creates the application injector – which is that thing which injects objects into other objects based on their string value;
  • compiles the HTML using whatever element contains the ng-app attribute as the root of the application and reads down the DOM tree from there.

This is how Angular is normally used. As long as all our scripts are loaded before DOMContentLoaded (think of this as document.ready), everything will be good. This makes Browserify a great solution for breaking Angular apps out into different physical files.

Using the above example, we could break down the files into the following structure…

  • app
    • partials
      • home.html
    • controllers
      • homeController.js
    • services
      • productsDataSource.js
    • app.js

Browserify allows the use of CommonJS modules in the browser. That means that each “module” needs to export itself so that it can be required by the others.

The homeController.js file would be:

// controllers/homeController.js

module.exports = function() {

  return function ($scope, $productsDataSource) {
   
    $scope.title = 'Home';
    $scope.productsDataSource = $productsDataSource;

   $scope.listViewTemplate = '<p>#: ShipCity #</p>';
  };

};

The productsDataSource.js factory is similarly simple:

// services/productsDataSource.js

module.exports = function () {
  // the productsDataSource service is injected into the controller
  return new kendo.data.DataSource({
    type: 'odata',
    transport: {
      read: 'http://demos.telerik.com/kendo-ui/service/Northwind.svc/Orders'
    },
    pageSize: 20,
    serverPaging: true
  });
};

The app.js file is where all the magic happens:

// app.js

// require all of the core libraries
require('../vendor/jquery/jquery.min');
require('../vendor/angular/angular.min');
require('../vendor/angular-route/angular-route.min');
require('../vendor/kendo-ui-core/js/kendo.ui.core.min');
require('../vendor/angular-kendo/angular-kendo');

// pull in the modules we are going to need (controllers, services, whatever)
var homeController = require('./controllers/homeController');
var productsDataSource = require('./services/productsDataSource');

// module up
var app = angular.module('app', [ 'ngRoute', 'kendo.directives' ]);

// routes and such
app.config(['$routeProvider', function($routeProvider) {
  $routeProvider
    .when('/home',
    {
      templateUrl: 'partials/home.html',
      controller: 'HomeController'
    })
    .otherwise(
    {
      redirectTo: '/home'
    });
}]);

// create factories
app.factory('productsDataSource', productsDataSource);

// create controllers
app.controller('HomeController', ['$scope', 'productsDataSource', homeController]);

And then, with all the command line skill in the world…

$> watchify js/app/**/*.js -o build/main.js

Watchify is a little utility which watches directories and “browserifys” all your code. I’ve taken some liberties here in assuming that you already have at least an awareness of browserify and what it is/does.

Some of this I like, and some of it makes me want to change my major.

I love how you can just require in vendor libraries in the app.js file. Beyond that, Browserify respects the order in which you require them in. Amazing.

I loathe the fact that I’m still manually creating controllers, factories and what not in the app.js file. It seems like I should be able to do this in the modules and pull them in. As it is, all my “Angular” code is really in the app.js file and every other file is just JavaScript. Well, it’s all just JavaScript so maybe I should shut up about it.

All in all, I like how Angular works with Browserify. I’m going to go out on a limb and say that Angular works pretty seamlessly with Browserify and I enjoyed working with it.

Next lets talk about something that I very much did not enjoy; RequireJS and Angular.

angrycat

OMG

I love RequireJS. I have written about it a bit, and use it in virtually all of my projects, both web and hybrid. I prefer it to Browserify. I believe, in my most humble of developer opinions, that RequireJS is the best way to module.

However…

Working with RequireJS and AngularJS was a vacation on Shutter Island. On the surface everything looks very normal. Under that surface is Ben Kingsley and a series of horrific flashbacks.

The issue at the core of this whole debacle is that Angular is doing things on DOM ready and doesn’t want to play your async games. Since RequireJS is all about async (AMD = Asynchronous Module Definition), reality begins to crumble around you as you try to put the pieces together.

Requiring Angular

Due to the async loading, the whole ng-app attribute is out. You cannot use it to specify your Angular app. This really tripped me up because it was the only way I knew how to Angular.

The second thing that is an issue is that darn app module. You can’t pass it around very easily without creating some crazy circular dependencies. This is an area of RequireJS that you want no part of.

There are plenty of blog posts on how to use Angular with RequireJS, but half of them I found to be incomplete and the other half looked like way more work than I wanted to do. What I ended up going with was something put together by Dmitry Eseev. I found his solution to be the most scalable and required the least amount of setup.

Based on his article, I came up with the following structure for the application…

  • app
    • partials
      • home.html
    • controllers
      • index.js
      • module.js
      • homeController.js
    • services
      • index.js
      • modules.js
      • productsDataSource.js
    • app.js
    • main.js
    • routes.js

Let’s start with the main.js file which requires in all vendor libraries (Angular, Kendo UI, jQuery) and shim’s the main app module. All of this is simply to make sure that the right files are loaded and executed in the right order.

require.config({
  paths: {
    'jquery': 'vendor/jquery/jquery',
    'angular': 'vendor/angular/angular',
    'kendo': 'vendor/kendo/kendo',
    'angular-kendo': 'vendor/angular-kendo',
    'app': 'app'
  },
  shim: {
    // make sure that kendo loads before angular-kendo
    'angular-kendo': ['kendo'],
    // make sure that 
    'app': {
        deps: ['jquery', 'angular', 'kendo', 'angular-kendo']
    }
  }
});

define(['routes'], function () {

  // create an angular application using the bootstrap method
  angular.bootstrap(document, ['app']);

});

Notice that the application is manually bootstrapped here. What this file is basically saying is, “load all of these files, then run angular on the document with ng-app set to ‘app'”. Since this file is loaded asynchronously by RequireJS, we have to use this “manual bootstrap” method to start the Angular application.

By the time that angular.bootstrap method is reached, all of the files have already been loaded. How does that happen? All via dependencies resolved by RequireJS. Notice above that the define function is asking for the routes.js file. RequireJS then loads this file before executing the angular.bootstrap method.

// routes.js

define([
  './app'
], function (app) {

  // app is the angular application object
  return app.config(['$routeProvider', function ($routeProvider) {
    $routeProvider
      .when('/home',
        {
          templateUrl: '/app/partials/home.html',
          controller: 'homeController'
        })
      .otherwise(
        {
          redirectTo: '/home'
        });
    
  }]);
});

The routes.js file has declared that app.js is a dependency. The app.js file create the angular application object and exposes it so that the routes can be defined off of it.

// app.js

define([
  './controllers/index',
  './services/index'
], function (controllers, index) {

  // the actual angular application module, passing
  // in all other modules needed for the application
  return angular.module('app', [
    'ngRoute',
    'kendo.directives',
    'app.controllers',
    'app.services'
  ]);
});

The app.js file creates the module and injects all of the required dependencies. This includes the ngRoute service, the Angular Kendo UI Directives and two other modules that we have yet to see, but were defined as dependencies in the top of the file. Those are the controllers/index.js file and the services/index.js file. Let’s break down the “controllers/index.js” file.

// controllers/index.js

define([
  './homeController'
], function () {
    
});

That code does nothing besides load dependencies. There is only one currently, but a larger application could and will have many, many controllers. All of those controllers would be loaded in this file. Each controller is then contained in a separate file.

// controllers/homeController.js

define([
  './module'
], function (module) {

  module.controller('homeController', ['$scope', '$productsDataSource',
    function ($scope, $productsDataSource) {
      $scope.title = 'Home';
      $scope.productsDataSource = $productsDataSource;

      $scope.listViewTemplate = '<p>#: ShipCity #</p>';
    };
  );

});

That’s the same old HomeController code, but it requires a module.js file. Another file?! Yep – last one for controllers. Its sole job is to create the app.controllers module so that it’s available when we try and create a controller off of it in any controller file.

// controllers/module.js

define([
], function () {

  return angular.module('app.controllers', []);

});

Let’s recap what just happened since that was pretty intense.

  • “main.js” requires “routes.js”
    • “routes.js” requires “app.js”
      • “app.js” requires “controllers/index.js”
        • “controllers/index.js” requires all controllers
          • all controllers require “module.js”
            • “module.js” creates the “app.controllers” module

That’s kind of a hairy dependency tree, but it scales really well. If you add a new controller, you just add the “controllers/nameController.js” file and add that same dependency to the “controllers/index.js” file.

The services work the same exact way. The app.js module requires the services/index.js file which requires all services. All services each require the services/module.js file which simply creates and provides the app.services module.

Back in the app.js file, all of these items are loaded in and passed to the Angular application module that we created. The very last thing that happens is that angular.bootstrap statement in the main.js file. Basically, we started at the top and worked our way to the bottom.

It’s far from ideal though.

RequireJS is forced to load all of the application code before the application ever runs. That means no lazy loading of code. Of course, you could make the argument that you should be using r.js to build all of your code into one file anyway, but you are still forcing the browser to load and parse every single bit of your code. I would consider that a micro-optimization though. If you find yourself with a bottleneck caused by JavaScript parsing, you may have just written Gmail, and you’ve got much bigger problems than how to structure your modules.

Browserify Or Require Or ?

I’ve already professed my preference for Require in most situations, but I actually believe that Browserify is better for AngularJS applications; if nothing else because you get to remove the async component, which really drops several levels of complexity.

Browserify and RequireJS are not the only module loaders on the planet. There are several others that are up and coming and worth looking into. I’ve recently heard great things about WebPack, which apparently not only works with AMD and CommonJS, but also any assets that might be going from the server to the client. It also handles pre-processors like LESS, CoffeeScript, Jade and others.

What module loader do you use with AngularJS? Have an opinion about Browserify vs Require? What about the Angular Seed Project? There are lots of options out there and I would love to know what everyone else is doing to get a structure that is as sexy and robust as Angular itself is.

Blueprint photo by Will Scullin

Cat photo titled “Angry Tiger” by Guyon Moreé

Comments

  • axel cateland

    Great article, wish i had one like this one year ago when i started to use requireJS on my angularJS projects.

    • burkeholland

      It was WAY harder than I expected it to be! I spent a lot of time and emotional energy trying to get this to work and it seemed like it should have been easier.

  • g_goodman

    I’ve started using Webpack in my rewrite of Plunker. I enjoy being able to declare style dependencies via Javascript.

    Beyond this convenience, I think it has let me reduce a bit of boilerplate in a way that lets me rewire things very quickly.

    In this gist https://gist.github.com/ggoodman/f9a55c731c419fad487a I’ve copied an older webpack.config.js as well as an earlier version of the entrypoint of the editor SPA (editor.js).

    What you can see is that webpack’s loader system lets me combine CommonJS with AngularJS’s DI in an elegant and intuitive way:

    var Angular = require(“angular”);

    module.exports =
    Angular.module(“plunker.editor”, [
    require(“angular-bootstrap”).name,

    require(“plunker.components.commander”).name,
    require(“plunker.components.notifier”).name,
    require(“plunker.components.sidebar”).name,
    require(“plunker.components.toolbar”).name,
    require(“plunker.components.visitor”).name,
    require(“plunker.components.workspace”).name,
    ])

    .service(….);

    There is a simple custom plugin that rewrites require strings according to my file structure and a custom loader that lets me adjust vendor components so that they export their main module in a CommonJS fashion.

    Great article Burke!

    • burkeholland

      I like that WebPack will pack pretty much all of the internet, not just the JavaScript.

  • darren2287

    I believe the single file is the way to go, but once that file hits a certain file size, then it would be safe to think about RequireJS. In case anyone is interested I have a skeleton project that not only does the main file creation but will also run a static server and headless tests with some other goodies here: https://github.com/dlabey/Angular-Grunt-SASS-Workflow-Skeleton.

  • yesimahuman

    Nice post Burke!

    One thing I find myself doing lately is only using one module in my angular projects, and defining it as a globally-accessible variable in the project (that will be encapsulated through a gulp build process). That reduces the annoyance of having to hard code module names and remember imports, and is just a lot more pleasant.

    As a consequence of this I tend to do a lot more with Gulp now, building the entire project into a single file, etc.

    • burkeholland

      Interesting! So you just put the app module in the window and reference it from all of your files? How do you ensure that the object exists when you go to reference it?

      • yesimahuman

        Generally the include order of the gulp concat task will keep top-level directory entries first in the order, then everything flows from there. Sometimes you’ll see an explicit gulp insertion for the module definition as well.

        So yea, we are putting it globally as far as the angular code is concerned, but like CoffeeScript, the whole thing gets wrapped in a closure to keep it from leaking.

  • rally25rs

    I might be missing something, but since Angular already has dependency injection built-in, you don’t need Require or Browserify to handle that aspect. That leaves just module loading. Using Require, if you are going to just r.js optimize all your files into a single file, then you might as well skip require.js completely. Your “build” process can just be “concatenate *.js and minify” can’t it? When using ASP.NET, I’ve just created a “bundle” for all my app code that is just bundles.Add(new ScriptBundle(“~/bundles/app”).Include(“~/App/*.js”)); and let the bundler concat and minify everything for me.

    • burkeholland

      Does that mean that every time you create a new file you have to add it to the bundler? Or do you just wildcard a directory? How are you sure that the app module exists when the other modules reference it?

      • rally25rs

        Slight correction. I re-checked my code,and what I did was to put everything but my main app.js file into subfolders to keep them organized, and can then wildcard them. The ASP.NET bundler respects ordering, so I just add app.js to the bundle first before wildcards:

        bundles.Add(new ScriptBundle(“~/bundles/app”).Include(
        “~/App/app.js”,
        “~/App/providers/*.js”,
        “~/App/directives/*.js”,
        “~/App/controllers/*.js”));

        I think uglify.js respects ordering when you pass multiple files in, so I would bet there is an easy way to make a Grunt task to just pass all files to it for non-.NET projects.

        • burkeholland

          Wow. I had no idea that the bundler would do this and respect the order. That’s huge. I’m starting to understand the appeal of Angular a whole lot more based on these comments.

      • Bojan Matić

        This is an exert from our gulpfile:

        // Compile JS
        gulp.task(‘compile’, function () {
        // Important that we first bring in the module.js files then all
        // others after. This is because module declaration has to come
        // before defining any resources on the module e.g. the module needs
        // to exist to be appended to. This can work with the below
        // declaration because we have the convention of always defining
        // modules in a module.js file in the root of their directory and we
        // rely on the fact that gulp is smart enough to not include the
        // same file twice.
        gulp.src([‘./ng/**/module.js’, ‘./ng/**/*.js’])
        .pipe(stripDebug())
        .pipe(concat(‘ng-app.min.js’))
        .pipe(ngAnnotate())
        .pipe(uglify())
        .pipe(gulp.dest(“./js”))
        /* end */;

        The way this works:
        We have separate modules *PER FUNCTIONALITY* and each module has it’s routing setup, it’s services, controllers etc. The directory structure for a module is like this:

        module_dir/module.js => Module declaration and configuration in this file
        module_dir/controllers/*.js => All the module controllers
        module_dir/services/*.js => All the module services
        module_dir/directives/*.s => All the module directives
        module_dir/templates/*.html => All the module templates
        And in your index.html you just load ng-app.min.js and you’re good to go. I can add and delete modules and their files willy-nilly and they get automatically pulled into ng-app.min.js in the correct order.

        • Brad Williams

          Fwiw I do almost exactly the same thing on my latest angular app: use gulp to (1) bundle all .js files, specifying a few root .js files first explicitly but then the rest via subdirectory wildcards; and (2) build the main html file’s list of tags too — either the full set for dev, or just the tags for the bundle(s) when doing a prod build. It is simple so I have a hard time seeing a benefit for my angular projects of using a non-angular module/dependency system. The key is indeed understanding that for the most part, *script order doesn’t matter in an angular app*, as long as you include 3rd party libs and your angular app before the rest of your angular things.

          Maybe I am just burned because of using require.js on one angular app and OMG indeed. Once we figured out that the async feature was being completely defeated (as soon as the user hit a page, most of the app was being loaded), we ripped require.js out to get rid of the verbose syntax and that soul-crushing config file.

          Having said all that, I think it all depends on the specific requirements of the system. If I was building a large mobile web app, I *might* be concerned that loading 80K of js upfront is not ideal, and might prioritize lazy loading the app in parts using something like require.js.

    • JustinBeaudry

      Angulars’ dependency management doesn’t organize the actual file loading dependencies. It doesn’t handle placing the script tags in the proper order so say jquery is loaded before angular is. Your ASP.NET seems like it handles that for you, but in most use cases I would say Browserify or RequireJS are a nice, well documented, widely used alternative.

    • Spent some time writing up a method like this using Node https://medium.com/@dickeyxxx/best-practices-for-building-angular-js-apps-266c1a4a6917

    • Jason Hamm

      The DI from Requirejs and Angularjs are 2 different types of DI. Check out this link. (https://www.youtube.com/watch?v=4yulGISBF8w). They work great together. I have a project that I have structured in this manner that has made life extremely simple. Debugging and navigation is really nice.

  • Pingback: Requiring Versus Browserifying Angular - | Soft...()

  • pmuellr

    In the “Or ?” category, I wrote this little tool a while ago – https://www.npmjs.org/package/ang-tangle

    The main idea is to keep your app DRYer, and to make it easier to inline HTML/JSON so you don’t need to go fetchin’ it every time. Also cat’s the resulting js into a single file and gives you a sourcemap for the whole wad so you can debug it in style.

    The “angular” bits of one of the sample apps is here – https://github.com/pmuellr/ang-tangle/tree/master/samples/sample-02/ang

  • This is a difficult topic for sure! And the most complicated issue plaguing heavy front-end JS applications today. Props for tackling it.

    Worth a mention in this context is systemjs (https://github.com/systemjs/systemjs). Why? Because in a perfect world we’d be writing ES6 modules, shimming until we have too, and praying that our ES6 modules written today will provide future proofing for tomorrow.

    • burkeholland

      I had not heard of that one! Need to give it a try. Being ES6 module ready today would be a huge added benefit.

  • Radu Brehar

    I prefer AMD during development, but I build for production using browserify. To ease this transition I’m using https://www.npmjs.org/package/unamd

  • StackFull Paul

    I’ve been working on a webpack plugin to assemble dependencies based on angular module definitions. https://github.com/stackfull/angular-webpack-plugin It works, but there are a lot of caveats. Hoping angular 2.0 fixes all these woes!

  • borisli

    I am actually having hard time understanding the issue of AngularJS bootstrapping in accordance to document.readyState value. Can you please elaborate the issue you see in this? Thanks

  • Konstantin Raev

    Nice overview.
    I have been scratching my head thinking about moduling and bootstrapping in Angular for the last year.

    I guess it all depends on the size of your app.

    For small ones, under 100 components, I would use simple script concatenation and Angular bootstrap mechanism to deal with script load order.
    Webstorm offers nice integration and live editing, perfect for this.

    For larger – it depends. Webpack looks like a better alternative to r.js, it makes my brain boil every time I need to set up new build of a require projevt.

    There is a nice lib for lazy loading with Angular for very large apps: github.com/ocombe/ocLazyLoad

    And I wrote a few related notes to all this medium.com/@bestander_nz

  • Pingback: Issue #9 – Tales from the Front End()

  • hi burkeholland.
    Great Post – i was thinking of using the same method for the main module file which should define the module.
    In this way the definition of the module is organised and required in it main file.
    ”’
    var guestsCtrl = require(‘./guests.ctrl’);
    var guestsSrv = require(‘./guests.srv’);
    angular.module(‘guests’, [])
    .controller(‘guests.list.ctrl’, guestsCtrl)
    .factory(‘guests.list.srv’, guestsSrv);
    ”’

    I was wondering ho you handle 3rd party commonjs incompatible files?
    I saw this module – https://github.com/thlorenz/browserify-shim – however, adding each time a 3rd party to a shim (at least manually) can be tedious. automating this process with grunt/gulp is taking a step back in the idea of using browserfiy – and the require method.

    is there a way for browserify to shim?
    Thanks,

    • paulmcpazzi

      I’m trying to find a solution to the same problem.
      Right now I’m exporting the module definition in browserify-shim:

      {
      “browser”: {
      “angular”: “./bower_components/angular/angular.js”,
      “angular-route”: “./bower_components/angular-route/angular-route.js”
      },
      “browserify-shim”: {
      “angular”: {
      “exports”: “angular”,
      “depends”: “jquery”
      },
      “angular-route”: {
      “depends”: “angular”,
      “exports”: “angular.module(‘ngRoute’)”
      }
      }
      }

      So that at least I can do something like:

      var angular = require(‘angular’);

      var myApp = angular.module(‘myApp’, [
      require(‘angular-route’).name
      // and so on…
      ])

      The are several alternatives like debowerify or shimbro that can be used to automate or partially automate this process, but they don’t play very well with angular.

  • kidkarolis

    Something’s very wrong here. You should be able to

    1. take the exact same code you used in the browserify example
    2. wrap each file in define(function (require, exports, module) { … })
    3. add a bit of shim config for vendor libraries to ensure loading order is correct

    and you should be good to go, the way require.js and browserify work conceptually is much more similar than you think. I don’t understand why the structure of the code had to be changed at all in the require.js example. Makes this blog post look like some kind of propaganda :-/

    I wanted to illustrate this with code, but I couldn’t get your browserify version working – if you have the working code for it, could you push it to github or similar?

  • Nice article.

    Have you consider injecting the app variable inside the module?

    For example:

    //main.js
    var app = angular.module(…);
    var services = require(‘services’);
    services.load(app);

    //services.js
    exports.load = function(app){
    app.service(…)
    }

    This way, you will encapsulate everything about the service in the file, including it’s configuration, dependencies, etc.

    • Ruslan Stelmachenko

      Yes. No one notice but I think it is biggest downside for any of both solutions.

      We wrote:

      app.controller(‘HomeController’, [‘$scope’, ‘productsDataSource’, homeController]);

      in one file and just:

      module.exports = function() {
      return function ($scope, $productsDataSource) {

      in another.

      In that another file we even don’t know what is it when editing? Controller? Servise? Which controller? We know it only by filename. Also if we for example add another dependecy we need not forget to add it also to our module file where array declaration syntax actually used. It’s all decouple things that need to be coupled.

    • Ruslan Stelmachenko

      Yes. No one notice but I think it is biggest downside for any of both solutions.

      We wrote:

      app.controller(‘HomeController’, [‘$scope’, ‘productsDataSource’, homeController]);

      in one file and just:

      module.exports = function() {
      return function ($scope, $productsDataSource) {

      in another.

      In that another file we even don’t know what is it when editing? Controller? Servise? Which controller? We know it only by filename. Also if we for example add another dependecy we need not forget to add it also to our module file where array declaration syntax actually used. It’s all decouple things that need to be coupled.

    • Ruslan Stelmachenko

      Yes. No one notice but I think it is biggest downside for any of both solutions.

      We wrote:

      app.controller(‘HomeController’, [‘$scope’, ‘productsDataSource’, homeController]);

      in one file and just:

      module.exports = function() {
      return function ($scope, $productsDataSource) {

      in another.

      In that another file we even don’t know what is it when editing? Controller? Servise? Which controller? We know it only by filename. Also if we for example add another dependecy we need not forget to add it also to our module file where array declaration syntax actually used. It’s all decouple things that need to be coupled.

  • Chris Thielen

    I’m using AngularAMD’s “ngload” requireJS plugin to lazy load ui-router angular modules. Check out the “future states” demo at http://bit.ly/UIRXtras

  • Sharondio

    We do Browserify and put everything into NPMs (internally), so each controller, service, and yes, even directives go into NPMs, which are registered in the app’s package.json. Then we just require everything in:

    // Controllers
    require(‘./controllers/main.js’)(app)
    require(‘./controllers/customer-list.js’)(app)

    // Services
    require(‘ep-authenticated-user/angular-service’)(app)
    require(‘ep-toast-service’)(app)
    require(‘./services/customerSvc.js’)(app)

    // Directives
    require(‘ep-pager-directive’)(app)

    We get around the “available to the front-end” issue in directives by in-lining CSS and related images.

    • beauX tschirhart

      Are ‘you’ still following this pattern? Is there somewhere I can see how you have your actual controllers vs. services vs. app configuration set up? Seems like you still go back and forth between npm and local files with the ./services/customerSvc.js reference…in the ‘end’ (aka distributed js file), is there any difference?

  • cuew1987@gmail.com
  • cuew1987@gmail.com

    How to install angular and angular-route use npm in my angular project with browserify ?

  • Honza Peša

    tl;dr – You can do better when trying Require with Angular.

    I think I packed Angular and Require in a quite elegant way. Few notes:

    I divide app into “core” (consisting of core modules) and “other modules / extensions”. Core libraries and app core are loaded before bootstrap (app core can be very thin), other modules are loaded async (!) via nice async Angular loader – ocLazyLoad – based on which state I “visit” in ui-router (or manually).

    Also, I have directory structure that I believe can actually scale up to some huge enterprise app. That means not splitting by code type (controllers, directives, etc.) but rather by modules (components). I don’t have “empty” index and module files, I have actual module declarations which pack, load and register their controllers, services, etc. These modules can have their configs, routing, etc., so you can just hire someone to build you a part of the app with its independent routing and logic. To be more specific I copied out an example – localization module from my test app core: https://gist.github.com/smajl/1d02b96fc44c29c02d06#file-core-localisation-module

    As you see in example, I don’t return angular modules anywhere from require define wrappers, I register them and require them before declaring them as dependencies in core. And everything else is eventually loaded and registered async.

    I appreciate Browserify, but I decided to go in a way, where you can divide app into minified and packed blocks which are loaded on demand and this is the way for me. 😉

    • Gopal Saini

      I also agreed. RequireJS is awesome if we use it along with oclazyload & ui-router.

  • You may want to take a look at my article about how RequireJS makes sense with AngularJS. It introduces a way to use AngularJS modules in a more friendly way to create a complex app structure, hopefully it can help to steady the balance between these two alternatives. http://leog.me/log/making-sense-of-requirejs-with-angularjs

  • Pingback: Best Practices for Building Angular.js Apps with Browerify()

  • David Chase

    Can you please explain why requirejs is better than browserify?
    and why would you ever include jquery with angular?

  • browserify example have a little wrong

    module.exports = function() {
    return function ($scope, $productsDataSource) {

    $scope.title = ‘Home’;
    $scope.productsDataSource = $productsDataSource;

    $scope.listViewTemplate = ‘#: ShipCity #’;
    };

    };

    >above should instead of bottom code

    module.exports = function ($scope, $productsDataSource) {

    $scope.title = ‘Home’;
    $scope.productsDataSource = $productsDataSource;

    $scope.listViewTemplate = ‘#: ShipCity #’;
    };

  • Dmitri

    Luckily I came across this awesome article explaining that you don’t need neither RequireJS nor Browserify:

    https://medium.com/@dickeyxxx/best-practices-for-building-angular-js-apps-266c1a4a6917

    Using Gulp I am minimizing and concatenating my code, and refresh on every save, so I can put my source files anywhere I want without any need to painfully update the paths (like in both RequireJS and Browserify).

    Also this allows me to keep plain angular modules, instead of wrapping them into `module.exports` (that doesn’t work by itself without browserify) or `define/require` blocks.

  • Pingback: Web Dev Tools 101: Modules (Part 2) | Shellmonger()

  • szahn

    RequireJS is a pain in the ass and adds superfluous markup . Why can’t you just concat all JS files using gulp?

  • szahn

    RequireJS is a pain in the ass and adds superfluous markup . Why can’t you just concat all JS files using gulp?

  • szahn

    RequireJS is a pain in the ass and adds superfluous markup . Why can’t you just concat all JS files using gulp?

  • Amit Thakkar

    Can we load controller file on route change with browserify? instead of bundle them into single file? I want to load controller file on demand only… any idea how we can implement it??

  • Pingback: Web Dev Tools 101: Modules (Part 2) | Adrian Hall()

  • Luis Troya

    How do you manage dependency injections with Browserify and CommonJS?