Avoir le temps sacré d'essayer de comprendre pourquoi la minification ne fonctionne pas.
J'ai injecté via un objet array mes fournisseurs avant la fonction, en fonction de nombreuses suggestions sur le Web, et pourtant, "fournisseur inconnu: aProvider <- a"
Ordinaire:
var app = angular.module('bpwApp', ['ui.bootstrap', 'ui', 'myTabs'])
.config(['$routeProvider', '$locationProvider', function($routeProvider, $locationProvider){
$routeProvider.
when('/', {templateUrl: 'partials/home.jade', controller: HomeCtrl});
$locationProvider.html5Mode(true);
}])
Minified:
var app = angular.module('bpwApp', ['ui.bootstrap', 'ui', 'myTabs'])
.config(['$routeProvider', '$locationProvider', function(a, b){
a.
when('/', {templateUrl: 'partials/home.jade', controller: HomeCtrl});
b.html5Mode(true);
}])
Toute suggestion serait très obligée!
AndrewM96 suggestion de ng-min
est juste.
L’alignement et l’espace blanc importent autant pour Uglify que pour Angular.
J'ai rencontré ce problème auparavant avec Grunt.js Uglify plugin.
Une des options est mangle
uglify: {
options: {
mangle: false
},
Ce qui, je crois, exécute les fonctions regex sur "comme des chaînes" et les minifys.
Par exemple:
angular.module("imgur", ["imgur.global","imgur.album"]);
Deviendrait:
angular.module("a", ["a.global","a.album"]);
Désactivez-le: cette fonctionnalité ne joue pas avec Nice avec Angular.
Pour être plus précis comme l'explique @JoshDavidMiller:
Uglify mangle
ne modifie que les variables, ce qui cause le problème AngularJS. C'est-à-dire que le problème réside dans l'injection et non dans la définition.
function MyCtrl($scope, myService)
serait mutilé en function MyCtrl(a, b)
, mais la définition du service à l'intérieur d'une chaîne ne devrait jamais être altérée.
ng-min
Avant d’exécuter uglify
résout ce problème.Angular a un injecteur de dépendance intégré qui transmettra les objets appropriés à votre fonction en fonction du nom de ses paramètres:
function MyController($scope, $window) { // ... }
Ici, les noms des paramètres
$scope
Et$window
Seront comparés à une liste de noms connus, et les objets correspondants seront instanciés et transmis à la fonction. Angular) obtient les noms de paramètres en appelanttoString()
sur la fonction, puis en analysant la définition de la fonction.Le problème avec ceci, bien sûr, est que cela cesse de fonctionner dès que vous réduisez votre code . Étant donné que vous vous souciez de l'expérience utilisateur, vous réduirez votre code. Par conséquent, l'utilisation de ce mécanisme d'identification interne endommagera votre application. En fait, une méthodologie de développement courante consiste à utiliser du code non minié dans le développement pour faciliter le débogage, puis à réduire au minimum le code lors du passage en production ou en transfert. Dans ce cas, le problème ne se posera pas tant que vous n’aurez pas atteint le point le plus douloureux.
(...)
Puisque ce mécanisme d’injection de dépendance ne fonctionne pas dans le cas général, Angular fournit également un mécanisme. Il est bien sûr qu’il en fournit deux. Vous pouvez soit faire passer un tableau de la manière suivante:
module.controller('MyController', ['$scope', '$window', MyController]);
Ou vous pouvez définir la propriété
$inject
Sur votre constructeur:MyController.$inject = ['$scope', '$window'];
Vous pouvez utiliser ng-annotate
pour ajouter automatiquement des annotations requises pour réduire:
ng-annotate
Ajoute et supprime les annotations d'injection de dépendance AngularJS. Il est non intrusif, votre code source reste donc exactement le même. Pas de commentaires perdus ni de lignes déplacées.
ng-annotate
Est plus rapide et plus stable que ngmin
(qui est maintenant obsolète) et contient des plugins pour de nombreux outils:
Depuis AngularJS 1.3, il y a aussi un nouveau paramètre dans ngApp
appelé ngStrictDi
:
si cet attribut est présent sur l'élément de l'application, l'injecteur sera créé en mode "strict-di". Cela signifie que l'application n'appellera pas les fonctions qui n'utilisent pas d'annotation de fonction explicite (et ne conviennent donc pas à la minification), comme décrit dans le guide d'injection de dépendance , et des informations de débogage utiles vous aideront à localiser la racine de ces insectes.
J'ai la même erreur. Cependant, pour moi, le problème est la déclaration du contrôleur des directives. Vous devriez le faire à la place.
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
templateUrl: 'directive.html',
replace: false,
restrict: 'A',
controller: ["$scope", "$element", "$attrs", "$transclude", "otherInjectables",
function($scope, $element, $attrs, $transclude, otherInjectables) { ... }]
};
return directiveDefinitionObject;
});
J'ai eu un problème similaire en utilisant grunt, ngmin et uglify.
J'ai couru le processus dans cet ordre: concat, ngmin, uglify
Je continuais à obtenir l'erreur $ injector de angular jusqu'à ce que j'ajoute l'option uglify mangle: false - tout était alors corrigé.
J'ai aussi essayé d'ajouter les exceptions à uglify comme ceci:
options: {
mangle: {
except: ['jQuery', 'angular']
}
}
Mais en vain...
Voici mon gruntFile.js pour plus de précisions:
module.exports = function(grunt) {
'use strict';
// Configuration goes here
grunt.initConfig({
pkg: require('./package.json'),
watch: {
files: ['scripts/**/*.js', 'test/**/*spec.js', 'GruntFile.js'],
tasks: ['test', 'ngmin']
},
jasmine : {
// Your project's source files
src : ['bower_components/angular/angular.js', 'bower_components/angular-mocks/angular-mocks.js', 'scripts/app.js', 'scripts/**/*.js' ],
// Your Jasmine spec files
options : {
specs : 'test/**/*spec.js',
helpers: 'test/lib/*.js'
}
},
concat: {
dist : {
src: ['scripts/app.js', 'scripts/**/*.js'],
dest: 'production/js/concat.js'
}
},
ngmin: {
angular: {
src : ['production/js/concat.js'],
dest : 'production/js/ngmin.js'
}
},
uglify : {
options: {
report: 'min',
mangle: false
},
my_target : {
files : {
'production/app/app.min.js' : ['production/js/ngmin.js']
}
}
},
docular : {
groups: [],
showDocularDocs: false,
showAngularDocs: false
}
});
// Load plugins here
grunt.loadNpmTasks('grunt-ngmin');
grunt.loadNpmTasks('grunt-docular');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jasmine');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-connect');
// Define your tasks here
grunt.registerTask('test', ['jasmine']);
grunt.registerTask('build', ['concat', 'ngmin', 'uglify']);
grunt.registerTask('default', ['test', 'build', 'watch']);
};
J'avais un problème similaire. Et l'a résolu de la manière suivante. Nous devons exécuter un module Gulp appelé gulp-ng-annotate avant d'exécuter uglify. Nous installons donc ce module
npm install gulp-ng-annotate --save-dev
Alors faites le require dans Gulpfile.js
ngannotate = require(‘gulp-ng-annotate’)
Et dans votre tâche usemin faire quelque chose comme ça
js: [ngannotate(), uglify(),rev()]
Cela l'a résolu pour moi.
[EDIT: fautes de frappe fixes]
Uglify a une option pour désactiver le brassage sur des fichiers spécifiques:
options: {
mangle: {
except: ['jQuery', 'angular']
}
}
https://github.com/gruntjs/grunt-contrib-uglify#reserved-identifiers
Ceci est très difficile à déboguer car beaucoup de services sont nommés de la même manière (principalement e ou a). Cela ne résoudra pas l'erreur, mais vous fournira le nom du service non résol, ce qui vous permettra de localiser, dans la sortie altérée, l'emplacement dans le code et enfin de résoudre le problème. :
Allez dans lib/scope.js
de Uglify2 (node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/scope.js
) et remplacez la ligne
this.mangled_name = this.scope.next_mangled(options);
avec
this.mangled_name = this.name + "__debugging_" + counter++