it-swarm.com.de

Angular.module-Minimierungsfehler

Ich habe die verdammteste Zeit, um herauszufinden, warum die Minimierung nicht funktioniert.

Ich habe über ein Array-Objekt meinen Providern zuvor die Funktion nach zahlreichen Vorschlägen über das Web injiziert und trotzdem "Unbekannter Provider: aProvider <- a"

Regulär:

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

Minimiert:

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

Jeder Vorschlag wäre sehr dankbar!

81
BPWDevelopment

AndrewM96 Vorschlag von ng-min ist richtig.

Die Ausrichtung und der Leerraum sind sowohl für Uglify als auch für Angular von Bedeutung.

5
BPWDevelopment

Ich bin mit Grunt.js Uglify Plugin auf dieses Problem gestoßen.

Eine der Optionen ist mangle

uglify: {
  options: {
    mangle: false
  },

Was ich glaube, läuft Regex-Funktionen auf "Like-Strings" und minimiert sie.

Beispielsweise:

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

Würde werden:

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

Deaktiviere es --- diese Funktion spielt nicht Nice mit Angular.

Bearbeiten:

Genauer gesagt, wie @JoshDavidMiller erklärt:

Uglify mangle zerfleischt nur wie Variablen, was tatsächlich das AngularJS-Problem verursacht. Das heißt, das Problem liegt in der Injektion und nicht in der Definition.

function MyCtrl($scope, myService) würde zu function MyCtrl(a, b) entstellt, aber die Service-Definition innerhalb eines Strings sollte niemals geändert werden.

  • Das Ausführen von ng-min Vor dem Ausführen von uglify löst dieses Problem.
139
Dan Kanze

Problem

Von AngularJS: The Bad Parts :

Angular verfügt über einen eingebauten Abhängigkeitsinjektor, der anhand der Namen seiner Parameter entsprechende Objekte an Ihre Funktion übergibt:

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

Hier werden die Namen der Parameter $scope Und $window Mit einer Liste bekannter Namen verglichen und entsprechende Objekte instanziiert und an die Funktion übergeben. Angular ruft die Parameternamen ab, indem toString() für die Funktion aufgerufen und anschließend die Funktionsdefinition analysiert wird.

Das Problem dabei ist natürlich, dass es nicht mehr funktioniert, sobald Sie Ihren Code minimieren . Da Ihnen die Benutzerfreundlichkeit am Herzen liegt, wird Ihr Code minimiert, sodass die Verwendung dieses DI-Mechanismus Ihre App beschädigt. Tatsächlich besteht eine übliche Entwicklungsmethode darin, bei der Entwicklung nicht minimierten Code zu verwenden, um das Debuggen zu vereinfachen, und den Code dann zu minimieren, wenn die Produktion oder das Staging gestartet werden. In diesem Fall wird dieses Problem seinen hässlichen Kopf erst dann aufrichten, wenn Sie an dem Punkt angelangt sind, an dem es am meisten weh tut.

(...)

Da dieser Abhängigkeitsinjektionsmechanismus im allgemeinen Fall nicht funktioniert, bietet Angular ebenfalls einen Mechanismus, der dies tut. Um sicher zu sein, bietet er zwei. Sie können entweder ein Array wie folgt übergeben:

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

Oder Sie können die Eigenschaft $inject In Ihrem Konstruktor festlegen:

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

Lösung

Sie können ng-annotate verwenden, um automatisch Anmerkungen hinzuzufügen, die zum Minimieren erforderlich sind:

ng-annotate Fügt AngularJS-Abhängigkeitsinjektionsanmerkungen hinzu und entfernt sie. Es ist nicht aufdringlich, so dass Ihr Quellcode ansonsten genau gleich bleibt. Keine verlorenen Kommentare oder verschobenen Zeilen.

ng-annotate Ist schneller und stabiler als ngmin (das jetzt veraltet ist) und es hat Plugins für viele Tools:


Ab AngularJS 1.3 gibt es auch einen neuen Parameter in ngApp mit dem Namen ngStrictDi:

wenn dieses Attribut im App-Element vorhanden ist, wird der Injektor im Modus "strict-di" erstellt. Dies bedeutet, dass die Anwendung keine Funktionen aufruft, die keine explizite Funktionsanmerkung verwenden (und daher für die Minimierung ungeeignet sind), wie im Abhängigkeitsinjektionshandbuch beschrieben, und nützliche Debugging-Informationen beim Aufspüren helfen die Wurzel dieser Fehler.

50
Paolo Moretti

Ich habe den gleichen Fehler bekommen. Für mich ist das Problem jedoch die Controller-Deklaration der Direktiven. Sie sollten dies stattdessen tun.

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

22
angelokh

Ich hatte ein ähnliches Problem mit Grunzen, Ngmin und Hässlichkeit.

Ich habe den Prozess in dieser Reihenfolge ausgeführt: concat, ngmin, uglify

Ich habe weiterhin den $ injector-Fehler von angular) abgerufen, bis ich in der Mangle uglify options fügte: false - dann war alles behoben.

Ich habe auch versucht, die Ausnahmen so zu hässlich zu machen:

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

Aber ohne Erfolg ...

Hier ist meine gruntFile.js zur weiteren Verdeutlichung:

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

};

9
Sten Muchow

Ich hatte ein ähnliches Problem. Und löste es auf folgende Weise. Wir müssen ein Gulp-Modul namens gulp-ng-annotate ausführen, bevor wir uglify ausführen. Also installieren wir dieses Modul

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

Dann machen Sie das in Gulpfile.js

ngannotate = require(‘gulp-ng-annotate’)

Und mach in deiner Usemin-Aufgabe so etwas

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

Das hat es für mich gelöst.

[BEARBEITEN: Fehler behoben]

Uglify hat eine Option, um das Mangeln für bestimmte Dateien zu deaktivieren:

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

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

2
Courtenay

Dies ist sehr schwierig zu debuggen, da viele Dienste den gleichen Namen haben (meistens e oder a). Dadurch wird der Fehler nicht behoben, sondern es wird Sie erhalten den Namen des ungelösten Dienstes angezeigt, mit dem Sie in der ungelösten Ausgabe die Position im Code ermitteln und schließlich das Problem beheben können :

Gehe in lib/scope.jsof Uglify2 (node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/scope.js) und ersetzen Sie die Zeile

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

mit

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