Когда яваскрипт в веб-проекте занимает достаточно большую долю, и клиентские скрипты вырастают за рамки «инлайн-скриптов» с одной-двумя строчками вызова jquery-плагинов, вопрос о проверке и валидности яваскрипта встает достаточно явно (даже для .net-разработчиков, достаточно далеких от js в принципе :)).
Для меня эта проблема стала наиболее актуальной, когда я начал генерировать яваскрипт-хэлперы с помощью T4-шаблонов, и стало просто необходимым своевременно узнавать о том, что яваскрипт-переменная Constants.MainController.ContentId больше не существует (а была переименована в ContentsId). Также хотелось сократить цикл обнаружения банальных опечаток в названиях переменных — раньше об этом говорила консоль ошибок браузера, а хотелось видеть это на этапе билда.
В решении данной проблемы мне помогли «псевдо-компиляторы» яваскрипта, хотя, пожалуй, корректнее было бы называть их верификаторами синтаксиса.
Самое простое из того, что находит гугл — это библиотеки вроде JSLint и JSHint. Сами они позиционируются как «инструменты проверки качества» яваскрипт кода и названы в честь когда-то популярной утилиты lint — статического анализатора кода на языке C.
И jshint, и jslint достаточно неплохи, имеют вполне серьезный функционал проверки и несколько способов интеграции с visual studio, но имеют и существенный минус — они, по сути, способны анализировать только один отдельный файл. В обстановке реального проекта, где из одного файла скрипта с легкостью используются функции/переменные из двух-трех других, эти утилиты становятся фактически бессмысленными (они хорошо справляются с задачей, для которой и были разработаны, но для решения данной проблемы — не подходят).
С проблемой референса нескольких js-файлов, видимо, столкнулся не я один, потому что достаточно быстро нашелся альтернативный проект, основанный на jslint — JavascriptLint. Он, среди прочих, содержит директиву /*jsl:import PathToOtherScript*/, которая позволяет при анализе файла «иметь ввиду» наличие других скриптов. Библиотека вполне неплоха, но от нее тоже пришлось отказаться, поскольку до анализа переменных «второго уровня» руки у неё не доходят (Constants.MainController — считается валидным всегда, если валидна переменная Constants). А «глубокая проверка» была мне абсолютно необходима.
После всех этих попыток не оставалось ничего другого, как остановить свой выбор на Google Closure. Это и компилятор, и «минификатор» и утилита проверки синтаксиса от небезызвестной компании из Маунтин-Вью. Используя Advanced оптимизацию и расширенное информирование об ошибках (warning level — verbose) можно узнать обо всех недостатках вашего js-кода :)
Для использования как External Tools или пост-билд ивент из Visual Studio можно использовать утилиту plovr — она позволяет настроить и ошибки, которые вы хотите/не хотите видеть (данная настройка, увы, не слишком детальна), и js-файлы, которые необходимо процессить.
Однако ошибки, выводимые plovr’ом можно будет увидеть только в Output window. Это слегка неудобно, потому что затрудняет поиск файла и строки с ошибкой — навигацию к ним приходится производить «в ручном режиме» :)
После этого и было найдено последнее слагаемое в успешной проверке яваскрипта — утилита cc2vs. Лучше всего результат интеграции опишет картинка:
Детальный отчет об ошибках именно там, где мы это привыкли видеть с поддержкой встроенной в VS навигации к файлу и строчке. Ну и интеграция в одну строку — просто прописать в post-build-event что-то вроде:
cc2vs.exe --input-dir "$(ProjectDir)Scripts\filename.js" --ccarg-warning_level VERBOSE --ccarg-compilation_level ADVANCED_OPTIMIZATIONS
Для большинства задач cc2vs вполне достаточно.
Однако мне хотелось более тонкой конфигурации ошибок/предупреждений и, как следствие, конфигурации через json-файл (как в plovr), поскольку конфигурирование через командную строку при большом количестве опций становится довольно-таки проблематичным.
Поэтому на базе cc2vs я написал свою небольшую библиотеку, код которой очень скоро появился на кодеплексе :)
А как это все работает? У меня есть разные js-файлы, которые могут подключаться динамически в зависимости от чего-нибудь. К тому же какие-то js-ки могут находиться прям на странице. И, опять, же они могут меняться динамически в райнтайме.
Оно валидирует конкретный js файл/файлы.
Js-ки «прям на странице» они не валидируют (по крайней мере я не пробовал).
Для проверки «все ли скрипты ты подключил на конкретной странице» они тоже не предназначены.
В норме валидатор конфигурируется на проверку, допустим, папки «js», с указанием «внешней» библиотеки «Scripts/jquery.js».
При этом он считает, что все файлы из папки js «подключены» и проверяет их. Он также считает, что «подключена» jquery, но её он не проверяет.
Как-то так :)
Ok, спасибо