Angular.module 축소 버그


82

최소화가 작동하지 않는 이유를 파악하기 위해 가장 시간을 투자하십시오.

나는 배열 객체를 통해 웹에서 수많은 제안에 따라 함수 이전에 내 공급자를 삽입했지만 여전히 "알 수없는 공급자 : aProvider <-a"

정규병:

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

어떤 제안이라도 많은 의무가 있습니다!


1
코드를 축소하기 위해 무엇을 사용합니까? uglifyJS? 또한 체크 아웃 : github.com/btford/ngmin를 )
AndreM96

ngmin을 사용했는데 다른 공백 형식으로 코드를 정렬하는 것뿐이었습니다. 미들웨어로 express-uglify를 사용해 보았지만 작동하지 않아 온라인 uglifier를 사용하여 수동으로 시도했습니다. 어느 쪽이든 코드는 동일하게 끝났습니다.
BPWDevelopment

또한 누락되지 않았 ]습니까? (폐쇄 전 ))
AndreM96

이 특정 스 니펫에서 잊어 버렸습니다. "알 수없는 공급자 a"가 여전히 발생한다는 사실은 변경되지 않습니다. (
BPWDevelopment

2
좋습니다. 어떤 온라인 미니 파이어를 사용 하셨나요? 이것은 당신의 코드와 잘 작동 : marijnhaverbeke.nl/uglifyjs
AndreM96

답변:


139

Grunt.js Uglify 플러그인 으로 전에이 문제가 발생했습니다 .

옵션 중 하나는 망글입니다.

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하면이 문제가 해결됩니다.

3
그는 자신의 코드를 업데이트했습니다. 그의 문제는 "$ locationProvider"가 "b"가되거나 그와 비슷한 것이 아니라는 것이 었습니다. 작동하지 않았습니다. 그러나,이 대답 : +1
AndreM96

1
그 옵션을 찾기가 어려웠습니다.
reen

앵귤러 부트 스트랩 + 여만을 사용할 때 똑같은 일이 발생했습니다. yeoman 각도 생성기를 사용하여 dist언급 된 종속성 오류 "Unknown Provider"가 있는 빌드를 생성 했습니다 . 설정으로 mangle: false문제가 해결되었습니다. (참고 :이 문제는 단지 문제이었다 grunt내장 dist되지 개발자 친화적 인 app빌드)
craigb

6
mangle: true 정말로 "문자열처럼" 엉망이 됩니까 ? 나는 그것이 실제로 AngularJS 문제를 일으키는 변수 처럼 엉망이 될 것이라고 확신합니다 . 즉, 문제는 정의가 아니라 주입에 있습니다. function MyCtrl($scope, myService)으로 엉망이 function MyCtrl(a, b)되지만 문자열 내부의 서비스 정의는 절대 변경되지 않아야합니다. 실행 ng-min하기 전에 실행 uglify하면이 문제가 해결됩니다.
Josh David Miller


51

문제

에서 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-annotateAngularJS 종속성 주입 주석을 추가하고 제거합니다. 방해가되지 않으므로 소스 코드는 그렇지 않으면 정확히 동일하게 유지됩니다. 잃어버린 주석이나 이동 된 줄이 없습니다.

ng-annotatengmin(현재 사용되지 않음) 보다 빠르고 안정적이며 많은 도구에 대한 플러그인이 있습니다.


AngularJS와 1.3에서 시작하면 새로운 PARAM있다 ngApp라고 ngStrictDi:

이 속성이 app 요소에있는 경우 인젝터는 "strict-di"모드로 생성됩니다. 즉, 종속성 주입 가이드에 설명 된대로 애플리케이션이 명시 적 함수 주석을 사용하지 않는 (따라서 축소에 적합하지 않은) 함수를 호출하지 못하며 유용한 디버깅 정보가 이러한 버그의 원인을 추적하는 데 도움이 될 것입니다.


1
+1 단순히 grunt-ng-annotate로 전환하면이 문제가 해결되었으며 ngmin은 이제 더 이상 사용되지 않으므로 전환해야하는 또 다른 이유입니다.
Pier-Luc Gendreau

그것은 내가 며칠 동안 찾고 있던 수정이었습니다!
jack.the.ripper

browserify, angular 및 gulp-minify를 사용하여 축소 된 코드를 작성하는 동일한 문제에 직면하고 있습니다. 나는 gulp minify를 제거하고 그것을 gulp-ng-annotate로 대체했습니다. 코드는 여전히 최소화되었지만 여전히 작동하지 않습니다.
Dimitri Kopriwa 15.01.13

당신이 최선의 방법을 browserify 사용하는 경우 @BigDong 수 있도록 아마 ngStrictDi(같은 <div ng-app="myApp" ng-strict-di />) 사용 gulp-ng-annotate하면 쉽게 이러한 축약 버그를 추적 있도록 개발 환경에서 심지어에서합니다.
Paolo Moretti 2015 년

@PaoloMoretti ngStrictDi 및 gulp-ng-annotate로 시도했지만 browserify는 번들로 사용할 수 있지만 코드는 축소되지 않습니다 .ng-annotate 작업이어야하지 않습니까?
Dimitri Kopriwa 15.01.14

22

같은 오류가 발생했습니다. 그러나 나에게 문제는 지시문의 컨트롤러 선언입니다. 대신이 작업을 수행해야합니다.

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


1
@angelokh 감사합니다! 나는 정확히이 문제가 있었다. 나는 controller: function ($scope) {}표기법 을 사용하고있었습니다 .
jbasko 2014

2
이것은 mangle: false다른 응답에서 제안한 것보다 실제 문제에 대한 해결책과 더 비슷합니다. 우리는 여전히 이름을 엉망으로 만들 수 있기를 원하기 때문입니다.
jbasko 2014

9

grunt, ngmin 및 uglify를 사용하여 비슷한 문제가 발생했습니다.

concat, ngmin, uglify 순서로 프로세스를 실행했습니다.

나는 uglify options mangle : false를 추가 할 때까지 각도에서 $ injector 오류를 계속 받고있었습니다. 그러면 모든 것이 수정되었습니다.

나는 또한 다음과 같이 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']);

};


