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 2013年

另外,难道不缺少]吗?(交易结束前)
AndreM96

在那个特定的片段中,我忘记了它们。它不会改变“未知提供者a”仍然发生的事实:(
BPWDevelopment 2013年

2
好的,那么,您使用了什么在线矿工?这可以很好地与您的代码一起工作:marijnhaverbeke.nl/uglifyjs
AndreM96 2013年

Answers:


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所述:

mangle只对像变量之类的手势进行丑化,这实际上是导致AngularJS问题的原因。也就是说,问题出在注入而不是定义上。

function MyCtrl($scope, myService)会被整形为function MyCtrl(a, b),但是字符串内的服务定义绝不能更改。

  • 先运行ng-min再运行即可uglify解决此问题。

3
他更新了他的代码。他的问题不是“ $ locationProvider”变成了“ b”或类似的东西。只是没有用。但是,此答案+1 :)
AndreM96

1
谢谢您一直很难找到该选项。
2013年

在使用角度引导程序+ yeoman时,我遇到了完全相同的问题。使用yeoman角度生成器,它生成的dist构建将具有提到的相关性错误“未知提供程序”。设置mangle: false解决了问题。(注意:问题只是grunt构建的问题而dist不是开发人员友好的app构建)
craigb

6
难道mangle: true 真的裂伤“之类的字符串”?我很确定它只会像变量那样混乱,这实际上是导致AngularJS问题的原因。也就是说,问题出在注入而不是定义上。function MyCtrl($scope, myService)会被替换为function MyCtrl(a, b),但是字符串内的服务定义永远都不应更改。先运行ng-min再运行即可uglify解决此问题,不是吗?
Josh David Miller

1
ng-min现在不推荐使用ng-annotate
Atav32

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”模式创建注射器。这意味着应用程序将无法调用不使用显式函数注释(因此不适合缩小)的函数,如Dependency Injection指南中所述,有用的调试信息将有助于跟踪这些错误的根源。


1
+1只需切换到grunt-ng-annotate即可解决此问题,并且无论如何现在都已弃用ngmin,这是切换的另一个原因。
2014年

那就是我一直在寻找的解决方法!
jack.the.ripper 2014年

我在用browserify,angular和gulp-minify构建缩小代码时也遇到了同样的问题。我已经删除了gulp minify并用gulp-ng-annotate代替了它,代码仍然缩小了,但仍然无法正常工作。
Dimitri Kopriwa 2015年

@BigDong(如果您使用的是Browserify),最好的方法可能是在您的开发环境中启用ngStrictDi(类似<div ng-app="myApp" ng-strict-di />)并使用它gulp-ng-annotate,以便您轻松跟踪这些缩小错误。
Paolo Moretti 2015年

@PaoloMoretti我曾尝试使用ngStrictDi和gulp-ng-annotate,browserify可以捆绑,但是代码没有被压缩,这不是ng-annotate的工作吗?
Dimitri Kopriwa 2015年

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

我一直在不断地从角度获取$ injector错误,直到在uglify选项中添加了错误: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']);

};


啊,谢谢你!节省了我很多时间。
mylescc 2014年

5

AndrewM96的建议ng-min是正确的。

对齐和空格对于Uglify和Angular都很重要。


10
ng-min似乎只是处理角度文件,因此它们对友好uglify。在我们的构建过程中,我们同时使用了(ng-minbefore uglify),而uglified js仍然存在问题。
craigb

4
为什么将此标记为答案?(另外,AndrewM96应该是AndreM96)
周杰伦

尽管在文档中ng-min听起来很有前途,但这并不能解决问题
special0ne 2014年

@ Craigb有同样的问题。也许是综合考虑。我也使用RequireJS。我基本上做了所有的功能更改材料ng-min应该自己做,并且仍然运行ng-min,比运行require build和运行uglify时要正确得多。该过程似乎在大多数时间都有效。
逸出的猫

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()] 

那为我解决了。

[编辑:固定错别字]


gulp-MG-注释应该是gulp-NG-注释吗?
hally9k 2016年

是的,对此错误感到抱歉。读书mg-annotate总是在哪里ng-annotate
Paulo Borralho Martins'Mar


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++
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.