Angular.module 缩小错误

Posted

技术标签:

【中文标题】Angular.module 缩小错误【英文标题】:Angular.module minification bug 【发布时间】:2013-06-18 19:01:19 【问题描述】:

花最宝贵的时间试图弄清楚为什么缩小不起作用。

根据网络上的众多建议,我已经通过数组对象在函数之前注入了我的提供者,但仍然是“未知提供者:aProvider

常规:

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

如有任何建议,我们将不胜感激!

【问题讨论】:

你用什么来缩小你的代码?丑化JS?另请查看:github.com/btford/ngmin ;) 我使用了 ngmin,它所做的只是将代码排列成不同的空白格式。我尝试使用 express-uglify 作为中间件,但它不起作用,所以我尝试手动使用在线 uglifier。无论哪种方式,代码都以相同的方式结束。 另外,不是缺少] 吗? (收盘前) 有,我在这个特殊的 sn-p 中忘记了它们。它不会改变“未知提供者a”仍然发生的事实:( 好的,你用的是什么在线压缩工具?这适用于您的代码:marijnhaverbeke.nl/uglifyjs 【参考方案1】:

我遇到了类似的问题。并通过以下方式解决。在运行 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-annotate 应该是 gulp-NG-annotate? 是的,很抱歉这个错误。读取mg-annotate 的位置始终为ng-annotate【参考方案2】:

这很难调试,因为很多服务的名称都相同(主要是 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++

【讨论】:

【参考方案3】:

问题

来自AngularJS: The Bad Parts:

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 依赖注入 注释。它是非侵入性的,因此您的源代码完全保持原样 否则相同。没有丢失的 cmets 或移动的行。

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

grunt-ng-annotate gulp-ng-annotate browserify-annotate

从 AngularJS 1.3 开始,ngApp 中还有一个名为 ngStrictDi 的新参数:

如果该属性存在于 app 元素上,则注入器将是 在“strict-di”模式下创建。这意味着应用程序将失败 调用不使用显式函数注释的函数(和 因此不适合缩小),如Dependency Injection guide 中所述,有用的调试信息将有助于跟踪 找出这些错误的根源。

【讨论】:

+1 只需切换到 grunt-ng-annotate 即可解决此问题,并且 ngmin 现在已被弃用,因此这是切换的另一个原因。 这是我寻找几天的解决方案! 我在使用 browserify、angular 和 gulp-minify 构建缩小代码时遇到了同样的问题。我已经删除了 gulp minify 并用 gulp-ng-annotate 替换它,代码仍然被缩小但仍然不起作用。 @BigDong 如果您使用的是 browserify,最好的方法可能是启用ngStrictDi(类似于<div ng-app="myApp" ng-strict-di />)并在您的开发环境中使用gulp-ng-annotate,以便您轻松跟踪消除这些缩小错误。 @PaoloMoretti 我确实尝试过使用 ngStrictDi 和 gulp-ng-annotate,browserify 可以捆绑但代码没有被缩小,它不应该是 ng-annotate 工作吗?【参考方案4】:

我遇到了同样的错误。但是,对我来说,问题在于指令的控制器声明。你应该这样做。

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

【讨论】:

谢谢@angelokh!我正是这个问题。我使用的是controller: function ($scope) 表示法。 这更像是实际问题的解决方案,而不是其他回复中建议的mangle: false,因为我们仍然希望能够破坏名称。【参考方案5】:

我在使用 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']);

;

【讨论】:

谢谢谢谢谢谢!这为我节省了很多时间。【参考方案6】:

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

其中一个选项是 mangle

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),但字符串中的服务定义永远不应该改变。

在运行uglify 之前运行ng-min 可以解决这个问题。

【讨论】:

他更新了他的代码。他的问题不在于“$locationProvider”变成了“b”或类似的东西。它只是没有用。但是,对此答案 +1 :) 谢谢 很难找到那个选项。 我在使用 angular bootstrap + yeoman 时遇到了同样的问题。使用yeoman angular generator 它生成了一个dist 构建,该构建将具有提到的依赖错误“未知提供者”。设置mangle: false 解决了这个问题。 (注意:这个问题只是 grunt 构建的问题 dist 不是开发人员友好的 app 构建) mangle: true 真的 会破坏“像字符串”吗?我很确定它只会像 variables 那样破坏,这实际上是导致 AngularJS 问题的原因。也就是说,问题在于注入而不是定义。 function MyCtrl($scope, myService) 会被修改为 function MyCtrl(a, b),但字符串中的服务定义永远不应该被改变。在运行uglify 之前运行ng-min 可以解决这个问题,不是吗? ng-min 现在已弃用,取而代之的是 ng-annotate【参考方案7】:

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

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

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

【讨论】:

添加 'angualr' 并没有解决问题。这不是预设。【参考方案8】:

ng-min的AndrewM96建议是对的。

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

【讨论】:

ng-min 似乎只处理角度文件,因此它们对uglify 很友好。在我们的构建过程中,我们同时使用了两者(uglify 之前的ng-min)并且仍然存在丑化 js 的问题。 为什么这被标记为答案? (另外,AndrewM96 应该是 AndreM96) 虽然在文档中 ng-min 听起来很有希望,但它并不能解决问题 @craigb 有同样的问题。也许它是事物的组合。我也使用 RequireJS。我基本上做了 ng-min 应该做的所有功能改变的东西,并且仍然运行 ng-min,而不是运行 require build 和运行 uglify 与 mangle true。这个过程似乎在大多数情况下都有效。

以上是关于Angular.module 缩小错误的主要内容,如果未能解决你的问题,请参考以下文章

php 编译小错误

JavaScript中易犯的小错误-------常见错误七:原型继承问题

CSS网页布局中易犯的10个小错误

JavaScript中易犯的小错误-------常见错误四:比较运算符

JavaScript中易犯的小错误-------常见错误五:低效的DOM操作

易犯的PHP小错误及相应分析