Bug minification di Angular.module

Avendo il tempo più dannato cercando di capire perché la minificazione non funziona.

Ho iniettato tramite un object array i miei provider prima della funzione per numerosi suggerimenti sul web e tuttavia ancora “Provider sconosciuto: aProvider <- a"

Regolare:

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); }]) 

Qualsiasi suggerimento sarebbe molto obbligato!

    Ho incontrato questo problema prima con il plugin Grunt.js Uglify .

    Una delle opzioni è mangle

     uglify: { options: { mangle: false }, 

    Quale credo funzioni le funzioni regex su “come le stringhe” e le minifiga.

    Per esempio:

     angular.module("imgur", ["imgur.global","imgur.album"]); 

    Potrebbe diventare:

     angular.module("a", ["a.global","a.album"]); 

    Disabilita — questa funzione non funziona correttamente con Angular.

    Modificare:

    Per essere più precisi come spiega @JoshDavidMiller:

    Uglify maneggia solo i mangles come variabili, che è ciò che effettivamente causa il problema di AngularJS. Cioè, il problema è nell’iniezione e non nella definizione.

    function MyCtrl($scope, myService) verrebbe function MyCtrl(a, b) , ma la definizione del servizio all’interno di una stringa non dovrebbe mai essere alterata.

    • Eseguire ng-min prima di eseguire uglify risolve questo problema.

    Problema

    Da AngularJS: The Bad Parts :

    Angular ha un injector di dipendenza incorporato che passerà gli oggetti appropriati alla tua funzione in base ai nomi dei suoi parametri:

     function MyController($scope, $window) { // ... } 

    Qui, i nomi dei parametri $scope e $window saranno confrontati con un elenco di nomi noti e gli oggetti corrispondenti verranno istanziati e passati alla funzione. Angular ottiene i nomi dei parametri chiamando toString() sulla funzione e quindi analizzando la definizione della funzione.

    Il problema con questo, ovviamente, è che smette di funzionare nel momento in cui si minimizza il codice . Poiché ti interessi dell’esperienza utente, il codice verrà ridotto al minimo, quindi l’utilizzo di questo meccanismo DI interromperà la tua app. In effetti, una metodologia di sviluppo comune consiste nell’utilizzare un codice non miniato in fase di sviluppo per facilitare il debugging e quindi per minimizzare il codice quando si spinge alla produzione o alla messa in scena. In questo caso, questo problema non farà arretrare la sua brutta testa finché non sarai nel punto in cui fa più male.

    (…)

    Poiché questo meccanismo di iniezione delle dipendenze in realtà non funziona nel caso generale, Angular fornisce anche un meccanismo che lo fa. A dire il vero, ne fornisce due. Puoi passare lungo un array in questo modo:

     module.controller('MyController', ['$scope', '$window', MyController]); 

    Oppure puoi impostare la proprietà $inject sul tuo costruttore:

     MyController.$inject = ['$scope', '$window']; 

    Soluzione

    Puoi usare ng-annotate per aggiungere automaticamente annotazioni richieste per il minifying:

    ng-annotate aggiunge e rimuove le annotazioni di iniezione delle dipendenze AngularJS. Non è intrusivo, quindi il tuo codice sorgente rimane esattamente lo stesso. Nessun commento perso o linee spostate.

    ng-annotate è più veloce e più stabile di ngmin (che ora è deprecato) e ha plugin per molti strumenti:

    • grunt-ng-annotate
    • gulp-ng-annotate
    • browserify-annotate

    A partire da AngularJS 1.3 c’è anche un nuovo parametro in ngApp chiamato ngStrictDi :

    se questo attributo è presente sull’elemento dell’app, l’iniettore verrà creato in modalità “strict-di”. Ciò significa che l’applicazione non invierà funzioni che non utilizzano l’annotazione della funzione esplicita (e quindi non sono adatte per la minificazione), come descritto nella guida alla dipendenza dalla dipendenza e utili informazioni di debug aiuteranno a rintracciare la radice di questi bug.

    Ho avuto lo stesso errore. Tuttavia, per me, il problema è la dichiarazione del controllore delle direttive. Dovresti farlo invece.

     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; }); 

    https://github.com/angular/angular.js/pull/3125

    Ho avuto un problema simile usando grunt, ngmin e uglify.

    Ho eseguito il processo in questo ordine: concat, ngmin, uglify

    Stavo continuando a ottenere l’errore $ injector da angular fino a quando ho aggiunto le opzioni uglify mangle: false – quindi tutto è stato risolto.

    Ho anche provato ad aggiungere le eccezioni a uglify in questo modo:

      options: { mangle: { except: ['jQuery', 'angular'] } } 

    Ma inutilmente …

    Ecco il mio gruntFile.js per ulteriori chiarimenti:

     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']); 

    };

    Il suggerimento AndrewM96 di ng-min è giusto.

    L’allineamento e lo spazio bianco sono importanti per Uglify e Angular.

    Ho avuto un problema simile. E risolto il seguente modo. Abbiamo bisogno di eseguire un modulo Gulp chiamato gulp-ng-annotate prima di eseguire uglify. Quindi installiamo quel modulo

     npm install gulp-ng-annotate --save-dev 

    Quindi fai la richiesta in Gulpfile.js

     ngannotate = require('gulp-ng-annotate') 

    E nel tuo compito usemin fare qualcosa di simile

     js: [ngannotate(), uglify(),rev()] 

    Questo l’ha risolto per me.

    [MODIFICA: errori di battitura fissi]

    Uglify ha un’opzione per disabilitare il mangling su file specifici:

     options: { mangle: { except: ['jQuery', 'angular'] } } 

    https://github.com/gruntjs/grunt-contrib-uglify#reserved-identifiers

    È molto difficile eseguire il debug perché molti servizi hanno lo stesso nome (principalmente e o a). Questo non risolverà l’errore, ma ti fornirà il nome del servizio non risolto che ti consentirà di rintracciare, nell’output migliorato, la posizione nel codice e, infine, di risolvere il problema:

    Andate in lib/scope.js di Uglify2 ( node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/scope.js ) e sostituite la riga

     this.mangled_name = this.scope.next_mangled(options); 

    con

     this.mangled_name = this.name + "__debugging_" + counter++