Closed mastix closed 10 years ago
I've encountered this problem literally 5 minutes ago too without any idea.
Haha... what a coincidence! :) You can set mangle to false, so variable names won't be shortened, then everything should work... but that leads to bigger JS files... :(
@mastix @fno this problem does not happen with the minified version we are providing, check our demo page: http://angular-ui.github.io/bootstrap/
I'm not sure what are the exact minification steps you are taking, but if you can prepare a minimal project showing that uglify is breaking our deliverables I can surely take a look. Otherwise this one is hardly actionable....
OK, here is more info: http://stackoverflow.com/questions/17238759/angular-module-minification-bug
and what can be done on the library level: https://github.com/gruntjs/grunt-contrib-uglify#no-mangling
I don't think we can do anything meaningful in the library so I'm going to close this issue. Will be happy to re-open if you guys think there is anything actionable on our side.
Hi,
sure, as soon as mangling is disabled, everything is cool, but that also increases the file size a lot.
I'm using ng-min before uglify (also on angular-bootstrap), but for some reason all of my controllers and included js files work fine, but the ui.bootrap file does not.
ng-min does the following:
angular.module('whatever').controller('MyCtrl', function ($scope, $http) { ... });
gets turned into:
angular.module('whatever').controller('MyCtrl', ['$scope', '$http', function ($scope, $http) { ... }]);
Now minifiers can handle AngularJS's dependency injection annotations since the attributes are added as string params in the array... but for some reason that does not work for angular-bootstrap.
So there might be actually something to check on your side!?
Thanks for your reply & help!!!
mastix
@mastix our deliverables already got all the minification-safe annotations (if you can spot places where it is not the case it is a bug that should be fixed - but I don't think so since the minified version we provide does work) so there is no reason to pass this code through the ng-min. This might actually cause problems.
Then, I'm not saying that some parts of our code make it uglify - unfriendly. If this is the case I'm all for fixing things. But in order to act we need to know which part of the code is causing problems.
@mastix @fno for now I assume that this is your custom build that is causing problems here, but I would like to be proven otherwise. So if you see anything strange please do let us know.
i dont know about the "custom" build as it seems to stem from a very popular approach using yeoman, bower and grunt while using the angular-generator.
when you install angular-bootstrap via bower into this setup, the ui-bootstrap-tpls.js is automatically added to the whole vendor.js pipeline (ngmin, uglify, etc) ... this seems to be the root cause of this.
so to reproduce:
npm install -g yo npm install -g generator-angular bower install angular-bootstrap grunt && grunt serve
as im fairly new to the js/angular ecosystem it seems not quite obvious as to where to place this problem exactly.
thanks for your time.
Don't have a solution yet... :( Kind of postponed it, until there's one available. This must be fixed before my project goes live - can't deliver my js with the long variable names! :)
well you could move the ui-bootstrap-tpls.js out of the uglify/concatenation block in your index.html
What worked for me is to exclude Angular itself from the mangling if you concatenate everything into one file. I'm not sure if it's going to work in your case, but you could give it a try.
Grunt
grunt.initConfig({
uglify: {
options: {
mangle: {
except: ['angular']
}
}
}
});
Gulp
.pipe(uglify({
mangle: {
except: ['angular']
}
}))
@mastix @fno I would really love to help here but you need to help me to help you... Couple of things:
@pkozlowski-opensource It's hard to upload it somewhere since it's kind of a process (grunt -> that minifies files) and not a resulting file.
I don't think that this is a "real" problem with your files, all I know is that when we I use ngmin on my files, they're getting converted correctly, so uglifying works like a charm there. You're file is part of this process as well (and I have no idea how to exclude it from the ngmin-step) and so ngmin is being called for that file as well.
I don't want this file to be served with a single request... it should be packaged into the whole js file.
It would be great if someone had an idea.
Thanks guys!
Btw - that's the error message:
@pkozlowski-opensource
as i already mentioned above its probably not your minified files but the way that your project is integrated into a very widespread development approach. to my knowledge other angular directives that install via bower dont exhibit this problem. i may be totally wrong here, but i think that @mastix has the same problem of attributing the real source of error here.
what seems to be happening is that bower places the ui-bootstrap-tpls.js file into the block that is later minified and concatenated as "vendor.js". the error is fixed by moving it out of the block or disabling "mangle". i'm too much of an angularjs novice to correctly attribute the real source of error, its probably a configuration somewhere that decides where to automatically place the includes.
@fno I am unable to duplicate this.
$ sudo npm install -g yo generator-angular
$ yo angular test
$ cd test
$ bower install --save angular-bootstrap
$ grunt serve:dist --force # to prevent imagemin errors
And everything works. I then added a directive to the main.html
page and it showed it just fine. Also, while I agree with @pkozlowski-opensource about not needing to run the file through ng-min
, I have done it many times as here without issue. So I don't know what's going on with your code. :-(
Is there any more information you can provide?
The problem seems to be occurring because of the concatenation.
In Index.html if you separate out ui-bootstrap-tpls.js
<!-- build:js(.) scripts/vendor2.js -->
<script src="bower_components/angular-bootstrap/ui-bootstrap-tpls.js"></script>
<!-- endbuild -->
And in your root bower.json add
...
"overrides": {
"angular-bootstrap": {
"main": []
}
}
...
Everything will work just fine and, for the most part, your files are uglified. Obviously this is just a workaround.
I got a similar bug recently, it was not caused by ngmin, uglify or ui-bootstrap per se. I my case the bug was caused by me not using array syntax when passing a controller as a parameter in modal options.
Because of ngmin I am not used to using array syntax for my controllers, services etc. so i forgot to add array syntax to the modalOptions.controller property:
// causes bug when uglifying (ngmin will not change this to array syntax)
modalOptions.controller = function($scope) { /* ... */ };
$modal.open(modalOptions)
// will work with ngmin and uglify
modalOptions.controller = ['$scope', function($scope) { /* ... */ }];
$modal.open(modalOptions)
For me this was angular ui-router
and I was injecting a property in the controller of a state and it wasn't having it.
@knutesten Thank you very much for posting your solution. Solved the problem for me as well :+1:
@knutesten Rockin! This was the ticket for me also. :sparkles:
@knutesten thanks Seems it's not an angular-ui issue.
@knutesten Banged my head around for a few hours with this problem and couldn't stack trace the problem properly. Your solution was spot on. Thanks!
This issue is generated in how the minifier system set the short variables, the angular engine define variables from controllers/services/etc name, the minifier does not edit string variable name but edit the variable param 'name' and the provider try to find a non existent variable. I get this error with grunt-uglify and my way to solve without disabling all mangle is declaring all the $varialbes:
uglify: {
options: {
mangle: {
except: [
'$anchorSmoothScroll',
'$classroom',
'$grade',
'$lesson',
'$filter',
]}}}
@sethen Same here. What was your fix?
Thank you @knutesten, it solved my problem :)
@frhd Sorry, just seeing this now.
I can't remember exactly what the issue was anymore (I commented that almost a year ago)... I remember it had something to do with the minification process in Yeoman somehow issuing a grunt build:dist
I believe. I think ui-router
will throw this error when you're doing something like:
.state('site.gateway.password-request', {
url: '^/password/request',
templateUrl: '/views/partials/templates/request.html',
controller: function ($rootScope) {
$rootScope.title = 'Password Request';
}
})
This looks right, but you need to give the controller an array with your injected stuff first like:
.state('site.gateway.password-request', {
url: '^/password/request',
templateUrl: '/views/partials/templates/request.html',
controller: [$rootScope, function ($rootScope) {
$rootScope.title = 'Password Request';
}]
})
If you don't give it an array first and issue a build, you will get the error. This may not help a lot, but that's all I can really remember.
For me it was the resolves in the states for ui router
$stateProvider.state('deals', {
url: '/deals',
templateUrl: '/contest/states/deals.template.html',
controllerAs: 'DealsCtrl',
resolve: {
deals: ['$http', function ($http) {
return $http.get('/api/deal/findactive')
.then(function (results) {
return results.data;
});
}],
It needed the ['$http', fn
@mastix @fno @pkozlowski-opensource I just hit the same issue using ui-bootstrap with these tools. The larger file size isn't an issue for me, so I'll work around it by not minifying that file. Curious though.. did resolving this issue get set aside for one reason or another?
I thought this issue was a thing of the past with ngAnnotate so was really confused when I ran into it again recently. Seems I removed the array syntax from a ui-router resolve — which ngAnnotate doesn't handle.
Actually, ngAnnotate can handle ui-router resolves; what was causing the issue was defining a controller with cironunes/angular-off-canvas and not using the array syntax. Anyone still seeing this issue and is using ngAnnotate, look through your code and make sure ngAnnotate supports anywhere you're not using the array syntax. This part of ngAnnotate's README is really helpful.
tl;dr for anyone else also reaching this issue via Google — issue wasn't with ui.bootstrap, was with me expecting ngAnnotate to annotate an unsupported declaration form.
@knutesten thanks - that was my oversight as well.
Amazing I found the solution to my problem in google leading here... @knutesten has my problem and solution (thanks!). minify is mucking up the of inline array controller syntax in the middle of code.
This won't happen if one declares the controller as a named controller rather than an inline one, which will rarely happen going forward since the documentation these days seems to promote that.
Nice Idea @knutesten :smiley: but I solve my problem with
.pipe(uglify({ mangle: false }))
OBS: in gulp
@knutesten this solved my problem!
Just a note for all of you here - you should ALWAYS turn on strictDi mode for your angular application. You can do it either via the ng-strict-di
attribute on your ng-app
element or, if you're bootstrapping your application, you can follow the instructions here. This will protect you from these type of issues moving forward.
Unfortunately, not all angular examples are good about using the strict injection declaration format and so people learn incorrectly.
I just want to point out that for all other users even with using ng-strict-di, it did not resolve this problem, or lead to this specific case.
I had a big problem with that too and I want to thank you all because a mix of answers was my good cocktail :D
I had to uncomment uglify on the Gruntfile and add the option 'mangle' with the value 'false' as mentioned by @ivomarsan. I also made a separate build for "" and added the piece of code that @PeterTrotter said to the bower.json.
And that was the solution for me!
Thank you so much!!
I found two problems,
The first is angular-bootstrap modal directive resolve problem, yeoman with grunt can not annotate the modal resolve dependency. so I write it manually.
But, The annotate problem is still there when I exec grunt build
I check the error stack in mangled code . I think the problem is angular-bootstrap modal, but i did't find the error code.
This is a bug with ng-annotate, not ui-bootstrap. For me it started after upgrading ui.bootstrap though. If we look in the ng-annotate docs, we'll find:
ng-annotate understands $uibModal.open (and $modal.open) (angular-ui/bootstrap). https://github.com/olov/ng-annotate/blob/master/IMPLICIT.md
There must be a bug with ng-annotate's handling of the newer ui.bootstrap, that uses the uib prefix. That is all I changed to replicate the bug was $modal.open to $uibModal.open, and that caused ng-annotate to stop implicitly matching.
If I tag the inline controller with @ngInject, it works:
$uibModal.open({
/** @ngInject */
controller: function($scope, $uibModalInstance) {
Or changing to this also works:
angular.controller('MyCntrl', function($scope, $uibModalInstance) {
});
$uibModal.open({
controller: 'MyCntrl'
});
In summary, this is a bug in ng-annotate, which is able to handle $modal.$open, angular.controller, but apparently not $uibModal.open -- it is not in any way ui.bootstrap's problem. It doesn't matter if you use ui-bootstrap.js, ui-bootstrap.min.js, or minify it yourself. The minification is not failing in ui.bootstrap's code, its failing to minify the code invoking ui.bootstrap (your code, not ui.bootstrap's).
Helpful tip for debugging, enable ng-strict-di & run your code through ng-annotate but do not minify. Then you will get more useful errors showing where the ng-annotate is skipping injections, causing the minification problems.
Hi, all. I was also having this issue on only one of several modal instances throughout my application, and after some debugging I realized that my problem was not using strict dependency injection in my resolve block, i.e.:
var modalInstance = $uibModal.open({
templateUrl: 'preferences.html',
controller: 'preferencesCtrl as ctrl', // this external controller was using explicit function annotation...
resolve: {
parent: [function() {
return ctrl;
}],
sectorList: ['preferencesService', function(preferencesService) { // but this was not!
return preferencesService.getSectors();
}]
}
});
Finally my issue is resolved. Please refer this url https://stackoverflow.com/questions/17238759/angular-module-minification-bug
@knutesten thanks, your solution really helped a lot. I was stuck from a while n tried almost every possible solution but not getting the reason behind. Now i get it . Thanks once again.
I'm using Laravel mix and fixed by inserting the config bellow
mix.options({
uglify: {
uglifyOptions: {
mangle: false,
}
}
})
Hi guys,
I ran into an issue yesterday when I've added the angular-bootstrap JS to my project (which has been set up using the Yeoman Angular Generator) and then it failed due to uglification.
I've added the lib via bower (uncompressed!) and it got included into the vendor.js for concatination and minification.
When the file (ui-bootstrap-tpls.js; uncompressed) is concatenated and bundled in one big vendor.js, everything looks fine, but as soon as the uglify task kicks in (with mangle: true = default), this fails (although the grunt ngmin task should rewrite the code to use Angular's inline annotation method):
The error message was pretty much this one:
Pretty much like this bug: https://github.com/yeoman/generator-angular/issues/378
Is this a bug in the angular-bootstrap code and how it's implemented? Does anybody have an idea why this is happening and how it can be fixed (without turning mangle off)?
Just a hint would be cool! :+1:
I've set mangle to false in the uglify.js code... and everything works fine, but I'd really like to turn it back to true again. :)
Regards,
mastix