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

任何建议都会非常感激!

4

8 回答 8

139

我之前在使用 Grunt.js Uglify插件时遇到过这个问题。

选项之一是mangle

uglify: {
  options: {
    mangle: false
  },

我相信它在“类似字符串”上运行正则表达式函数并缩小它们。

例如:

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

会成为:

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

禁用它 --- 这个特性在 Angular 上不好用。

编辑:

更准确地说,正如@JoshDavidMiller 解释的那样:

Uglifymangle只会像变量一样破坏,这实际上是导致 AngularJS 问题的原因。也就是说,问题在于注入而不是定义。

function MyCtrl($scope, myService)会被修改为function MyCtrl(a, b),但字符串中的服务定义永远不应该被改变。

  • 先跑ng-min再跑uglify解决了这个问题。
于 2013-06-21T15:48:25.160 回答
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-annotate添加和删​​除 AngularJS 依赖注入注解。它是非侵入性的,因此您的源代码在其他方面保持完全相同。没有丢失的评论或移动的行。

ng-annotatengmin(现已弃用)更快更稳定,并且它具有许多工具的插件:


从 AngularJS 1.3 开始,还有一个新的参数ngApp被调用ngStrictDi

如果 app 元素上存在此属性,则注入器将以“strict-di”模式创建。这意味着应用程序将无法调用不使用显式函数注释的函数(因此不适合缩小),如依赖注入指南中所述,有用的调试信息将有助于追踪这些错误的根源。

于 2014-07-09T17:07:18.870 回答
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

于 2014-02-02T07:03:11.443 回答
9

我在使用 grunt、ngmin 和 uglify 时遇到了类似的问题。

我按以下顺序运行该过程:concat、ngmin、uglify

我继续从 angular 获取 $injector 错误,直到我添加了 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']);

};

于 2014-01-06T08:31:11.003 回答
5

AndrewM96 的建议ng-min是对的。

对齐和空白对 Uglify 和 Angular 都很重要。

于 2013-06-21T16:11:29.937 回答
3

我有一个类似的问题。并通过以下方式解决。在运行 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()] 

这为我解决了它。

[编辑:修正错别字]

于 2015-12-27T21:59:36.263 回答
2

Uglify 有一个选项可以禁用对特定文件的修改:

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

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

于 2013-12-09T16:11:17.733 回答
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++
于 2015-03-06T10:20:37.310 回答