Когда я загружаю уменьшенную (через UglifyJS) версию моего приложения AngularJS, я получаю в консоли следующую ошибку:
Unknown provider: aProvider <- a
Теперь я понимаю, что это происходит из-за искажения имени переменной. Версия без запутывания работает нормально. Однако я действительно хочу использовать изменение имени переменной, поскольку оно резко уменьшает размер нашего выходного файла JS.
По этой причине мы используем ngmin в нашем процессе сборки, но, похоже, он не решает эту проблему, хотя в прошлом он хорошо служил нам.
Итак, чтобы отладить эту проблему, я включил исходные карты в нашей задаче uglify grunt. Они генерируются только штраф и Chrome делает загрузку карты с сервера. Тем не менее, я все еще получаю то же бесполезное сообщение об ошибке, хотя у меня создалось впечатление, что теперь я должен увидеть исходное имя поставщика.
Как заставить Chrome использовать исходные карты, чтобы сообщить мне, какой поставщик является проблемой здесь, или, как вариант, как я могу узнать поставщика другим способом?
источник
Ответы:
Мне все еще хотелось бы знать, как я мог найти место в нашем исходном коде, которое вызвало эту проблему, но с тех пор я смог найти проблему вручную.
В глобальной области видимости объявлена функция контроллера вместо использования
.controller()
вызова модуля приложения.Так получилось примерно так:
Это отлично работает для AngularJS, но для правильной работы с искажением мне пришлось изменить его на:
После дальнейших тестов я действительно обнаружил экземпляры большего количества контроллеров, которые также вызывали проблемы. Вот как я нашел их источник вручную :
Прежде всего, считаю очень важным включить украшение вывода в опциях uglify. Для нашей тяжелой задачи это означало:
Затем я открыл веб-сайт проекта в Chrome с открытым DevTools. Это приводит к регистрации ошибки, подобной приведенной ниже:
Нас интересует метод трассировки вызовов, который я пометил стрелкой. Это
providerInjector
вinjector.js
. Вам нужно разместить точку останова там, где она выдает исключение:Теперь, когда вы повторно запустите приложение, будет достигнута точка останова, и вы сможете перепрыгнуть вверх по стеку вызовов. Будет звонок из
invoke
ininjector.js
, узнаваемый по строке «Неправильный токен инъекции»:locals
Параметр (подогнаны кd
в моем коде) дает довольно хорошее представление о том, какой объект в источнике является проблемой:Быстрый просмотр
grep
нашего источника обнаруживает много экземпляровmodalInstance
, но, исходя из этого, было легко найти это место в источнике:Что нужно изменить на:
В случае, если переменная не содержит полезной информации, вы также можете перепрыгнуть вверх по стеку, и вы должны нажать вызов,
invoke
который должен иметь дополнительные подсказки:Предотвратить это снова
Теперь, когда вы, надеюсь, нашли проблему, я чувствую, что должен упомянуть, как лучше всего избежать повторения этого в будущем.
Очевидно, вы могли бы просто везде использовать аннотацию встроенного массива или
$inject
аннотацию свойств (в зависимости от ваших предпочтений) и просто постараться не забывать об этом в будущем. Если вы это сделаете, обязательно включите режим строгой инъекции зависимостей , чтобы на раннем этапе отлавливать подобные ошибки.Или вы можете позволить ng-annotate позаботиться об этом. Я настоятельно рекомендую сделать это, так как это устраняет множество ошибок в этой области, например:
Обновление аннотаций - это просто головная боль, и вам не нужно этого делать, если это можно сделать автоматически. ng-annotate делает именно это.
Он должен хорошо интегрироваться в ваш процесс сборки с помощью grunt-ng-annotate и gulp-ng-annotate .
источник
uglify({ output : { beautify : true }})
Рецензия Оливера Зальцбурга была фантастической. Проголосовали.
Совет для всех, у кого может быть эта ошибка. Моя была просто вызвана тем, что я забыл передать массив для контроллера директивы:
ПЛОХОЙ
ХОРОШО
источник
/* @ngInject */
до функции. Кажется, он выполняет сложную часть инъекции без необходимости вводить каждый включенный модуль (я использую Yeoman)используйте ng-strict-di с ng-app
Если вы используете ANGULAR 1.3 вы можете спасти себя мир боли, используя ngStrictDi директиву с ngApp:
Теперь - предварительная минификация - все, что не использует аннотации, взорвет вашу консоль, и вы сможете увидеть это чертово имя, не копаясь в искаженных следах стека.
Согласно документам:
Одно предостережение , он лишь обнаруживает , что в аннотации, а не о том , что аннотации являются полными.
Смысл:
Не поймет, что ThingB не является частью аннотации.
Благодарность за этот совет принадлежит разработчикам ng-annotate , который рекомендуется вместо устаревшего ngMin.
источник
Чтобы минимизировать angular, все, что вам нужно сделать, это изменить ваше объявление на «режим объявления массива», например:
Из:
Чтобы
Как заявить заводские услуги?
источник
У меня была такая же проблема, и я решил ее, просто заменив ngmin (теперь устаревший) на ng-annotate для моей задачи сборки grunt.
Кажется, что yeoman angular также был обновлен для использования ng-annotate с момента этого коммита: https://github.com/yeoman/generator-angular/commit/3eea4cbeb010eeaaf797c17604b4a3ab5371eccb
Однако, если вы используете старую версию yeoman angular, как я, просто замените ng-min на ng-annotate в своем package.json:
run
npm install
(затем по желаниюnpm prune
) и следите за изменениями в фиксации для редактированияGruntfile.js
.источник
чтобы узнать, каково было исходное имя переменной, вы можете изменить способ изменения переменных в uglify:
и теперь ошибка более очевидна
РЕДАКТИРОВАТЬ
Теперь это так очевидно ...
теперь каждая переменная преобразована в уникальное значение, которое также содержит оригинал ... просто откройте минимизированный javascript и найдите "a_orig_ $ stateProvider_91212" или что-то еще ... вы увидите это в исходном контексте ...
не может быть проще ...
источник
Также не забываем
resolve
свойство маршрута. Он также должен быть определен как массив:источник
С генератором-глотком-угловым:
Напишите / ** @ngInject * / перед каждым контроллером, службой, директивой.
источник
Быстрое и грязное исправление для этого, если вам не требуется, чтобы Uglify искажал / сокращал имена переменных, - это установить mangle = false в вашем Gruntfile.
источник