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.js
of 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-annotate
比ngmin
(现已弃用)更快更稳定,并且它有许多工具的插件:
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 缩小错误的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript中易犯的小错误-------常见错误七:原型继承问题
JavaScript中易犯的小错误-------常见错误四:比较运算符