На своем проекте я использую AngularJS. Для нормальной индексации страниц поисковыми роботами на сервере у меня поднят Prerender. Его задача - при получении запроса от поискового робота рендерить страницу на сервере и отдавать ему уже готовый html. Это все из-за того, что поисковики до сих пор хреново работают с JavaScript и динамическим контентом. Google заявляет, что он якобы уже научился. Однако практика и публикации в интернете этого не подтверждают. Яндекс же даже не пытается и этот костыльный способ с пререндером на сервере признает единственно верным.
Так вот, заметил я, что внезапно повыпадало из индекса поисковиков очень много страниц. Стал разбираться. Яндекс где-то сообщил, что не может найти title
на страницах с параметром ?_escaped_fragment_=
. А title
генерится у меня на клиенте. Стал проверять страницы, которые генерирует Prerender - нет контента. Полез в логи и там вот такой вот шедевр от ангулара:
Failed to instantiate module app due to:
[$injector:nomod] Module 'app' is not available! You either misspelled the module name or forgot to load it. If registering a module ensure that you specify the dependencies as the second argument.
http://errors.angularjs.org/1.4.7/$injector/nomod?p0=app
http://xlpe.org/scripts/vendor.f6c40e4e.js:1:95053
b@http://xlpe.org/scripts/vendor.f6c40e4e.js:1:42416
http://xlpe.org/scripts/vendor.f6c40e4e.js:1:68594
http://xlpe.org/scripts/vendor.f6c40e4e.js:2:4789
f@http://xlpe.org/scripts/vendor.f6c40e4e.js:1:33796
n@http://xlpe.org/scripts/vendor.f6c40e4e.js:2:4636
$a@http://xlpe.org/scripts/vendor.f6c40e4e.js:2:4412
h@http://xlpe.org/scripts/vendor.f6c40e4e.js:1:40471
ga@http://xlpe.org/scripts/vendor.f6c40e4e.js:1:40780
fa@http://xlpe.org/scripts/vendor.f6c40e4e.js:1:40028
http://xlpe.org/scripts/vendor.f6c40e4e.js:6:12045
d@http://xlpe.org/scripts/vendor.f6c40e4e.js:4:14969
c@http://xlpe.org/scripts/vendor.f6c40e4e.js:2:819
Описание ошибки просто шикарное! Ссылка на сжатый вендорный код. Отлично!
Запускаю проект в developer mode. JS файлы не сжаты и не сконкатенированы - все работает! Запускаю grunt build
, production mode - у пререндера ошибка.
Пробую все возможные браузеры. Все нормально работают, приложение открывается, никаких сообщений об ошибках. Даже в IE! А вот пререндер, который работает на браузере PhantomJS, никак не хочет.
Попробовал разные версии Prerenderа.
Проверил все версии ангулара, плагинов для grunt, пакетов bower. Изменений нет.
День 2
Нахожу закономерность, что ошибка появляется, когда выполнена конкатенация (объединение) js файлов проекта. Стал объединять их частями и таким образом вышел на модули, добавление которых к объединяемым файлам приводит к появлению ошибки. Хаха, результат! А ангулар в описании ошибки ни строчки про мои файлы не писал, сука.
Продолжаем дебажить в том же духе. Модуль состоит из нескольких файлов. Вычищаем их и постепенно заполняем кодом до момента возникновения ошибки. Так нахожу файл с контроллером ангулара. Теперь используем комментарии и находим те строчки, из-за которых все не работает. Вот они:
CableTypesResources.CableTypes().get({},
function succes(results) {
//...
}, function err(err) {
//...
}
);
Здесь я использую ангуларовский $resource
, который вытягивает данные по REST с сервера и выполняет колбэки succes
или err
. Так вот, нужно просто убрать эти имена колбэков...
CableTypesResources.CableTypes().get({},
function (results) {
//...
}, function (err) {
//...
}
);
Так все работает. Жесть!
Такие функции используются у меня в нескольких модулях. Подправляем их и любуемся результатом. Два дня, два дня не отходя от компа... Срочно пива!
Выводы:
-
Проблемные модули были добавлены в проект несколько месяцев назад и выпадение из индекса у поисковиков растянулось на это время.
-
За все это время от гугла ни одной ошибки. Черный ящик. Выпадают страницы, и хер его знает, почему. Возможно, выпадение и не связано с этим багом. Будем смотреть. Очень растянут во времени этот процесс.
-
JS с его кучей фрэймворков, пакетов, зависимостей - это жесть. К использованию сторонних разработок надо подходить очень аккуратно и обдуманно, дабы после не страдать от чужих багов.