Настало время поприветствовать Хабрахабр от имени стартапа Ecoisme!

Администрация уже давненько предоставила стартаперский аккаунт для нашей компании, а мы взамен пообещали рассказывать обо всяких интересных штуках, которые у себя используем.

Сегодня расскажем о том, как делаем лэндинги (посадочные страницы).
Мы используем те вещи, которые большинство разработчиков пока не используют, но которые здорово облегчают жизнь нам и могут облегчить другим.

В чём суть


Лэндинги делаются для привлечения целевой аудитории с целью объяснить потенциальным клиентам что к чему и вызвать у них желание выполнить целевое действие (подписаться, купить что-то).

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

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

Впоследствии проб и экспериментов появилось несколько устойчивых правил, которые у нас работают очень хорошо, и чем мы решили поделиться.

Сервер отдает только контент


Имеется ввиду, что HTML, возвращаемый сервером, не имеет практически ничего общего с тем, как контент будет отображаться.

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

<article is="cs-indiegogo-benefits" id="benefits">
	<h1>Our benefits</h1>
	<picture>
		<source srcset="/components/modules/Indiegogo/includes/img/benefits-1-mobile.jpg" media="(max-width: 1100px)">
		<img src="/components/modules/Indiegogo/includes/img/benefits-1.jpg" alt="Benefits">
	</picture>
	<picture>
		<source srcset="/components/modules/Indiegogo/includes/img/benefits-2-mobile.jpg" media="(max-width: 1100px)">
		<img src="/components/modules/Indiegogo/includes/img/benefits-2.jpg" alt="Benefits">
	</picture>
	<picture>
		<source srcset="/components/modules/Indiegogo/includes/img/benefits-3-mobile.jpg" media="(max-width: 1100px)">
		<img src="/components/modules/Indiegogo/includes/img/benefits-3.jpg" alt="Benefits">
	</picture>
	<dl>
		<dt>Appliance Detection</dt>
		<dd>Ecoisme detects all devices in your home and shows you statistics of their usage</dd>
		<dt>Personalized Tips</dt>
		<dd>Get clear and specific tips, based on usage of your home appliances</dd>
		<dt>Integration with smart devices</dt>
		<dd>Having smart devices like NEST or WeMo, make them smarter with Ecoisme</dd>
	</dl>
</article>

Веб-компоненты отображают контент согласно дизайну


Поскольку наш контент с внешним видом имеет мало общего — веб-компоненты берут на себя всю работу по графическому представлению и позволяют вытворять на странице всё, что придет в голову дизайнера.

Для удобства используются Polymer-элементы, которые наследуют системные <header>, <article> и подобные.
Веб-компонент для кода выше состоит из двух частей:

<polymer-element name="cs-indiegogo-benefits" extends="article" noscript>
	<template>
		<link rel="stylesheet" href="style.css">
		<div>
			<content></content>
		</div>
	</template>
</polymer-element>

и немного стилей (на самом деле с учётом мобильной версии не так уж и мало), получается в итоге красивый блок:



В данном случае всё просто, весь контент целиком, как есть, попадает внутрь, но иногда контент разбивается на части и вставляется поэлементно:

<polymer-element name="cs-indiegogo-header" extends="header">
	<template>
		<link rel="stylesheet" href="style.css">
		<div horizontal layout center wrap>
			<a href="/">
				<content select="picture"></content>
			</a>
			<div flex></div>
			<img id="menu" src="/components/modules/Indiegogo/includes/html/cs-indiegogo-header/menu.png" on-tap="{{menu_toggle}}">
			<content select="ul"></content>
			<button id="subscribe" target="#main">Subscribe</button>
		</div>
	</template>
	<script src="script.js"></script>
</polymer-element>


Адаптивность


Адаптивность для лэндинга тоже важна, к примеру, на Ecoisme 45% посетителей заходят с мобильных устройств, и в подавляющем большинстве это смартфоны, а не планшеты.

Поскольку контент у нас отдельно, а внешний вид отдельно — контент должен быть адаптивным. Подключаем полифилл для тэга <picture> и используем адаптивные изображения:

<picture>
	<source srcset="/components/modules/Indiegogo/includes/img/benefits-1-mobile.jpg" media="(max-width: 1100px)">
	<img src="/components/modules/Indiegogo/includes/img/benefits-1.jpg" alt="Benefits">
</picture>

На самом деле — это все изменения контента.
Остальные изменения происходят внутри веб-компонента — меняется порядок и размещение элементов, полностью перестраивается макет страницы:



Удобство поддержки


Поскольку веб-компоненты сами по себе обычно небольшие и являются автономной самодостаточной частью странички, поддерживать их проще, не нужно придумывать сложную систему именования классов (здесь мы передаем привет БЭМ), уровней вложенности минимум, один компонент не мешает своими стилями другому.

Подобные страницы и их части


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

Некоторые компоненты похожи, по не совсем одинаковы — тут можно настраивать веб-компонент с помощью атрибутов, либо наследовать компонент и переопределять некоторые стили/функциональность.
В функциональной части нашего сайта мы используем эти возможности для графиков:





Эти графики — очень похожи и в основном отличаются внешне тем, что имеют разный цвет, а под капотом в виде атрибута передается id устройства, потребление которого нужно показать, ну и загружаются соответствующие данные.

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

Возникающие трудности и нюансы


В связи с тем, что веб-компоненты и тэг <picture> ещё не поддерживаются из коробки всеми браузерами, приходится использовать полифилы.

В начале использования (около года назад) в них было некоторое количество неприятных багов, часть из которых приходилось исправлять и отправлять патчи разработчикам.

К счастью, на данный момент все баги, которые мешали, давно исправлены, и никаких неудобств больше не возникает.
Так же для полноценного использования нужно хорошенько разобраться с тем, как работает Shadow DOM, поскольку практически всё находится в нём.

