Angular module().factory() is not a function after concat (gulp)

All we need is an easy explanation of the problem, so here it is.

Trying to concat/uglify my angular app using gulp for the last few hours, i have stripped down whole process to simple concat, and even removed angular file from concat process to a separate <script> request in header – and still, I receive the same error:

Uncaught TypeError: angular.module(…).factory(…) is not a function

Without concat everything is fine.

My gulp task:

gulp.task('JS', function() {
  gulp.src(['!_dependencies/angular.min.js', '_dependencies/jquery.min.js', '_dependencies/moment.min.js', 'Alpha/_lilhelpers.js', 'Alpha/routes.js' , '!trainerreg.js', '**/*.js'], {cwd: './public/scripts'})         
    .pipe(concat('concat.js'))    
    .pipe(gulp.dest('./public/min'));
});

It seems that Error basicaly happends as soon as .factory appears in code.

Here is the line on which it currently stops with error – it is a minified code, yet i am not minifiying it, im just concating files right now including angular-animate.min from which this line of code (1st one in fact).
And if I remove angular-animate it will just throw error on another factory that will be on the way.

(function(N,f,W){'use strict';f.module("ngAnimate",["ng"]).directive("ngAnimateChildren",function(){return function(X,r,g){g=g.ngAnimateChildren;f.isString(g)&&0===g.length?r.data("$$ngAnimateChildren",!0):X.$watch(g,function(f){r.data("$$ngAnimateChildren",!!f)})}}).factory("$$animateReflow",["$$rAF","$document",function(f,r){var g=r[0].body;return function(r){return f(function(){r(g.offsetWidth)})}}]).config...

UPDATE: Oh, I was mistaken, it’s NOT breaking as soon as .factory met; it breaks as soon as it meets .factory in minified part of concated file…

Will be happy to hear any solutions/assumptions!

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

I’ve found it!
Chrome was pointing to a wrong line, Firefox helped me a bit. Error itself confused me, only after some time I understood that angular.module(...).factory(...) means not that .factory is undefined but rather that something trying to invoke returned by factory value as a function i.e .factory(...)() is happening. Today I finally figured out what was the cause.
Right after one of my factories there was some 3rd party code (angular animate in this case) and it was wrapped in closure as usual, but the thing is, my factory had no ; at the end so after concat I had:

.factory('fact', function(){my-factory-code}) (function(args){3rd-party-code})()

Wrapping around closure was interpreted as function invocation due to a fact that line with factory wasn’t terminated by semicolon. And this problem was not showing up without concat, as this module was in a separate file.

Lesson – don’t forget our fellow ; 😉

Method 2

Without seeing your factory code, I’m assuming that you didn’t claim your dependencies before your function… This has happened to me in the past. MAKE SURE THAT YOUR FACTORY IS SOMETHING LIKE THIS (and it is wrapped in an anonymous function):

 (function(){
  angular.module('yourModule')
    .factory('YourFactory', ["$scope", "$state", function ($scope, $state){
       //Your Code
    }]);
  }());

For Minified AngularJS Files, you need to claim your dependencies as strings in order for it to properly minify… and its always a good idea to wrap your controllers/factories/services in anonymous functions. I hope this helps.

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply