Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular-ui-router breaks when uglified with gulp

I have the following simple angular.js app, following best practices outlined here.

angular
  .module('myApp', ['ui.router']);

(function() {
    function routes($stateProvider, $urlRouterProvider) {
        $urlRouterProvider.otherwise("/404");

        $stateProvider
            .state('createCluster', {
                url: '/create-cluster',
                templateUrl: 'templates/create-cluster.html'
            })
    }

    angular
        .module('myApp')
        .config(routes);
})();

I am using gulp to concat all JavaScript files, including angular-ui-router.js and run everything through uglify after. When I uglify though, I am getting:

Uncaught Error: [$injector:modulerr] Failed to instantiate module myApp due to:
Error: [$injector:unpr] Unknown provider: e

When I remove the uglification, everything works. How can I get uglification to not break ui-router?

Here is my gulp task:

gulp.task('uglify-js', function () {
  gulp.src(['client/js/libraries/**/*.js', 'client/js/source/**/*.js'])
    .pipe(concat('app'))
    .pipe(ngAnnotate())
    .pipe(uglify())
    .pipe(rename({ extname: ".min.js" }))
    .pipe(gulp.dest('client/js'))'
});
like image 346
Justin Avatar asked Jul 25 '14 21:07

Justin


2 Answers

One simple thing to get this working without changing all your code is to set the mangle option of uglify to false like so :

gulp.task('uglify-js', function() {
  gulp.src(['client/js/libraries/**/*.js', 'client/js/source/**/*.js'])
    .pipe(concat('app'))
    .pipe(ngAnnotate())
    .pipe(uglify({ mangle: false }))
    .pipe(rename({ extname: '.min.js' }))
    .pipe(gulp.dest('client/js'));
});

That keeps the names so you will not have injections problems.

like image 93
Preview Avatar answered Nov 17 '22 21:11

Preview


You should use ngannotate. This while preprocess your angular code to make it safe for uglify/minification. Ngannotate adds dependency annotations so the minifier doesn't break your dependency injection.

The angular documentation provides a note on this:

Since Angular infers the controller's dependencies from the names of arguments to the controller's constructor function, if you were to minify the JavaScript code for PhoneListCtrl controller, all of its function arguments would be minified as well, and the dependency injector would not be able to identify services correctly. We can overcome this problem by annotating the function with the names of the dependencies, provided as strings, which will not get minified.

Ngannotate does this process for you which keeps your code cleaner.

Ngmin is now deprecated and the github advises to use ngannotate. It is also faster than ngmin.

like image 4
cnaut Avatar answered Nov 17 '22 23:11

cnaut