web-dev-qa-db-ja.com

Angular.moduleの縮小バグ

なぜミニフィケーションが機能していないのかを理解しようとするのが一番の時間です。

配列オブジェクトを介して、Web上の多数の提案ごとに関数の前にプロバイダーを注入しましたが、それでも「不明なプロバイダー: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);
    }])

どんな提案も大いに義務付けられます!

81
BPWDevelopment

AndrewM96のng-minの提案は正しい。

UglifyとAngularでは、配置と空白が重要です。

5
BPWDevelopment

Grunt.js Uglify プラグインでこの問題に遭遇しました。

オプションの1つはmangle

_uglify: {
  options: {
    mangle: false
  },
_

私は「文字列のような」上で正規表現関数を実行し、それらを縮小すると信じています。

例えば:

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

になるでしょう:

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

無効にします---この機能は、AngularでNiceを再生しません。

編集:

@JoshDavidMillerが説明するように、より正確に言うと:

Uglify mangleは、変数のようにマングルのみを行います。これは、AngularJSの問題を実際に引き起こします。つまり、問題は定義ではなく注入にあります。

function MyCtrl($scope, myService)function MyCtrl(a, b)にマングルされますが、文字列内のサービス定義は変更されません。

  • uglifyを実行する前に_ng-min_を実行すると、この問題が解決します。
139
Dan Kanze

問題

AngularJS:The Bad Parts :から

Angularには、パラメーターの名前に基づいて適切なオブジェクトを関数に渡す依存関係インジェクターが組み込まれています。

_function MyController($scope, $window) {
    // ...
}
_

ここでは、パラメータ_$scope_および_$window_の名前が既知の名前のリストと照合され、対応するオブジェクトがインスタンス化されて関数に渡されます。 Angularは、関数でtoString()を呼び出し、関数定義を解析してパラメーター名を取得します。

もちろん、これの問題は、コードを縮小した瞬間に動作が停止することです。ユーザーエクスペリエンスを重視するため、コードを縮小することになり、このDIメカニズムを使用するとアプリが破損します。実際、一般的な開発方法論は、デバッグを容易にするために開発時に縮小されていないコードを使用し、本番またはステージングにプッシュするときにコードを縮小することです。その場合、この問題は、最も痛いところに来るまで、untilい頭を立てることはありません。

(...)

この依存性注入メカニズムは一般的なケースでは実際に機能しないため、Angularも機能するメカニズムを提供します。確かに2つ提供されます。次のように配列を渡すことができます。

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

または、コンストラクタで_$inject_プロパティを設定できます。

_MyController.$inject = ['$scope', '$window'];
_

解決

_ng-annotate_ を使用して、縮小に必要な注釈を自動的に追加できます。

_ng-annotate_は、AngularJS依存性注入アノテーションを追加および削除します。それは邪魔にならないので、ソースコードはそれ以外はまったく同じままです。コメントの紛失や行の移動はありません。

_ng-annotate_は ngmin (現在は非推奨)よりも高速で安定しており、多くのツールのプラグインがあります。


AngularJS 1.3以降では、 ngApp と呼ばれるngStrictDiの新しいパラメーターもあります。

この属性がapp要素に存在する場合、インジェクターは「strict-di」モードで作成されます。これは、 Dependency Injection guide で説明されているように、アプリケーションが明示的な関数注釈を使用しない(したがって縮小に適さない)関数の呼び出しに失敗し、有用なデバッグ情報が追跡を支援することを意味しますこれらのバグのルート。

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の順に実行しました

Uglifyオプションにmangle:falseを追加するまで、angularから$ 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']);

};

9
Sten Muchow

同様の問題がありました。そして、次の方法で解決しました。 uglifyを実行する前に、gulp-ng-annotateというGulpモジュールを実行する必要があります。そのモジュールをインストールします

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

次に、Gulpfile.jsでrequireを実行します

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

そしてuseminタスクでこのようなことをします

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

それで解決しました。

[編集:タイプミスを修正]

Uglifyには、特定のファイルのマングリングを無効にするオプションがあります。

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

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

2
Courtenay

多くのサービスが同じ名前(ほとんどeまたはa)であるため、これはデバッグが非常に困難です。これはエラーを解決しませんが、未解決のサービスの名前を提供しますこれにより、コード化された出力でコードの場所を追跡し、最終的に問題を解決することができます:

に入る lib/scope.jsof 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