it-swarm.com.ru

Ошибка минимизации Angular.module

Иметь самое трудное время, пытаясь понять, почему минификация не работает.

Я ввел через объект массива мои провайдеры перед функцией в соответствии с многочисленными предложениями в Интернете, но все еще "Неизвестный провайдер: aProvider <- a"

Regular:

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

Уменьшенная:

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

Любое предложение будет очень благодарен!

81
BPWDevelopment

AndrewM96 предложение ng-min верно.

Выравнивание и пробел имеют значение как для Uglify, так и для Angular.

5
BPWDevelopment

Я столкнулся с этой проблемой раньше с плагином Grunt.js Uglify .

Один из вариантов mangle

uglify: {
  options: {
    mangle: false
  },

Который я полагаю, выполняет функции регулярных выражений на "как строки" и минимизирует их.

Например:

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

Станет:

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

Отключите его - эта функция не работает с Angular.

Правка:

Чтобы быть более точным, как объясняет @JoshDavidMiller:

Uglify mangle искажает только переменные, что и является причиной проблемы AngularJS. То есть проблема в инъекции, а не в определении.

function MyCtrl($scope, myService) будет преобразован в function MyCtrl(a, b), но определение службы внутри строки никогда не должно изменяться.

  • Запуск ng-min перед запуском uglify решает эту проблему.
139
Dan Kanze

Проблема

От AngularJS: Плохие партии :

Angular имеет встроенный инжектор зависимостей, который будет передавать соответствующие объекты вашей функции на основе имен ее параметров:

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

Здесь имена параметров $scope и $window будут сопоставлены со списком известных имен, а соответствующие объекты будут созданы и переданы функции. Angular получает имена параметров, вызывая функцию toString(), а затем анализируя определение функции.

Конечно, проблема в том, что он перестает работать в тот момент, когда вы минимизируете свой код . Так как вы заботитесь о пользовательском опыте, вы будете минимизировать свой код, поэтому использование этого механизма DI разрушит ваше приложение. Фактически, общая методология разработки заключается в использовании незавершенного кода в процессе разработки для упрощения отладки, а затем для минимизации кода при переходе к производству или подготовке. В этом случае эта проблема не поднимет уродливую голову, пока вы не окажетесь в той точке, где она причиняет боль больше всего.

(...)

Поскольку этот механизм внедрения зависимостей фактически не работает в общем случае, Angular также предоставляет механизм, который работает. Конечно, это обеспечивает два. Вы можете передать массив следующим образом:

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

Или вы можете установить свойство $inject в вашем конструкторе:

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

Решение

Вы можете использовать ng-annotate для автоматического добавления аннотаций, необходимых для минимизации:

ng-annotate добавляет и удаляет аннотации внедрения зависимостей AngularJS. Это не навязчиво, поэтому ваш исходный код остается точно таким же, в противном случае. Нет потерянных комментариев или перемещенных строк.

ng-annotate быстрее и стабильнее, чем ngmin (что устарело) и имеет плагины для многих инструментов:


Начиная с AngularJS 1.3, есть также новый параметр в ngApp называемый ngStrictDi:

если этот атрибут присутствует в элементе приложения, инжектор будет создан в режиме строгого режима. Это означает, что приложение не сможет вызывать функции, которые не используют явную аннотацию функции (и, следовательно, не подходят для минимизации), как описано в Руководство по внедрению зависимости , а полезная информация об отладке поможет в отслеживании корень этих ошибок.

50
Paolo Moretti

Я получил ту же ошибку. Однако для меня проблема заключается в декларации контроллера директив. Вы должны сделать это вместо этого.

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

У меня была похожая проблема с использованием grunt, ngmin и uglify.

Я запустил процесс в следующем порядке: concat, ngmin, uglify

Я продолжал получать ошибку $ инжектора от angular до тех пор, пока не добавил в параметры uglify mangle: false - тогда все было исправлено.

Я также попытался добавить исключения для uglify, как это:

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

Но безрезультатно ...

Вот мой gruntFile.js для дальнейшего разъяснения:

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

У меня была похожая проблема. И решил это следующим образом. Нам нужно запустить модуль Gulp под названием gulp-ng-annotate, прежде чем мы запустим uglify. Итак, мы устанавливаем этот модуль

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

Затем выполните запрос в Gulpfile.js

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

И в вашем задании usemin сделайте что-то вроде этого

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

Это решило это для меня.

[Правка: Исправлены опечатки]

3
Paulo Borralho Martins

Uglify имеет возможность отключить искажение в определенных файлах:

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

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

2
Courtenay

Это очень трудно отладить, потому что многие сервисы имеют одинаковые имена (в основном, e или a). Это не устранит ошибку, но предоставит вам имя неразрешенной службы, которая позволяет отслеживать в расширенном выводе местоположение в коде и, наконец, позволяет решить проблему. :

Перейдите в lib/scope.js of Uglify2 (node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/scope.js) и замените строку

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

с

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