И ещё — jQuery понятия не имеет о теневых деревьях (некоторые важные исправления уже доступны в Git версии jQuery), так что пользоваться можно, но нужно понимать где и как, то есть процент VanillaJS будет гораздо больше:)

Заключение


В результате, создание нового лэндинга занимает около одного рабочего дня одного человека, что весьма неплохо. А создание похожего лэндинга, если отличия небольшие, возможно в течении одного-двух рабочих часов.

Посмотреть вживую можно на нашем сайте, не стесняйтесь поковырять страничку инспектором и отладчиком, расскажите нам, что думаете.

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


  1. Zenitchik
    19.05.2015 17:08
    +1

    А у нас сервер отдаёт JSON, а отрисовкой и клиентским поведением ведает толстый клиент.


    1. nazarpc Автор
      19.05.2015 17:22

      Тоже вариант, мы проводим эксперименты с JSON-LD для данных, но на лэндингах пока не используем.


      1. firya
        20.05.2015 12:20

        А почему? Честно говоря начиная статью только эта мысль и пришла в голову, вы же используете html, который по сути xml
        Плюсы от jsona:

        1. Меньше весит
        2. Легче работа с данными
        3. Легче парсить на стороне клиента

        Минусов не нахожу вовсе


        1. nazarpc Автор
          20.05.2015 12:25

          Есть ещё такой нюанс как видимость поисковыми машинами)
          HTML они хорошо видят, JSON-LD видят, но нужно выбрать правильную структуру и убедиться что она правильно понимается поисковыми системами. В продакшен пока такое не выкатываем, но есть в планах.


          1. firya
            20.05.2015 16:46

            Я так и не понял, что именно заставляет вас генерировать страницу на стороне пользователя?


            1. nazarpc Автор
              20.05.2015 21:20

              Так на много проще и удобнее, попробуйте — увидите почему и на сколько.


              1. sashabeep
                25.05.2015 11:38


  1. corax
    19.05.2015 18:04

    уменьшаю, увеличиваю окно по ширине и всё едет :(


    1. nazarpc Автор
      19.05.2015 18:13

      Макет расчитан на ширину 1100px+, при меньшем размере он переключается в мобильную версию. У вас некоторые изображения переключились, а некоторые нет. Не подскажете что за браузер и его версия?


      1. corax
        19.05.2015 18:17


        1. nazarpc Автор
          19.05.2015 18:37

          Какой-то очередной баг Safari, он почему-то не выходит с мобильного режима при растяжении экрана, точнее выходит, но как-то не до конца.
          Разберемся, поправим, спасибо что сообщили!


  1. aalebedev
    19.05.2015 18:50

    Я всегда ценил лэндинги за скорость. У вас быстро, но уделить время оптимизации стоит:
    — объединение JS
    — объединение CSS
    — спрайты
    — минификация HTML кода.
    Кеширование не нужно, так как у вас мало возвращающихся пользователей.

    Да и методы которые вы используете медленнее, чем генерация HTML на сервере.


    1. nazarpc Автор
      19.05.2015 19:03

      Минификация HTML кода сомнительна, остальное присутствует в полной мере (даже объединение веб-компонентов, что Facebook называет Vulcanization), по-моему это уже само собой разумеется в современном вебе, HTTP/2 ведь ещё не пришел повсеместно)

      Да, наши методы медленнее генерации на сервере, но гибкость и скорость разработки это компенсирует с лихвой.

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

      Кеширование не нужно, так как у вас мало возвращающихся пользователей.

      Вынужден не согласиться, во-первых кэширование не мешает, а во-вторых благодаря тому что раздачей кэшированной статики занимается CDN, получается выгодно и полезно как нам, так и посетителю сайта. Банально быстрее загрузка страницы и меньше нагрузка на наш сервер.


  1. meta4
    19.05.2015 19:40
    +7

    К сожалению не понял, почему для относительно неинтерактивного контента (лэндинг) удобнее использовать шаблонизацию на стороне клиента?


  1. mgremlin
    20.05.2015 16:39

    при ресайзе браузера горизонтальный скролл присутствует почти всегда.
    Строка логотипов сливается, часть вылезает за вьюпорт.
    Хромиум@linux.

    По сути — примитивный html мне кажется лучше 8-)
    Как-то звучит диссонансом: с одной стороны — «с минимально необходимым количеством тэгов», с другой — полтора метра и более 4 секунд на статическую страничку…


    1. nazarpc Автор
      20.05.2015 21:18

      при ресайзе браузера горизонтальный скролл присутствует почти всегда.

      Да, есть такое (впечатление складывается что vw единицы считаются не корректно и не учитывают появившийся вертикальный скролл), при этом на реальном телефоне баг отсутствует. Страница делалась из предположения, что пользователи имеют экран на десктопе как минимум 1200px

      По сути — примитивный html мне кажется лучше 8-)

      Так там и есть обычный HTML, принципиально ничего нового, просто поделено на логические переиспользуемые кусочки

      Как-то звучит диссонансом: с одной стороны — «с минимально необходимым количеством тэгов», с другой — полтора метра и более 4 секунд на статическую страничку…

      Отнюдь, большую часть из «полтора метра» это растровая графика и кастомные шрифты, от который никуда не деться. Сами веб-компоненты без картинок — это пару кибибайт в gzip


  1. wdmaster
    25.05.2015 05:55

    У меня минут 5 страница белая и курсор ожидания. FF.


    1. nazarpc Автор
      25.05.2015 12:27

      В ответ я могу только спросить:
      * версия?
      * ошибки в консоли браузера?
      * работает ли в безопасном режиме (без расширений)?

      Все проверенные версии от стабильной до Nightly работают отлично.