AngularJS中$filter配合Uglify打包后失效,报[$injector:unpr]错误
解决AngularJS构建后$filter("currency")/$filter("date")注入错误的问题
你遇到的这个问题本质是代码压缩混淆导致AngularJS内置服务依赖注入失效——uglifyjs把$locale这类内置服务的变量名混淆成了短字符e,但ng-annotate-webpack-plugin没正确识别这些间接依赖,最终让注入器找不到对应的提供者,所以抛出了Unknown provider: eProvider <- e <- $locale <- currencyFilter这类报错。
下面是几个针对性的解决方案,按优先级推荐:
方案1:优化ng-annotate配置,确保依赖被正确标注
ng-annotate默认可能不会自动处理$filter调用里间接依赖的内置服务,你可以从两方面调整:
- 先检查webpack配置里的ng-annotate插件,确保开启
add模式(自动添加缺失的注入注释):
new NgAnnotatePlugin({ add: true, // 核心:自动为未标注的依赖添加注入注释 single_quotes: true })
- 对于使用
$filter的代码块,手动添加显式的数组式注入注释,把$locale这类依赖明确写出来,避免压缩时被混淆:
angular.module('yourAppModule').controller('YourController', ['$filter', '$locale', function($filter, $locale) { // 正常使用过滤器 var price = $filter('currency')(199.99); var today = $filter('date')(new Date(), 'yyyy-MM-dd'); }]);
这种写法会让Angular通过注释里的字符串常量找到对应的服务,不受变量名混淆影响。
方案2:禁止uglify混淆Angular内置服务名
如果ng-annotate的调整没生效,你可以直接给uglifyjs-webpack-plugin设置白名单,让它保留关键的Angular内置服务变量名:
new UglifyJsPlugin({ uglifyOptions: { mangle: { // 保留这些内置服务的原始名称,不进行混淆 reserved: ['$locale', '$filter', 'currencyFilter', 'dateFilter'] }, compress: { warnings: false } } })
这样压缩后这些服务名不会被改成短字符,注入器就能正常识别它们了。
方案3:使用/*@ngInject*/简化注入标注
如果不想手动写数组式注入,也可以用/*@ngInject*/注释让ng-annotate自动识别依赖,比如:
angular.module('yourAppModule').controller('YourController', function($filter, $locale) { /*@ngInject*/ var price = $filter('currency')(199.99); });
只要ng-annotate插件开启了add模式,就会自动把这个注释转换成Angular能识别的注入格式。
额外检查项
- 确认你的AngularJS版本是1.3及以上,更早版本对压缩混淆的兼容性较差;
- 检查webpack插件执行顺序,必须让ng-annotate-webpack-plugin在uglifyjs-webpack-plugin之前运行——要先完成依赖标注,再进行压缩混淆,顺序颠倒的话ng-annotate就起不到作用了。
内容的提问来源于stack exchange,提问作者José Alejandro Salazar Marcano
相关产品推荐
相关产品推荐

