“未知提供者:aProvider <- a"如何找到原始提供商? [英] &quot;Unknown provider: aProvider &lt;- a&quot; How do I find the original provider?

查看:32
本文介绍了“未知提供者:aProvider <- a"如何找到原始提供商?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我加载 AngularJS 应用程序的缩小版(通过 UglifyJS)时,我在控制台中收到以下错误:

未知提供者:aProvider <- a

现在,我意识到这是由于变量名修改造成的.未损坏的版本工作正常.但是,我确实想使用变量名修改,因为它大大减少了我们的 JS 输出文件的大小.

出于这个原因,我们在构建过程中使用了 .你会想要在它抛出异常的地方放置一个断点:

当你现在重新运行应用程序时,断点将被命中,你可以跳转到调用堆栈.,或(取决于您的偏好)$inject 属性注释 并且尽量不要在将来忘记它.如果这样做,请确保启用严格依赖注入模式, 尽早发现此类错误.

<块引用>

小心!如果您使用的是 Angular Batarang,StrictDI 可能不适合您,因为 Angular Batarang 会将未注释的代码注入您的代码中(糟糕的 Batarang!).

或者你可以让 ng-annotate 来处理它.我强烈建议这样做,因为它消除了这方面的很多潜在错误,例如:

  • 缺少 DI 注释
  • DI 注释不完整
  • DI 注释顺序错误

保持注释最新是一件很麻烦的事情,如果可以自动完成,您就不必这样做.ng-annotate 正是这样做的.

它应该使用 grunt-ng-annotate 很好地集成到您的构建过程中和 gulp-ng-annotate.

When I'm loading the minified (through UglifyJS) version of my AngularJS application, I get the following error in the console:

Unknown provider: aProvider <- a

Now, I realize that this is due to variable name mangling. The unmangled version works just fine. However, I do want to make use of variable name mangling, as it drastically reduces the size of our JS output file.

For that reason, we're using ngmin in our build process, but it doesn't seem to resolve this issue, even though it served us well in the past.

So, to debug this issue, I enabled source maps in our uglify grunt task. They are generated just fine and Chrome does load the maps from the server. Yet, I still get the same unhelpful error message, even though I was under the impression that I should now see the original name of the provider.

How do I get Chrome to use the source maps to tell me which provider is the problem here, or, alternatively, how can I find out the provider in another way?

解决方案

I'd still love to know how I could have found the place in our source code that caused this issue, but I have since been able to find the problem manually.

There was a controller function declared on the global scope, instead of using a .controller() call on the application module.

So there was something like this:

function SomeController( $scope, i18n ) { /* ... */ }

This works just fine for AngularJS, but to make it work right with mangling, I had to change it to:

var applicationModule = angular.module( "example" );
function SomeController( $scope, i18n ) { /* ... */ }
applicationModule.controller( "SomeController", [ "$scope", "i18n", SomeController ] );

After further tests, I actually found instances of more controllers that also caused issues. This is how I found the source of all of them manually:

First of all, I consider it rather important to enable output beautification in the uglify options. For our grunt task that meant:

options : {
    beautify : true,
    mangle   : true
}

I then opened the project website in Chrome, with the DevTools open. Which results in an error like the one below being logged:

The method in the call trace we're interested in, is the one I marked with an arrow. This is providerInjector in injector.js. You're going to want to place a breakpoint where it throws an exception:

When you now re-run the application, the breakpoint will be hit and you can jump up the call stack. There will be a call from invoke in injector.js, recognizable from the "Incorrect injection token" string:

The locals parameter (mangled to d in my code) gives a pretty good idea about which object in your source is the problem:

A quick grep over our source finds many instances of modalInstance, but going from there, it was easy to find this spot in the source:

var ModalCreateEditMeetingController = function( $scope, $modalInstance ) {
};

Which must be changed to:

var ModalCreateEditMeetingController = [ "$scope", "$modalInstance", function( $scope, $modalInstance ) {
} ];

In case the variable does not hold useful information, you can also jump further up the stack and you should hit a call to invoke which should have additional hints:

Prevent this from happening again

Now that you've hopefully found the problem, I feel that I should mention how to best avoid this from happening again in the future.

Obviously, you could just use the inline array annotation everywhere, or the (depending on your preference) $inject property annotation and simply try not to forget about it in the future. If you do so, make sure to enable strict dependency injection mode, to catch errors like this early.

Watch out! In case you're using Angular Batarang, StrictDI might not work for you, as Angular Batarang injects unannotated code into yours (bad Batarang!).

Or you could let ng-annotate take care of it. I highly recommend doing so, as it removes a lot of potential for mistakes in this area, like:

  • DI annotation missing
  • DI annotation incomplete
  • DI annotation in wrong order

Keeping the annotations up-to-date is simply a pain in the ass and you shouldn't have to do it if it can be done automatically. ng-annotate does exactly that.

It should integrate nicely into your build process with grunt-ng-annotate and gulp-ng-annotate.

这篇关于“未知提供者:aProvider <- a"如何找到原始提供商?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