AH 감사합니다! 시간이 많이 절약되었습니다.
mylescc

5

AndrewM96의 제안 ng-min이 맞습니다.

정렬과 공백은 Angular뿐만 아니라 Uglify에도 중요합니다.


10
ng-min 은 각도 파일을 처리하는 것처럼 보이므로 uglify. 우리의 빌드 프로세스에서 우리는 ( ng-min이전 uglify) 둘 다 사용 했지만 여전히 추악한 js에 문제가있었습니다.
craigb 2013 년

4
이것이 답변으로 표시되는 이유는 무엇입니까? (또한 AndrewM96은 AndreM96이어야 함)
Jay

문서에 문제가 해결되지 않는 그것을 약속 사운드 분 겨 불구하고
special0ne

@craigb 같은 문제가 있습니다. 아마도 그것은 사물의 조합 일 것입니다. RequireJS도 사용합니다. 나는 기본적으로 모든 기능 변경 사항을 수행합니다. 이 프로세스는 대부분의 경우 작동하는 것 같습니다.
escapedcat 2014

3

비슷한 문제가있었습니다. 그리고 다음과 같은 방법으로 해결했습니다. uglify를 실행하기 전에 gulp-ng-annotate라는 Gulp 모듈을 실행해야합니다. 그래서 우리는 그 모듈을 설치합니다

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

그런 다음 Gulpfile.js에서 요구 사항을 수행하십시오.

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

그리고 usemin 작업에서 다음과 같이하십시오.

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

그것은 나를 위해 그것을 해결했습니다.

[편집 : 오타 수정]


gulp-MG-annotate는 gulp-NG-annotate 여야합니까?
hally9k

네, 죄송합니다. 어디 읽는 것은 mg-annotate항상ng-annotate
파울로 Borralho 마틴


2

많은 서비스의 이름이 동일하므로 (대부분 e 또는 a) 디버깅하기가 매우 어렵습니다. 이렇게하면 오류가 해결되지는 않지만 미해결 된 출력에서 코드의 위치를 ​​추적하고 마지막으로 문제를 해결할 수 있는 해결되지 않은 서비스의 이름을 제공합니다 .

lib/scope.jsUglify2 ( 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++
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.