AngularJS + Rails - Problems when compressing assets

I recently created an AngularJS 1.0.0rc8 app with a Rails 3.2.3 back-end and it worked fine in development, but after deploying to Heroku there was a Unknown Provider error - apparently the app could not see the service object.

I know that it's now necessary to include angular-resource.js as a separate file and inject ngResource into the app module like this:

// main app javascript file

'use strict';

angular.module('contactapp', ['ngResource']).
  config(['$routeProvider', function($routeProvider) {
      when('/contacts', {template: 'assets/app/partials/contact-list.html', controller: ContactListCtrl}).
      when('/contacts/new', {template: 'assets/app/partials/new-contact.html', controller: ContactListCtrl}).
      when('/contacts/:contact_id', {template: 'assets/app/partials/contact-detail.html', controller: ContactDetailCtrl}).
      otherwise({redirectTo: '/contacts'});      


I also know that when files are minified that the controllers can't tell what their dependencies are unless they are also injected into the controller objects like this:

ContactListCtrl.$inject = ['$scope', '$http', 'Contacts'];

I've also tried doing it the other way that Angular recommends with bracket notation and passing in a function like this:

var ContactListCtrl= ['$scope', '$http', 'Contacts', function($scope, $http, Contacts) { /* constructor body */ }];

However, none of this seems to work.

The only way my application could see the resource provided was by turning off asset compression in the Production.rb file, like this:

# Compress JavaScripts and CSS
  config.assets.compress = false

It took several hours for me to figure this out, but I recently saw another Rails + AngularJS app that had the same issue.

Jens Krause came to the same conclusion and explains it on his blog:

If I have a relatively large app, and I need to compress the assets, how do I get around this using Angular with Rails?


If you're using Rails 4, change your js_compressor in your production and staging environments to:

config.assets.js_compressor = false)

I think the problem is that your minifier is still obfusticating the variable name of the control itself (ContactListCtrl -> a or whatever it does).

Have you tried defining your controllers with the module.controller function?

angular.module('myModule', [])
.controller('Controller1', ['dep1', 'dep2', function(dep1, dep2) {

Adding this line to my config/environments/production.rb did the trick for me:

config.assets.js_compressor = { => false) }