Введение


Динамические веб приложения (SPA, Single Page Applications) становятся все более популярными. Их использование позволяет упростить и ускорить разработку и поддержку за счет следующий преимуществ:


  • не требуется server-side рендеринг;
  • сайт — это набор статических файлов (html, js, css, images, fonts), которые лежат на CDN;
  • нет затрат на масштабирование frontend;
  • код frontend локализован в одном проекте. (Раньше часть кода была на server-side, часть в frontend.);
  • уменьшение затрат на разработку backend (только API);
  • уменьшение нагрузки на backend (только API запросы);
  • возможность вместо собственного backend использовать сервисы типа (https://scaphold.io), микросервисы, lambda.

Из популярных библиотек для SPA хочется отдельно выделить ReactJS. Его использование позволяет создавать сложные веб приложения быстро и просто, сохранить скорость разработки на большой базе кода, избежать регрессионных ошибок при добавлении новых функций.


Большой нерешенной проблемой SPA является их полная несовместимость с веб краулерами поисковых систем (индексация сайтов) и социальных сетей (sharing в соц. сетях). На текущий момент краулеры не выполняют на своей стороне javascript и поэтому не могут получить содержимое SPA в виде html кода. В 2015 году Google официально отказался от поддержки выполнения javascript кода на своей стороне.



Решения


Сегодня есть несколько типов решений для проектов, которые хотят полноценно разрабатывать SPA.


Поддержка собственного server-side рендеринга


Что это такое


Это старый подход к организации веб приложения при котором сохраняется server-side рендеринг html страниц. Когда загружается SPA в браузере клиента, обычно, сначала приложение удаляет весь html код, созданный сервером, и его место заполняется результатом работы программы. На текущий момент это наиболее часто используемое решение.


Чем это хорошо


  • это работает;
  • все свое.

Чем это плохо


  • удорожает и замедляет разработку за счет необходимости дважды реализовывать одни и те же функции на сервере и клиенте;
  • удорожает поддержку и масштабирование, т.к. требуется управлять и обслуживать веб-сервера;
  • увеличивает вероятность отказов, ошибок, сбоев.

Изоморфный рендеринг


Что это такое


Идея о том, что один и тот же код может выполняться и на клиенте и на сервере. К сожалению, работает эта идея только на очень простых приложениях. Кроме того поддерживать все новые появляющиеся функции браузеров на сервере очень трудно, что приводит к потребности часто выполнять дополнительную работу для адаптации приложения для работы на сервере.


Чем это хорошо


  • работает на очень простых приложениях, типа "hello world";
  • не требует дважды реализовывать одни и те же функции на сервере и клиенте.

Чем это плохо


  • не работает на проектах сложнее "hello world", которые требуют работы с динамически загружаемым контентом, управлением очередями запросов, websocket подписками на обновления данных;
  • удорожает разработку, т.к. не работает из коробки, по факту все равно требуется дополнительно разбираться с серверным кодом;
  • удорожает поддержку и масштабирование, т.к. требуется управлять и обслуживать веб-сервера.

Prerender.io


Что это такое


Это сервис с открытым исходным кодом, который позволяет организовать перенаправление трафика от краулеров на специальный браузер, который выполняет javascript код и вернет статическую html страницу. В качестве браузера используется PhantomJS.


Чем это хорошо


  • open-source (можно развернуть у себя и не платить за Cloud решение, на деле получается дороже);
  • работает для сложных проектов;
  • умеет правильно отдавать 404, 301 из <meta name="prerender-status-code" content="404"> (https://prerender.io/documentation/best-practices);
  • снижает затраты на разработку (требуется только frontend);
  • снижает затраты на поддержку (frontend можно раздавать с cdn, как набор статики).

Чем это плохо


  • платный;
  • медленный на сложных проектах. Краулеры часто не дожидаются ответа. Причем, если умный краулер google через некоторое время попробует еще раз получить содержимое страницы, то пользователь социальной сети, который хотел поделиться со своими друзьями интересным контентом вашего сайта и недождался ответа, потерян навсегда.
  • на сложных проектах краулеры почти всегда получают cached pages. Т.е. почти всегда получают старую информацию и со второго раза.
  • иногда требует дополнительных усилий от разработки;
  • если что-то не работает, очень трудно отлаживать;
  • регулярная переиндексация страниц для cache создает дополнительную нагрузку на backend;
  • требует наличия web server для интеграции.

Способы интеграции


Предлагает множество однотипных интеграций для разных фрейморков и веб серверов. Они заключаются в проксировании трафика от краулеров на prerender.io (если в заголовке запросов UserAgent соответствует краулеру или в параметрах запроса есть _escaped_fragment_). Остальной трафик отдается в обычном режиме (набор статики).


Renderjs.io


Что это такое


Cloud based сервис, который работает аналогично prerender.io, но работает быстро, не использует cache, использует последнюю версию Chromium.


Как это работает


После первой загрузки SPA приложения в современных браузерах работают очень быстро. Для отрисовки новой страницы обычно требуется всего несколько запросов. Renderjs.io — сервис, который делает это для браузеров. Для рендеринга используется Chromium browser. При первом обращении краулера в настоящем, реальном Chromium открывается закладка с веб приложением. Эта закладка не закрывается долгое время. При обращении по новому url не происходит полной загрузки всего, а лишь pushState в уже загруженное приложение. Таким образом рендеринг работает очень быстро и очень легко отлаживать, если у вас в Chromium работает — работает и на Renderjs.io.


Чем это хорошо


  • работает для сложных проектов;
  • умеет правильно отдавать 404, 301 из <meta name="status-code" content="404">;
  • снижает затраты на разработку (требуется только frontend);
  • снижает затраты на поддержку (frontend можно раздавать с cdn, как набор статики);
  • работает быстро;
  • для рендеринга использует Chromium;
  • не использует cache — страницы всегда содержат актуальную информацию;
  • позволяет подключиться за 5 минут используя DNS интеграцию.

Чем это плохо


  • не open-source;
  • работает только внутри приложения. Т.к. для смены url используется history.pushState то выход за границы приложения работать не будет.

Способы интеграции


Интеграция при помощи middleware аналогична prerender.io.


Интеграция при помощи DNS записи. При этом способе интеграции проект перенаправляет весь свой трафик на cdn.renderjs.io и получает полноценную обработку трафика от краулеров через рендер сервис, а остальной трафик на свой веб сервис. Этот способ позволяет небольшим проектам за 5 минут сделать свой SPA доступным для поисковых систем и заниматься более важными делами.


Выполните несколько простых шагов:


  1. Зарегистрируйтесь;
  2. Создайте новый проект;
  3. Заполните поля. Domain — это поле название домента (mysite.com), с которого будут приходить запросы, а поле origin — это url (обычно хостера mysite.github.io) по которому лежит ваше приложение;
  4. Создайте на вашем DNS сервисе запись CNAME mysite.com -> cdn.renderjs.io;
  5. Проверьте ваше приложение (в терминале curl http://mysite.com или в браузере view-source:http://mysite.com/?_escaped_fragment_=);
  6. Если все правильно, получите отрендеренный html.

Частые вопросы


Q: А почему не отдавать всем клиентам готовый html код?
A: По нескольким причинам:


  • без поддержки javascript клиент все-равно не сможет полноценно пользоваться приложением, так что лучше отдавать какой-нибудь fallback.html с надписью включите javascript;
  • рендеринг требует времени — это все-таки дольше, чем получить набор статики (html, js, css) с cdn.


    Q: Как индексировать закрытые разделы, которые требуют cookies?
    A: Технически это возможно, но на практике не требуется.



Выводы


Мы считаем, что для молодых проектов на начальном уровне использование renderjs.io и DNS интеграции — идеальное решение, которое позволяет одновременно получить все преимущества полноценного SPA и сосредоточиться на решении действительно важных задач, а именно создании ценности для клиента.


Новые проекты с трафиком тоже могут использовать renderjs.io с DNS интеграцией или nginx интеграцией.


Большие, успешные проекты пусть думают самостоятельно. Если есть желание бороться проблемами, которые уже решены, что ж они большие — сами знают, что делать.


О нас


purelab.io — Мы команда профессиональных разработчиков. Специализируемся на разработке высококачественных и современных веб приложений на базе ReactJS. Используем функциональное программирование. Имеем собственные решения для того, что бы делать вещи правильно. Можем помочь, проконсультировать, разработать. Пишите, будем рады.

Поделиться с друзьями
-->

Комментарии (21)


  1. vintage
    30.04.2017 12:19
    +2

    Из популярных фреймворков для SPA хочется отдельно выделить ReactJS.

    Почему вы шаблонизатор называете фреймворком?


    1. Hazrat
      30.04.2017 12:26
      +7

      может хватит уже? Чаще всего под ReactJS предполагают связку react+react-router+redux, чем не фреймворк?


      1. DexterHD
        30.04.2017 12:36
        +2

        Relay забыли и GraphQL, для полноты картины...
        Подразумевать могут что угодно, а по факту ReactJS это View библиотека. Нужно называть вещи своими именами, иначе все будут говорить на разных языках.


      1. vintage
        30.04.2017 12:53
        +4

        Чаще всего ЦементЖС подразумевает связку Цемент+Железо+Вода. Чем не каркас здания?


    1. Hazrat
      30.04.2017 12:32
      +1

      А вот тут ты сам упомянул ReactJS как фреймворк:

      Сколько нужно времени, чтобы просто вывести на экран большой список, используя современные фреймворки?

      и ниже reactjs
      https://habrahabr.ru/post/311172/


      1. vintage
        30.04.2017 12:56

        Спасибо, поправил.


    1. OnYourLips
      30.04.2017 17:39

      Потому что в современной разработке эти понятия давно смешались: фреймворк — это всего лишь связка библиотек с опциональным скелетом. И пересечение этих понятий огромное.


      1. vintage
        30.04.2017 17:44
        +1

        О том и речь, что когда говорят "у нас проект на Реакте" — никогда не знаешь звязка каких именно библиотек имеется ввиду и в какую архитектуру они связаны.


  1. DexterHD
    30.04.2017 12:49
    +2

    Изоморфный рендеринг
    Чем это плохо
    не работает на проектах сложнее «hello world»

    Это не правда, работает и на приложениях сложнее Hello world

    … работы с динамически загружаемым контентом, управлением очередями запросов, websocket подписками на обновления данных;

    Если эти вещи мешают рендерить где бы то ни было, значит у вас проблема с архитектурой приложения, потому что все эти вещи прямого отношения к рендерингу как таковому не имеют. Рендерится HTML код, с пустым состоянием что на фронте что на бэке. А потом это состояние заполняется из хранилища (store). И потом уже это все отдается клиенту. То как вы заполните хранилище, это уже другой вопрос. На бэке вы как правило генерится заполненый store и через props передается полное состояние всего приложения, потом это все отдается на фронт. Да и вообще весь этот изоморфный рендеринг по сути ни чем не отличается от классической схемы применяемой в web разработке хз с каких времен. Поменялись только языки, библиотеки и некоторые принципы проектирования. Но все это базируется на технологиях существующих десятилетиями, поэтому концептуально с точки зрения рендеринга PHP + Smarty так или иначе равно Node.js + ReactJS. Просто и в первом и во втором случае возникают немного разные проблемы. Но это ни как не влияет на все те технологии поверх которых все это работает.

    В Renderjs.io в минусы первым пунктом жирным шрифтом нужно записать:
    Cloud based сервис...


    1. yury_egorenkov
      01.05.2017 14:20

      Трудности с изоморфным рендерингом у нас возникали начиная от отсутствия совместимой с браузером версии XMLHttpRequest в nodejs, необходимостью адаптироваться к jsdom (там много чего нет), необходимостью
      эмулировать то, что есть в браузере, например определение гео позиции и т.д.

      У нас такая схема, вьюшки, которые попадают во viewport браузера клиента рендерят заглушки и подписываются на данные, когда поступают данные — реакт заменяет заглушки данными. Пробовали изоморфно — просто не получилось. Возможно, вы более удачливы.

      В любом случае, спасибо за комментарий.

      Cloud based — возможно, как минус. Однако для маленьких проектов, прототипов, бережливых стартапов и т.д. это скорее плюс. Я бы не хотел делать то, что уже сделано. Но это мое мнение.

      В любом случае, спасибо за комментарий.


      1. vintage
        01.05.2017 14:27

        XMLHttpRequest же есть в jsdom вроде.


  1. napa3um
    30.04.2017 12:58
    +2

    > В 2015 году Google официально отказался от поддержки выполнения javascript кода на своей стороне (https://webmasters.googleblog.com/2015/10/deprecating-our-ajax-crawling-scheme.html).

    Гугл отказался от старой схемы, требующей от вебмастеров организации специальных урлов (_escaped_fragment_) для динамического (AJAX) контента. Теперь вебмастерам не нужно специальным образом шаманить, чтобы их SPA/PWA был видимым для пауков — пауки умеют в клиентский JS и сами. И это написано по приведённой вами же ссылке.


    1. catanfa
      30.04.2017 14:11

      По ссылке из поста написано, что Гугл замечательно индексирует SPA самостоятельно, никакие дополнительные сервисы не нужны для этого. yury_egorenkov что вы на это скажите?


      1. vintage
        30.04.2017 14:28
        +1

        Кроме Гугла есть и другие не столь продвинутые поисковики.


        1. ainu
          01.05.2017 00:33

          Видимо, не пробовали.
          ВТБ 24(не имею никакого отношения ни прямого ни косвенно) как раз такой пример client-only сайта. Яндекс, Гугл, бинг, мейл — все индексируются.



        1. napa3um
          01.05.2017 10:46

          Замечание касалось исключительно поисковика от Гугла.


      1. yury_egorenkov
        01.05.2017 14:12

        Они там хотят, что бы route был сделан через #!.. Если вы сделаете обычный — выполняться-индексироваться не будет. Мы делали большой магазин на SPA, мучались сначала с гуглом, потом с prerender.io — не получилось работать нормально. Возможно, кто-то более удачливый. Кроме того, соц. сети (fb, vk, twitter) и т.д. не выполняют js, что тоже весьма грустно. Хотелось бы, что бы все работало из коробки и никаких дополнительных приспособлений не требовалось.


        1. vintage
          01.05.2017 14:16

          Так а зачем вам "обычный"? Чем "#!" не угодил?


          1. yury_egorenkov
            01.05.2017 14:25

            Мне хотелось бы # в урле — скролл до раздела. Ну и почище урлы, попривычнее, более читаемые.


            1. vintage
              01.05.2017 14:30

              Ну то есть сами себе создали проблемы ради так себе чистоты. Наверняка ещё и с кешированием огребли.