Angular.module küçültme hatası


82

Küçültmenin neden işe yaramadığını anlamaya çalışırken en lanet zamana sahip olmak.

Sağlayıcılarımın web'deki sayısız öneriye göre işlevden önce bir dizi nesnesi yoluyla enjekte ettim ve yine de "Bilinmeyen sağlayıcı: aProvider <- a"

Düzenli:

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

Küçültülmüş:

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

Herhangi bir öneri çok zorunluluktur!


1
Kodunuzu küçültmek için ne kullanıyorsunuz? uglifyJS? Şunlara da göz atın : github.com/btford/ngmin ;)
AndreM96

Ngmin kullandım, tek yaptığı kodu farklı bir beyaz boşluk formatında sıralamaktı. Ara yazılım olarak express-uglify kullanmayı denedim ama çalışmıyordu, bu yüzden manuel olarak çevrimiçi bir çirkinleştirici kullanmayı denedim. Her iki durumda da kod aynı şekilde sonuçlandı.
BPWDevelopment

Ayrıca bir eksik yok ]mu? (kapanıştan önce ))
AndreM96

Vardı, onları bu pasajda unuttum. "Bilinmeyen sağlayıcı a" gerçeğini değiştirmez :(
BPWDevelopment

2
Tamam, peki, hangi çevrimiçi minifier'ı kullandın? Bu kodunuzla iyi çalışıyor: marijnhaverbeke.nl/uglifyjs
AndreM96

Yanıtlar:


139

Bu problemle daha önce Grunt.js Uglify eklentisiyle karşılaşmıştım.

Seçeneklerden biri mangle

uglify: {
  options: {
    mangle: false
  },

Ben de "gibi dizeler" üzerinde normal ifade işlevlerini çalıştırdığına ve onları küçülttüğüne inanıyorum.

Örneğin:

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

Olacaktı:

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

Devre dışı bırakın --- bu özellik Angular ile iyi oynamıyor.

Düzenle:

@JoshDavidMiller'ın açıkladığı gibi daha kesin olmak gerekirse:

Çirkinleştir, manglesadece değişkenler gibi karıştırılır, bu aslında AngularJS problemine neden olur. Yani sorun enjeksiyonda, tanım değil.

function MyCtrl($scope, myService)karıştırılır function MyCtrl(a, b), ancak bir dizenin içindeki hizmet tanımı asla değiştirilmemelidir.

  • Koşmadan ng-minönce çalıştırmak uglifybu sorunu çözer.

3
Kodunu güncelledi. Onun sorunu "$ locationProvider" ın "b" olması ya da onun gibi bir şey değildi. Sadece işe yaramadı. Ancak, bu cevap için +1 :)
AndreM96

1
Teşekkürler bu seçeneği bulmak için çok zorlanıyordu.
2013

Açısal önyükleme + yeoman kullanırken aynı şeyle karşılaştım. Yeoman açısal üretecini kullanarak, distbahsedilen bağımlılık hatası "Bilinmeyen Sağlayıcı" olan bir yapı üretti . Ayar mangle: falsesorunu çözdü. (not: sorun yalnızca geliştirici dostu gruntdistapp
yapıda

6
Does mangle: true gerçekten "dizeleri gibi" bozmak? Sadece değişkenler gibi karıştığından oldukça eminim , bu aslında AngularJS problemine neden oluyor. Yani sorun enjeksiyonda, tanım değil. function MyCtrl($scope, myService)karıştırılır function MyCtrl(a, b), ancak bir dizenin içindeki hizmet tanımı asla değiştirilmemelidir. Koşmadan ng-minönce koşmak uglifybu sorunu çözer, değil mi?
Josh David Miller

1
ng-minartık lehine kullanımdan kaldırıldıng-annotate
Atav32

51

Sorun

Gönderen angularjs: Kötü Parçaları :

Angular, parametrelerinin adlarına göre işlevinize uygun nesneleri iletecek yerleşik bir bağımlılık enjektörüne sahiptir:

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

Burada parametrelerin isimleri $scopeve$window bilinen isim listesi ile eşleşen ve karşılık gelen nesneler örneği ve işleve geçmiş olsun. Angular toString(), işlevi çağırarak ve ardından işlev tanımını çözümleyerek parametre adlarını alır .

Elbette bununla ilgili sorun şu ki , kodunuzu küçülttüğünüz anda çalışmayı bırakmasıdır . Kullanıcı deneyimini önemsediğiniz için kodunuzu küçülteceksiniz, bu nedenle bu DI mekanizmasını kullanmak uygulamanızı bozacaktır. Aslında, yaygın bir geliştirme metodolojisi, hata ayıklamayı kolaylaştırmak için geliştirmede küçültülmemiş kodu kullanmak ve ardından üretime veya aşamalandırmaya geçerken kodu küçültmektir. Bu durumda, bu sorun, en çok acı çektiği noktaya gelene kadar çirkin başını kaldırmayacaktır.

(...)

Bu bağımlılık enjeksiyon mekanizması aslında genel durumda çalışmadığından, Angular ayrıca çalışan bir mekanizma sağlar. Elbette iki tane sağlar. Bir dizi boyunca şöyle bir geçiş yapabilirsiniz:

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

Ya da $injectözelliği kurucunuzda ayarlayabilirsiniz :

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

Çözüm

ng-annotateKüçültme için gerekli ek açıklamaları otomatik eklemek için kullanabilirsiniz :

ng-annotateAngularJS bağımlılık enjeksiyon ek açıklamalarını ekler ve kaldırır. Müdahaleci değildir, bu nedenle kaynak kodunuz aksi takdirde tamamen aynı kalır. Kayıp yorum veya taşınan satır yok.

ng-annotatengmin(artık kullanımdan kaldırılmıştır) daha hızlı ve kararlıdır ve birçok araç için eklentileri vardır:


AngularJS 1.3'ten başlayarak ngAppadında yeni bir parametre de var ngStrictDi:

Bu özellik uygulama öğesinde mevcutsa, enjektör "katı-di" modunda oluşturulur. Bu, uygulamanın Bağımlılık Ekleme kılavuzunda açıklandığı gibi açık işlev açıklamasını kullanmayan (ve bu nedenle küçültme için uygun olmayan) işlevleri çağırmada başarısız olacağı ve yararlı hata ayıklama bilgilerinin bu hataların kökünün izlenmesine yardımcı olacağı anlamına gelir.


1
+1 Sadece grunt-ng-annotate'e geçmek bu sorunu çözdü ve ngmin artık kullanımdan kaldırıldı, bu yüzden geçiş yapmak için başka bir neden.
Pier-Luc Gendreau

günlerdir aradığım düzeltme buydu!
pedrommuller

Tarayıcı doğruluğu, açısal ve yutkunma küçültme ile küçültülmüş bir kod oluştururken aynı sorunla karşı karşıyayım. Yudum küçültmeyi kaldırdım ve gulp-ng-annotate ile değiştirdim, kod hala küçültülmüş ama yine de çalışmıyor.
Dimitri Kopriwa

@BigDong, browsererify kullanıyorsanız en iyi yol, muhtemelen bu küçültme hatalarını kolayca takip edebilmeniz için geliştirme ortamınızda bile etkinleştirmek ngStrictDi(buna benzer bir şey <div ng-app="myApp" ng-strict-di />) ve kullanmaktır gulp-ng-annotate.
Paolo Moretti

@PaoloMoretti ngStrictDi ve gulp-ng-annotate ile denedim, browsererify paketlenebilir ama kod küçültülmemiş, ng-annotate işi olması gerekmiyor mu?
Dimitri Kopriwa

22

Ben de aynı hatayı aldım. Ancak benim için sorun direktiflerin denetleyici bildirimi. Bunun yerine bunu yapmalısın.

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
Teşekkür ederim @angelokh! Tam olarak bu problemim vardı. controller: function ($scope) {}Notasyonu kullanıyordum .
jbasko

2
Bu, mangle: falsediğer yanıtlarda önerilenden daha çok asıl sorunun çözümü gibidir , çünkü hala isimleri karıştırabilmek istiyoruz.
jbasko

9

Grunt, ngmin ve uglify kullanırken benzer bir sorun yaşadım.

Süreci şu sırayla çalıştırdım: concat, ngmin, uglify

Uglify options mangle'ı ekleyene kadar $ injector hatasını açısaldan almaya devam ediyordum: false - sonra her şey düzeltildi.

Ayrıca şöyle çirkinleştirmek için istisnalar eklemeye çalıştım:

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

Ama boşuna...

Daha fazla açıklama için 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 TEŞEKKÜR EDERİM! bu bana çok zaman kazandırdı.
mylescc

5

AndrewM96'nın önerisi ng-mindoğru.

Hizalama ve beyaz boşluk, Angular'ın yanı sıra Uglify için de önemlidir.


10
ng-min sadece açısal dosyaları işliyor, böylece kolaylık sağlıyor uglify. Derleme sürecimizde ikisini de (daha ng-minönce uglify) kullanıyoruz ve çirkin js ile hala bir sorunumuz var.
craigb

4
Bu neden cevap olarak işaretlendi? (Ayrıca, AndrewM96 AndreM96 olmalıdır)
Jay

Dokümanlarda ng-min, problemi çözmeyeceğine dair umut vaat ediyor
special0ne

@craigb aynı sorunu yaşıyor. Belki bir şeylerin birleşimidir. Ben de RequireJS kullanıyorum. Temelde, tüm işlev değiştiren şeyleri ng-min kendim yapmalı ve hala ng-min çalıştırmalıyım, çalıştırmak derleme gerektiriyor ve daha sonra mangle true ile çirkinleşiyor. Bu süreç çoğu zaman işe yarıyor gibi görünüyor.
escapedcat

3

Benzer bir problemim vardı. Ve şu şekilde çözüldü. Çirkinleştirmeden önce gulp-ng-annotate adlı bir Gulp modülü çalıştırmalıyız. Bu yüzden bu modülü kuruyoruz

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

Ardından Gulpfile.js'deki gereksinimi yapın

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

Ve senin usemin görevinde böyle bir şey yap

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

Bu benim için çözdü.

[DÜZENLE: Düzeltilen yazım hataları]


gulp-MG-annotate gulp-NG-annotate olmalıdır?
hally9k

Evet, hata için özür dilerim. Nerede okur mg-annotatedaimang-annotate
Paulo Borralho Martins


2

Bu, hata ayıklaması çok zordur çünkü birçok hizmet aynı şekilde adlandırılır (çoğunlukla e veya a). Bu, hatayı çözmez, ancak çözümlenmemiş hizmetin adını size sağlar; bu, çirkin çıktıda koddaki konumu izlemenize ve sonunda sorunu çözmenize olanak tanır:

Gidin lib/scope.jsUglify2 (bir node_modules/grunt-contrib-uglify/node_modules/uglify-js/lib/scope.js) ve çizgiyi değiştirin

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

ile

this.mangled_name = this.name + "__debugging_" + counter++
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.