32

I'm having problems with grunt build on a Yeoman generated Angular app, using Coffee and Slim, with all libraries up-to-date. (The app was just generated a few days ago with the most recent generator.)

grunt build and grunt server both worked fine initially. But after a few days of development using grunt server, I discovered that grunt build had stopped working entirely.

There were a few different problems that I fixed. The biggest one was that I had to abandon Slim entirely for my index file and use straight HTML, since grunt build was inexplicably removing 80% of the index file when it published to /dist.

Unfortunately, after I got almost everything resolved, I started getting this error in one of my Angular directives:

Uncaught Error: Unknown provider: aProvider <- a

The problem seems to be in uglify. I think it could possibly be the same problem reported here, but I'm not absolutely sure. I tried a number a number of solutions, but the only thing that has worked for me was to manually generate clean js files from my coffeescript, copy the files into /dist, and then write the paths into dist/index.html.

Obviously that's not optimal. I'm sure there's a neater way to do it in Grunt (probably by removing minification entirely from the build process, as that other user did in the link above), but I'm new to it and haven't yet figured out how to do that. Either way, it would be a workaround.

My Gruntfile is pretty basic: I've only added grunt-connect-proxy, grunt-contrib-sass, and grunt-slim to the default file. In fact, I tried to bring in a clean, newly-generated Gruntfile but it didn't build any better.

The directive that's failing is below. The error actually comes up right in the first line of the controller, $scope.showInput = false. What's frustrating is that everything works great in grunt server. The moment I build though, it falls apart entirely.

myModule.directive "editable", ->

  controller = ($scope) ->
    $scope.showInput = false

    $scope.saveContent = -> 
      $scope.toggleContent()
      $scope.save()

  linker = (scope, element, attrs) ->    
    scope.toggleContent = -> 
      scope.showInput = not scope.showInput
      setTimeout((-> element.find('input').focus()), 100)

  return DDO = 
    restrict: 'E'
    controller: controller
    link: linker
    templateUrl: "template/editable.html"
    scope:
      editableType: "@"
      text: "="
      placeholder: "@"
      save: "&"

(The template isn't really important. It just has an ng-switch that toggles using $scope.showInput.)

If anybody has any suggestions, I'd appreciate it.

Community
  • 1
  • 1
javbotero
  • 423
  • 1
  • 4
  • 4
  • 1
    possible duplicate of [AngularJS Service Config value get destroyed on minification](http://stackoverflow.com/questions/15341588/angularjs-service-config-value-get-destroyed-on-minification) – Stewie Dec 03 '13 at 00:39
  • The problem here is that ngMin (which generator-angular uses) doesn't correctly minsafe the `controller = ($scope)` part so you would have to manually minsafe that one. For things based off the `myModule` ngmin should work fine. – Eddie Monge Jr Dec 03 '13 at 22:20

1 Answers1

47

It sounds like the common issue of Angular's reliance on the name of arguments for dependency injection. Make sure when you pass dependencies that you include the dependency names as strings so that Angular will know what to inject after minification (since string values won't be changed in the minification process).

myApp.controller('myCtrl', ['$scope', '$http', function($scope, $http) {

}])

From Angular docs: A Note on minification

Simon Wicki
  • 4,029
  • 4
  • 22
  • 25
m59
  • 43,214
  • 14
  • 119
  • 136
  • Absolutely right. I realized my mistake a few minutes after I posted but didn't have time to come back and fix it until now. I had already tried injecting $scope, but I made a stupid mistake with the syntax that I just realized. – javbotero Dec 03 '13 at 02:16
  • Adding this code after the controller definition of course resolved it: controller.$inject = ['$scope'] That mistake aside, I think there is a problem in how the Slim index file was getting converted; i.e., the fact that it was losing 80% of the code in the process. I'll post separately about that, because I do think there may be a bug there. Thanks again for pointing out the mistake with injection. – javbotero Dec 03 '13 at 02:21
  • 2
    This was the answer that helped me, apart from the rest in SO. The link from angular doc was important too. – justinkoh Oct 10 '14 at 02:58
  • I still have a problem with minification. I've tried applying the same approach within my directive. In the link function, I've added the same syntax and wrapped my function and dependencies inside a square bracket but that breaks the directive, and does not even return an error. Can the same syntax be applied to a link function within the directive? – iChido Jun 28 '17 at 19:53
  • The link function does not receive arguments via dependency injection. Its arguments are: `function link(scope, element, attrs, controller, transcludeFn)` https://docs.angularjs.org/guide/directive#creating-a-directive-that-manipulates-the-dom – m59 Jun 28 '17 at 21:54