如何在角度缩小构建后修复注入器错误?

时间:2014-10-15 12:08:44

标签: javascript angularjs minify

在发言之前,我读到它提出了建议,但仍然导致错误。看看简短的代码:

function IndexController($scope, $route, $routeParams, $location){
  $scope.sfv = project.version.name;
}
angular.module("TkwebMobile", ['ngRoute', 'ngCookies'])
  .controller('IndexController', ['$scope', '$route', '$routeParams', '$location', IndexController]);

只有这个并且错误仍然存​​在。我正在使用grunt来“uglify”,而且我也使用“concat”将代码统一在“lib”中。甚至我使用Angular文档中推荐的“注入”。

Uncaught Error: [$injector:modulerr] Failed to instantiate module TkwebMobile due to:
Error: [$injector:unpr] Unknown provider: a

是否是grunt concat的问题? (咕噜-的contrib-的concat)

3 个答案:

答案 0 :(得分:10)

这是由于你的缩小,特别是缩小和 mangle 变量名称的选项。

Angular根据参数名称确定要注入函数的值。例如......

angular.factory('MyFactory', function($location) {...});

...将导致angular查找名为'$location'的任何依赖项,然后使用$location值作为参数调用函数。

当你缩小你的javascript时,如果启用了一个名为 mangle 的选项,则变量名称会被破坏。之前的功能将变成这个......

angular.factory('MyFactory', function(a) {...});

Angular在源代码中不再具有正确的参数名称,因为$location现在是a。这节省了javascript的大小,但完全破坏了Angular的隐式依赖解析。您可以通过以下两种方式之一解决此问题。

第一个是角度为你提供的功能。

angular.factory('MyFactory', ['$location', function(a) {...}]);

您提供数组中参数的名称,数组的最后一个元素是将参数注入的函数。这样,你在代码中调用你的参数并不重要,并且minifier永远不会改变字符串文字,所以Angular总是知道你想要什么。

另一种方法是,如果您不想失去不必使用数组表示法的便利,请关闭缩小器上的 mangle 设置。这显然意味着你不会缩小到相同的程度,但要问自己是否真的值得这些额外的字节。

中途使用类似ngMin的东西,允许将数组符号注释到代码中,然后继续缩小。这是两个世界上最好的imo,但增加了部署客户端js的复杂性。

修改

关闭grunt中的mangle行为的正确设置是......

uglify: {
  options: {
    report: 'min',
    mangle: false
  }
}

但是ngAnnotate包可以避免这种情况。有关详细信息,请参阅here。 (ngAnnotate是接管ngMin的包)

答案 1 :(得分:1)

我遇到了类似的问题。事实证明,我没有正确识别和格式化控制器和服务等的依赖关系。我相信我通过查看缩小输出来发现这一点。 (这很粗糙,让我告诉你。)

基本上我必须查看我的所有文件并验证依赖项列表与我在控制器和服务中使用的相匹配。这很奇怪,因为它没有变化。

以下是我必须做的一个例子:

<强>原始

angular.module('FootCtrl', []).controller('FooterController', function($scope) {
    $scope.footer = 'Copyright \u00A9 ' + new Date().getFullYear() + name;
});

<强>固定

angular.module('FootCtrl', []).controller('FooterController', ["$scope", function($scope) {
    $scope.footer = 'Copyright \u00A9 ' + new Date().getFullYear() + name;
}]);

也许请注意我使用单引号和双引号的位置。

希望这会有所帮助。我不确定你的代码是否比显示的更多 - 如果没有,我不太确定。

答案 2 :(得分:0)

我遇到了这个问题,我花了很多时间来弄清楚问题是什么,因为我尝试禁用变量名称的修改,使用$ inject数组而不是仅依靠函数定义将服务和提供程序名称传递给函数定义角度隐式依赖注入但仍然存在问题。事实证明,在我的一个使用IIFE的控制器中,最后丢失了分号。请看下面的代码。

在:

  

(函数(){

     

})()

上面的代码在缩小之前可以正常工作,因为自动分号插入但是在缩小后它会因为没有分号而搞乱。经过修正后,它看起来如下所示。

正确:

  

(函数(){

     

})();

这解决了我的问题。我希望这对某些人有所帮助 注意:我使用grunt useminPrepare,usemin,copy,uglify和ngAnnotate。