【问题标题】:Angular.module minification bugAngular.module 缩小错误
【发布时间】: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

标签: javascript angularjs minify 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(现已弃用)更快更稳定,并且它有许多工具的插件:


    从 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。这个过程似乎在大多数情况下都有效。
    猜你喜欢
    • 1970-01-01
    • 2015-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多