Индексация AJAX-сайтов



    Вместе с разработкой Joosy, AJAX внезапно – но ожидаемо, – заполонил все проекты, за которые мы беремся. Парадигма оказалась крайне удачной во всех аспектах, кроме одного. Того самого классического: «AJAX? Индексация? Пфф...». Пока мы делаем интернет-банки, это нас вполне устраивает. Но как не отказывать себе в этом изысканном удовольствии для открытых Web-ресурсов?

    А вот как: Google AJAX Crawling – это стандарт Google, который позволяет при формировании AJAX-адресов специальным образом (#!) заставить Google магически запрашивать вместо него другой магический адрес. С которого Google будет ждать HTML-дамп этой страницы, который он весело прожует. Добрые люди уже написали статью про то как это работает. Ну а нам остается научиться эффективно этот дамп формировать. Да так, чтоб без вмешательства в код самого приложения.


    Hashbang – это маленький прокси-сервер на Ruby, работающий по протоколу Rack. Последнее означает, что для того чтобы его поднять сгодится любой web-сервер, работающий с Ruby и/или Rails. А для тех, кто использует собственно Rails, мы приготовили парочку особенных плюшек. Но обо всем по порядку.

    Общее устройство


    При инициализации, Hashbang создает в своих недрах инстанс WebKit-браузера. После того как запрос с указанием нужного URL запущен, он открывает нужный адрес, ждет специального Javascript-события и возвращает HTML код на момент, когда это событие произошло.

    Это означает, что все, что вам потребуется изменить в текущем приложении – это вызывать

    Sunscraper.finish()

    когда страницу, подготавливаемую Javascript'ом можно считать готовой.

    В боевом режиме это будет выглядеть так:



    Про внутренний браузер и производительность


    Мы много экспериментировали с возможными реализациями «безголового» браузера. Пробовали Watir и разные существующие биндинги Qt. Ничего хорошего не вышло. Отчаявшись, мы просто написали свой биндинг к Qt-WebKit, который и только и умеет, что возвращать HTML, отслеживая событие: Sunscraper. Написано это чудо на смеси C/C++ и подключается к Ruby посредством FFI. Это значит, что Sunscraper должен работать не только на MRI, но и на JRuby/Rubinius. К сожалению, с Rubinius он все-таки не работает из-за багов в реализации того самого FFI.

    Так как все, что мы запускаем – это сам движок WebKit, производительность близка к максимальной для решения этой задачи. Реальные данные с живых серверов в процессе сбора.

    Перед установкой


    Sunscraper использует Qt. Поэтому он обязательно вам понадобится для установки gem'а Hashbang. Если вы используете Mac, мы рекомендуем Homebrew: brew install qt. В Linux можно ставить любой, посвежее, из пакетов.

    Development-режим для тех, кто на рельсах


    Если вы не разрабатываете на Rails, смело переходите к следующему параграфу, который расскажет о внедрении Hashbang в бой.

    Для установки Hashbang в Rails-проект, необходимо выполнить следующую последовательность действий:

    1. Добавить gem hashbang в Gemfile
    2. Сгенерировать базовое приложение с помощью rails g hashbang

    Теперь внутри вашего Rails-приложения, в папке hashbang, лежит мини-приложение самого Hashbang'а. А это значит, что вам нужно пропустить первый абзац в части «настройки и запуска».

    В development-среде, Hashbang вставляет в загрузку Rails свой middleware, который перехватывает все запросы, содержащие магический фрагмент _escaped_fragment_ и автоматически обрабатывает их. Проблема лишь одна: Webrick работает в один поток. А так как Hashbang запрашивает «сам себя», это приводит к дедлоку. Поэтому чтобы потестировать текущее приложение локально, запустите его с помощью rake hashbang:rails. Эта команда запустит ваше приложение под сервером Unicorn в два поток. После запуска – localhost:3000/?_escaped_fragment_ – и проверяйте HTML. Только не забудьте, что в самом AJAX-приложении надо вызывать Sunscraper.finish().

    Чтобы сэмулировать запуск Hashbang в боевом режиме, где он работает через /?url=http://..., используйте команду rake hashbang:standalone.

    Настройка и запуск


    Если вы не используете Rails, базовое приложение можно взять из специального репозитория. Все, что вам надо будет сделать – разместить его где-нибудь, убедиться что у вас установлен gem bundler и сделать в корне приложения bundle install.

    Внутри сгенерированного/скопированного Hashbang-приложения лежит файл config.rb, который обязательно надо отредактировать для эффективной работы. В нем всего две директивы:

    • url: регулярное выражение, которому должен соответствовать запрашиваемый URL
    • timeout: таймаут в милисекундах, который hashbang будет дожидаться события Sunscraper.finish()

    Предположим, что для запуска сервиса мы используем модуль Passenger, который реализует работу с Rack на базе Nginx. В этом случае для корректной работы нам нужно добиться следующего:

    • На специальном внутреннем адресе у нас должно работать приложение Hasbang
    • Все запросы, содержащие _escaped_fragment_ должны пробрасываться на это приложение, причем пробрасываться uri-escaped абсолютным урлом в параметр url=....
    • Нам нужно ограничить количество параллельных ресурсов к этому приложению, потому что врядли нас будут индексировать в сто потоков, а ресурсы WebKit любит.

    Вот какой конфигурационный файл можно использовать: https://gist.github.com/2127685. Это пример использования Hashbang в Ralis-приложении.

    О грустном


    К сожалению, в наши родные пенаты, Яндекс, этот стандарт так и не дошел. Его поддерживает Google, его поддерживает Bing (а значит и Yahoo). Даже crawler Facebook и тот его поддерживает. А Яндекс – нет. Это значит, что Hashbang никак не поможет вашей индексации в отечественном сегменте интернета. По крайней мере пока. Мы направляем яростные лучики добра в сторону команды Яндекса и желаем им поскорее обратить свой взор на столь активно развивающийся технологический сегмент Web'а :).

    В заключение


    Несмотря на то, что мы уже используем Hashbang в бою, мы еще не обкатали его на всех возможных конфигурациях. Если у вас возникнут какие-то проблемы при его сборке или настройке, мы всегда рады новым Issues на гитхабе.

    Спасибо :).
    Round Lake 33,55
    Компания
    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Похожие публикации
    Комментарии 53
    • +4
      Я понимаю, что хешбенги это клёво и каттинг эдж (этим я показал, насколько я продвинут в жаргоне :)). Но мне претит сама идея ломающая веб по корню — переложить навигацию и загрузку с HTTP в джава-скрипт. И я не один.

      И о грустном. Issue у вас один — опечатка в скрипте и весь ваш сайт лежит. Выключенный в целях безопасности джаваскрипт и весь ваш сайт одна пустая оболочка.
      • +1
        Ах, ну да, зато Гуглбот ваш сайт проиндексирует на славу. :)
        • +1
          «Переложить навигацию и загрузку с HTTP в Javascript» – Javascript тоже использует HTTP для загрузки. Очень странный комментарий.

          В остальном – спасибо за ваше мнение, но давайте обойдемся без троллинга и холиваров. Эта статья не о том как клево или не клево использовать RICH. Она для тех, кто свой выбор уже сделал.
          • +2
            Ну а я для тех, кто этого выбора ещё не сделал соответственно. :-)
          • –1
            А почему вы не воспринимаете данные сайты как клиент-серверные приложения, просто выполненные на JS и работающие в браузере?
            • +1
              Угу. Лучше уж использовать что-то типа continious integration. Сделали обычный сайт, затем на него навесили аякс. Тем более, что многие фреймворки давно уже имеют встроенные хелперы типа $this->isXmlRequest(). Тогда никто не потеряет в функциональности. Плюс, хешбенг несет в себе жуткие ограничения на архитектуру (если его используете, то нельзя отдавать страницы без него). Лучше уж History API + обычный хеш (либо вовсе для старых браузеров отказаться от аякса).
              • +5
                Ой. Утро доброе. Перепутал. continious integration = progressive enhancement
              • НЛО прилетело и опубликовало эту надпись здесь
              • 0
                Яндексу можно пытаться скармливать «escaped_fragment-ированные» ссылки в Sitemap.

                В целом состояние с индексацией AJaX — печальное. Львиная доля форумов и блог-движков (включая Хабр) и часть мессенджеров не понимают ссылки с хешбенгами, соответственно, получение веса от внешних ссылок для таких страниц закрыто. Обычные люди не понимают, как такие ссылки передавать и как по ним переходить. При загрузке страница мигает (контент на /-странице заменяется контентом по ссылке из хешбенга).

                Из приятного — на горизонте маячит HTML5 History API, который частично проблему передачи и непривычного вида ссылок решит.
                • +1
                  На самом деле, History API сделает только хуже. Если есть возможность генерировать сразу весь HTML на сервере, то порционная его загрузка – это полумера. Настоящее веселье заключается в переносе на клиент вообще всего представления, включая рендеринг. И тогда History API просто не работает. Вообще.

                  Лично я считаю, что будущее за браузером в виде виртуальной машины, а web-сервера станут просто REST Application-серверами. При таком подходе hashbang'и, конечно, костыль. Но лучше ничего просто нет. Поэтому это вопрос проникновения и привычки. Ну и наличия критической массы инструментов, таких как Hashbang, которые решают типовые проблемы, связанные с таким технологическим стэком.
                  • 0
                    Да почему же? History API вполне себе работает. Пример — ippk.sfedu.ru (к оформлению и содержимому не цепляйтесь :)). Попробуйте походить по ссылкам. Для браузеров, которые не понимаю History API (к примеру, старый IE), видны простые ссылки. И индексируется отлично ;).
                    • 0
                      Нет нет, вы не совсем меня поняли. Он работает, безусловно. Я лишь про то, что Hashbang создан для случаев, когда рендеринг шаблонов выполняется в браузере. А сервер ничего не рендерит вообще. Если мы используем History API, у нас нет способа разграничить серверную часть и клиентскую. А с #! – есть.
                      • 0
                        Хм, видать и в правду плохо вас понял. Но, если рассмотреть картину идеального взаимодействия клиента с сервером, то, на мой взгляд, на клиенте должна быть просто картинка и все, как некий видеопоток с возможностью отсылать на сервер действия мышки, клавиатуры и т.п., а сервер возвращает следующие кадры. В итоге от клиента требуется минимума производительности, что сэкономит батарею и цену железа под такой клиент, но возрастет нагрузка на сервер, что, по моему мнению, обойдется дешевле. Вроде что-то подобное пытаются сделать с видеоиграми…
                        • 0
                          Спорный момент. Серверов всегда меньше чем клиентов. Игры слишком максималистичный вариант – это скорее исключение. Рендеринг шаблонов не такая затратная операция для браузера. Но стоит ее умножить на миллион клиентов, как она становится затратной для сервера. То есть на клиенте мы ее не замечаем, но:

                          1) Передаются только данные в JSON, канал разгружается от лишнего HTML.
                          2) Мы управляем рендерингом там же, где работает код, который управляет динамикой. Это невероятно удобно и дает много доп. возможностей. Это, на самом деле, основная цель. Мы можем добавить эффекты в переходы между страницами, хорошо структурировать клиентский код и т.п. Javascript'а в современных ресурсах все больше и сопрягать его с серверной частью все сложнее.
                          3) Ну и нагрузка на сервера меньше. Для сложных представлений рендеринг – вполне заметная операция.
                          4) Удобнее кооперироваться. Я противник четкого выделения ролей в команде, но всегда есть люди, которым больше нравится писать на Ruby и люди, которым больше нравится возиться с прямым взаимодействием с пользователем. С таким подходом обе категории становятся счастливее :).

                          Я вначале написал, что Hashbang создавался после нашего повального увлечения другой нашей разработкой, Joosy. Посмотрите 3 первых гайда (0,1,2) на guides.joosy.ws – вот как и с чем мы работаем
                          • 0
                            Зато сервера могут быть нагружены постоянно и использовать свой ресурс по максимуму, а клиентское железо, в большинстве случаев, большую часть своей «жизни» простаивает. Цены растут и цена простоя вместе с ними.

                            А Joosy обязательно рассмотрю повнимательнее как некую концепцию.
                            • 0
                              Честно говоря, мне совершенно непонятен Ваш подход, Владимир. Издавна люди стремились к кластеризации. Сервер и так будет нагружен, ему с головой хватит обработки бизнес-логики и удерживания СУБД. А клиентские машины представьте себе как эдакий огромный кластер, который обрабатывает именно часть с представлением.

                              Я не могу представить себе ситуацию, когда на любом современном железе (включая мобильные телефоны) люди будут жаловаться, что де «не открывается сайт, комп перегружен». А вот от перегрузки серверов все падает регулярно. Сервера не просто и так не простаивают, они не справляются. А вот клиентские мощности как-раз не задействованы вообще.
                              • 0
                                Ну а смысл, к примеру, мощного процессора в телефоне / ноутбуке и т.п., когда он просто лежит и не работает (ну, почти не работает). А так железо бы работало. То, что под мое представление идеального нет инфраструктуры — на то он и идеал, что не достижим :).

                                Ну а сайты на мобилках-то открываются, вот только проблемы с производительность вполне могут быть. Ну и проблема с не обновляемым ПО… Возможно все это можно было бы решить, если бы сервер отдавал просто видеопоток.
                                • 0
                                  С рендерингом их не будет. Проверено. С эффектами, любым сложным взаимодействием с клиентом – да. С рендерингом – нет.

                                  Касательно вашего представления о мире – я понял, это действительно идеал. Процессоры в телефонах уже есть. Не использовать их глупо. Вот такая простая логика. А что могло бы быть в теории… Люди же ходили по этому пути – были простые терминальные клиенты. Не пошло. В первую очередь потому, что сделать facebook, который всем будет стрим видео раздавать интерактивного – это на порядки больше нагрузки. А им ее и так хватает. Это просто не работает :\
                        • 0
                          Хватит уже говорить, что рендринг страницы\шаблона\представления выполняется на сервере, на сервере максимум может генерироваться разметка, а ее рендринг всегда происходит в браузере.
                          • 0
                            Толсто. Разметка тоже рендерится из шаблонов.
                            • 0
                              Что-что делается с разметкой?

                              Ре́ндеринг (англ. rendering — «визуализация») — термин в компьютерной графике, обозначающий процесс получения изображения по модели с помощью компьютерной программы.

                              Вы упорно путаете термины рендеринг и генерация…
                                • 0
                                  Криво названные методы — отличный аргумент!
                                  • 0
                                    Точно. Самые популярные web-фреймворки делают мудаки, один Вы – Д'Артаньян :). Уходите отсюда, пожалуйста.
                                    • 0
                                      Успокойтесь, вас никто не троллит. Чтобы понять, что генерация разметки не является рендерингом, надо напрячь мозг, а не бежать прыгать в окно за остальными. С тем же самым успехом, можно назвать рендерингом генерацию машинного кода.
                  • +2
                    Я использую простой способ.
                    • 0
                      ээм, простите, что это? и как оно помогает при индексации RICH-сайтов?
                      • +1
                        А разве в сайты написанные на Ruby нельзя вставить JavaScript?
                        Принцип же точно такой же остается: вешаем обработчик на ссылки. В зависимости от состояния JS (выключен или включен) запрос будет отправлен AJAX'ом или по старинке
                        • 0
                          Мой пример надо доработать, добавив после 17 строки:
                          history.pushState({}, '', this.href);
                          • 0
                            ах вы о progressive enhancement.
                            это совершенно другой случай. у нас кроме одной стартовой страницы, больше никакая разметка не формируется на стороне сервера. все шаблоны и т.п. рендерятся через JS, c сервера приходит только JSON. мы намеренно отказались от progressive enhancement для клиентов, которые не работают с JS, чтобы получить максимум гибкости и не дублировать серверный и клиентский код.
                        • НЛО прилетело и опубликовало эту надпись здесь
                          • 0
                            Это для примера, а так все через JSON идет
                            • НЛО прилетело и опубликовало эту надпись здесь
                        • НЛО прилетело и опубликовало эту надпись здесь
                          • 0
                            и тогда придётся писать сайт не на JS, а и на JS, и на Ruby. это сведёт к нулю всю гибкость разработки RICH-приложений.
                            • НЛО прилетело и опубликовало эту надпись здесь
                              • +2
                                буду рад, если вы опишите возможный сценарий. как сейчас это на деле:
                                если впилить History API, то когда приходит запрос на /some/page, придётся его рендерить на сервере, а если это переход со страницы, то рендерить на клиенте. сейчас же запрос может прийти только вида /!#/some/page, поэтому нам хватает рендеринга _только_на_клиенте_.
                                поэтому, прошу пояснить про цели и кривые инструменты.
                                • НЛО прилетело и опубликовало эту надпись здесь
                                  • 0
                                    > то прогоняется на сервере через рендерер
                                    вот она, главная проблема. у нас вообще нет на серверах рендереров. зачем нам делать два рендеринга (клиентский и серверный) для одного и того же? только чтобы у пользователей не было "#!" в строке браузера? сомнительный повод для увеличения объёма работы в более, чем 1.5 раза.
                                    • НЛО прилетело и опубликовало эту надпись здесь
                                      • +1
                                        Нет, это не правда. Как минимум потому что шаблоны всегда содержат минимальный код (хотя бы хелперы). А это разные языки на сервере и на клиенте. И это только одна проблема из тысяч. Я подозреваю, что Вы просто никогда не делали рендеринга на клиенте отсюда и недопонимание. А про фреймворк – это вообще просто слова. Вы когда говорите, что что-то можно решить чем-то таким магическим, ссылку в студию. А то слова такие слова.

                                        Отсутствие индексации в Яндексе нас не пугает, так как проекты на западный рынок.

                                        Серьезно, Вы действительно считаете, что все эти люди зря придумали Backbone? И он зря такой популярный? А ведь это именно та парадигма, которую мы используем. Какие все глупые, не используют progressive enhancement! К сожалению, реальность выглядит иначе. А Ваша позиция напоминает мне картинку «JPG JPG JPG! No thinking required!»
                                        • НЛО прилетело и опубликовало эту надпись здесь
                                          • +1
                                            Да при чем тут лучшее решение или нет :). Просто очевидно совершенно, что Вы – теоретик. Потому что год назад я размышлял так же как Вы. Просто посмотрите на свои ссылки. Я просил у Вас решение проблемы рендеринга, а вы мне дали ссылку на свой гитхаб. Спасибо :). По ссылке – какой-то вводный материал для тех, кто вообще не понимает о чем речь. Опять же, потрясающее доказательство ваших слов :).

                                            Давайте по пунктам:

                                            — никто не заставляет пихать хелперы в шаблоны

                                            Вот это ровно то, в чем Вы нас пытаетесь уличить. Вы под кривые задачи подгоняете парадигму. Код и хелперы в шаблонах – это нормально и удобно. Это есть почти всегда. Простейшие шаблонизаторы вроде mustache банально неудобно использовать. Они усложнят разработку на порядок.

                                            — рендерим то на сервере, то на клиенте

                                            Вы создаете себе тьму проблем. И в ответ на их перечисление: «ну есть же фреймворк!» и пункт 1. Очень обоснованные ответы :). И ссылок не даете. Так кто там подгоняет парадигму под кривые цели?

                                            А еще Вы меня школьником назвали :(. Ну ай-ай-ай. А я Вам могу с тем же успехом сказать, что вы консервативны как старик ;). Но давайте на этом остановимся с личностями, ок?

                                            — 8< — А что же мы получаем от нашей парадгимы:

                                            1) Мы не используем рендеринг на сервере вообще. Мы раздаем REST. Единая база кода для всех приложений, в браузере, на десктопе, в мобильных.
                                            2) Благодаря тому, что шаблоны изначально оседают в браузере мы не тратим ни канала, ни серверного времени на рендеринг. И если Вы думаете, что это малое время, то Вы заблуждаетесь. В сложных проектах и сложных представлениях – это ОЧЕНЬ большое время.
                                            3) У нас нет жуткой смеси из Ruby и JS для динамики. Каждый язык выполняет свою цель.

                                            И единственная (я подчеркиваю, единственная!) проблема – это индексация. Мы ее решили. Если кому-то еще нужно, с сообществом поделились. На этом предлагаю вопрос закрыть.
                                            • НЛО прилетело и опубликовало эту надпись здесь
                                              • 0
                                                Видите, по делу сказать нечего :). Я потратил 5 абзацев текста чтобы объяснить Вам отличия парадигмы, используемой нами, от той, которую описываете Вы. Это _разные_ подходы. Не один кривой, а другой нет. А разные способы разработки. С разными целями и разными инструментами. Я задал Вам _конкретные_ вопросы. И конкретно все прокомментировал про ссылки. Но это, похоже, был бисер.

                                                P.S. Но вот «и что вам каждую ссылку должны разжевывать» – это как-то перебор, чтоли. www.google.com/. Вот Вам ссылка. Идите и учите матчасть. А то буду я вам еще тут ссылки разжевывать %). Вот как это звучит.
                                                • НЛО прилетело и опубликовало эту надпись здесь
                                                  • 0
                                                    Виталий, почему у вас такая плотная связь «RICH = одностраничник»? В современном мире AJAX используется далеко не только для подгрузки маленьких блоков на страничке.
                                                    • НЛО прилетело и опубликовало эту надпись здесь
                              • +1
                                Главное понимать — нужно ли этот контент индексировать. Не вижу смысла делать single-page javascript app доступный для индексации сегодня. Вся суть rich в том, что приложение, а не вэб-сайт. В чем понт индексировать панель управления например?
                                • 0
                                  весь прикол как раз заключается в том, что наша Joosy позволяет писать полнценные RICH-сайты, с лёгкостью одностраничковых приложений (но это уже совсем другая история, не относящаяся к статье). это очень подсаживает на себя. отсюда и появилась надобность индексирования RICH-приложений.
                            • 0
                              Люди, делающие подобные поделки, не понимают, что ajax — это всего лишь транспорт информации в другом формате, по другому каналу.

                              Есть канал html, есть json (грубо говоря, ajax).

                              Поясняю. То есть, на странице должны быть обычные ссылки и сайт должен работать нормально без js. Но как только js включён, на ссылки вешаются обработчик, который запрашивает данные через ajax-канал и выводит/обновляет информацию в нужном виде в нужном месте (зависит от приложения, от простого body.replaceHtml(newHtml) до сложного обновления только нужных блоков).
                              • 0
                                Это вы не понимаете что такое JS MVC :). Почитайте про Backbone прежде чем кидаться громкими словами. Ваш подход древний как мамонты. Мы используем другой.
                              • 0
                                Яндекс таки научился индексировать сайты с hashbang-адресацией тем же методом, что и Google, да и глупо было бы изобретать свой.

                                Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                Самое читаемое