Генераторы статических сайтов стремительно становятся важной частью инструментария при профессиональной разработке сайтов. Новые генераторы появляются практически каждую неделю. И выбрать для использования один из них становится все сложнее.

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

В этой статье будет более детальный обзор четырех популярных генераторов: Jekyll, Middleman, Roots, Hugo. Этот обзор должен дать вам стартовую точку в выборе генератора, подходящего для вашего проекта. 4 отобранных движка отражают различные актуальные на данный момент тренды.

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

Jekyll

Ни одна статья о генераторах статических сайтов сейчас не обходится без упоминания Jekyll.

Мы бы не говорили сейчас о возрождении статических сайтов, если бы основатель GitHub Том Престон-Вернер не решил в октябре 2008 года написать свой движок для блога, сидя со стаканом яблочного сидра в своих апартаментах в Сан Франциско.

Результатом стал Jekyll — “простой, готовый для ведения блога генератор статического сайта”.

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

  1. Берете простой HTML-макет блога.
  2. Выносите все повторяющиеся хедеры, футеры, меню и т.д. в отдельные фрагменты шаблонов.
  3. Переводите все страницы и записи в блоге в Markdown, после чего отправляете их содержимое в шаблоны.

Также в Jekyll есть встроенный локальный сервер, отслеживающий изменения в файлах и генерирующий HTML, CSS и JavaScript из шаблонов, текстов в Markdown, файлов Sass или CoffeeScript.

Jekyll был первым генератором статических сайтов, представившим концепцию “вводной части” — способа добавления метаданных в шаблоны или файлы markdown. Вводная состоит из небольшого количества данных в формате YAML в начале каждого файла, отделенных тремя дефисами (---) с конца и с начала:

---
title: A blog post
date: 2014-09-01
tags: ["meta", "yaml"]
---

# Blogpost with meta data

This is a short example of a Markdown document with meta data as front matter.

Движок шаблонов

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

С одной стороны это делает шаблоны более простыми и декларативными, кроме того в Liquid есть хороший набор фильтров и хелперов “из коробки”.

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

Liqud позволяет вам использовать переменные в шаблонах, используя распространенный синтаксис с двойными фигурными скобками:

{{ some_variable }}

Блоки с тегами выглядят так:

{% ifsome_variable %} Show this {% endif %}

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

{{ some_variable | default: 'Default Value' }}

Поэтому на данный момент в коде шаблонов практически любого сайта на Jekyll вы обнаружите нагромождения неуклюжих операторов if и else.

Контентная модель

Контентная модель в Jekyll значительно эволюционировала с момента создания.

Сейчас содержимое можно сохранять в различных форматах и задавать ему разное поведение.

Простейшая форма отдельного документа это Markdown или HTML. Этот документ конвертируется в соответствующую страницу HTML при сборке. В документе задается макет, который будет использоваться для создания HTML-страницы, а также метаданные, к которым движок шаблонов имеет доступ через переменную page.

В Jekyll реализована отдельная обработка каталога _posts, в котором располагаются файлы в формате Markdown, именованные по схеме yyyy-mm-dd-title-of-the-post.md. Посты обрабатываются как записи блога.

С версии 2.0 Jekyll поддерживает коллекции. Коллекция это каталог с документами Markdown. У вас есть доступ к коллекциям в шаблонах через переменную site.collections, вы можете задать сборку каждого документа в коллекции как отдельной страницы.

Последняя форма содержимого это файлы с данными. Они сохраняются в каталоге _data и могут быть в форматах YAML, JSON or CSV. И все эти данные доступны во всех шаблонах через переменную site.data.

Система управления ресурсами

Обработка ресурсов в Jekyll реализована предельно просто. Также как и в случае с минималистичным шаблонизатором Liquid, здесь есть хорошее и плохое. В Jekyll нет встроенной поддержки LiveReload, минификации или связывания ресурсов, однако Sass и CoffeeScript работают без дополнительной настройки. Любой файл с расширением .sass, .scss или .coffee и вводной в формате YAML будет обработан и конвертирован в соответствующий файл .css или .js в итоговом статическом сайте.

Это значит, что для обработки файла CoffeeScript к нему надо добавить лишь вводную:

---
---

alert "Hello from CoffeeScript"

Учтите, что отделяющие вводную дефисы могут не понравится подсветчику синтаксиса вашего редактора.

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

Образец сайта

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

Внешний вид страницы документации Jekyll

Внешний вид страницы документации Jekyll. (увеличенная версия)

Итак, как все это сделано.

Основная структура сайта задана в файле шаблона layouts/default.html. В нем есть два подключаемых фрагмента _includes/header.html и _includes/footer.html. В хедере вбито навигационное меню — в Jekyll нет способа выбрать набор страниц и пройти по ним циклом, обычно ссылки в навигационное меню добавляются вручную.

Каждая страница документации это файл Markdown в каталоге _docs/. Страницы используют удобную возможность Jekyll вкладывать макеты — им задан шаблон _layouts/docs.htm, использующий в свою очередь шаблон _layouts/default.html.

Боковая колонка сгенерирована из данных _data/docs.yml, размещающих различные файлы в группы, каждую со своим названием.

Расширения Jekyll

Jekyll легко расширяется и для него уже написано сравнительно много плагинов. Самый простой способ расширить Jekyll — это добавить файл Ruby в каталог _plugins. Существует 5 типов плагинов: генераторы, конвертеры, команды, теги и фильтры.

Как упоминалось ранее, шаблонизатор Liquid не позволяет включать код Ruby в шаблоны. Это ограничение обходится за счет добавления своих тегов и фильтров.

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

Команды позволяют добавлять новые возможности к интерфейсу командной строки Jekyll.

Выводы

Jekyll широко используется и начиная с версии 2, его контентная модель достаточно развита для поддержки сайтов, более сложных, чем простой блог. В большом проекте вы, скорее всего, столкнетесь с ограничениями встроенной системы управления ресурсами и перейдете на Gulp or Grunt. Liquid это надежный и проверенный шаблонизатор, но он может показаться ограничивающим. Как только вам потребуются более сложные манипуляции с контентом, вам придется писать собственные плагины.

Middleman

Middleman существует примерно столько же как и Jekyll. Он так и не получил такого широкого распространения как Jekyll (пришедший к успеху за счет интеграции с GitHub), но стал основой для сайтов известных в мире веб-дизайна компаний: сайты MailChimp, Nest и Simple построены на Middleman.

сайты MailChimp, Nest и Simple построены на Middleman. Сайты MailChimp, Nest и Simple построены на Middleman.

Это успешный проект с открытым кодом, в котором участвует более сотни разработчиков. Лидер проекта — Томас Рейнольдс, технический директор компании из Портленда ‘Instrument’.

И если Jekyll создавался как легкий и простой движок для генерации статического блога, Middleman это фреймворк для продвинутых сайтов для маркетинга и документации. Это мощный инструмент, простой для тех, кто знаком с Ruby On Rails.

Движок шаблонов

Целью создателя Middleman было создание аналога Ruby on Rails для генерации статических сайтов. Также как Rails, в Middleman по умолчанию используется стандартный шаблонизатор Ruby ERB, но его всегда можно заменить на Haml или Liquid.

ERB это простой движок шаблонов, позволяющий вам свободно использовать код Ruby в ваших шаблонах без ограничений. Он намного мощнее Liquid, но требует больше дисциплины от разработчика, потому что его возможности позволяют написать весь код прямо в шаблонах.

Система управления ресурсами

Несколько лет стабильной версией Middleman была 3. Но уже вышла бета 4-ой версии, которая внесет изменения в контентную модель и в управление ресурсами.

Ядро контентной модели Middleman это sitemap — файл со списком всех файлов проекта, называемых “ресурсы” в терминологии Middleman.

У каждого ресурса есть source_file(источник) и destination_file(назначение), через которые ресурс трансформируется при сборке сайта.

Простой файл-источник source/about/index.html перейдет в файл-назначение build/about/index.html без каких-либо трансформаций. Также как и при использовании системы управления ресурсами Rails, вы можете задавать трансформации файла, указывая его расширение.

Файл source/about/index.html.erb будет обработан шаблонизатором ERB и трансформирован в build/about/index.html. А файл source/js/app.js.coffee будет распознан как CoffeeScript и скомпилирован в build/js/app.js.

Ресурсопровод построен на Sprockets, также как в Rails и это значит, что вы можете использовать “магические” комментарии в файлах JavaScript и CSS для подключения зависимостей:

//= require 'includes/test.js'

Это облегчает разделение фронтенда на небольшие модули, все зависимости разрешает Middleman.

В грядущей версии 4 представлена концепция внешнего ресурсопровода. Она позволяет Middleman при сборке управлять внешними инструментами, такими как Ember CLI и Webpack, что делает систему управления ресурсами более мощной. Это действительно удобно, использовать Middleman для запуска отдельных процессов Ember CLI и проксирования ответов серверу Ember.js .

Контентная модель

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

В текущей стабильной версии Middleman (3) есть интерфейс запросов в карте сайта, имитирующий Active Record (систему работы с базами данных в Rails), он будет удален в версии 4, с заменой на простые методы Ruby для запросов данных.

Представим, у вас есть каталог, названный source/faq. Записи FAQ сохранены в файлах в формате markdown с небольшой вводной следующего типа:

---
title: What is Middleman?
position: 1
---

Middleman is a [static website generator](https://www.staticgen.com) with all of the shortcuts and tools of modern web development.

Предположим, вам надо отправить эти записи в шаблон ERB и упорядочить их по position. Наш шаблон source/faq.html.erb будет выглядеть так:

<h1>FAQ</h1>
<% sitemap.resources
   .select { |resource| resource.path =~ /^faq\// }
   .sort_by { |resource| resource.data.position }
   .each do |resource| %>
   <h2 class="question"><%= resource.data.title %></h2>
   <div class="answer"><%= resource.render(:layout => false) %></div>
<% end %>

В четвертой версии появилась концепция коллекций, позволяющая использовать подобные фильтры в карте сайта внутри коллекции. В режиме LiveReload, Middleman мониторит файловую систему и автоматически обновляет коллекции при изменениях (собирает заново каждый файл, зависящий от них).

После того, как вы вникните в этот метод, для вас станет простым создание любой архитектуры контента для сайта. Если что-то можно собрать в статический сайт, Middleman сделает это для вас.

Также поддерживаются файлы с данными (формата YAML или JSON в каталоге data/), также как в последних версиях Jekyll.

Расширения Middleman

Middleman позволяет подключать расширения в разных точках через хуки с помощью мощного API. Это нужно не так часто как в Jekyll, потому как при свободных возможностях создавать специальные функции-хелперы, фильтровать коллекции и страницы и также при наличии шаблонизатора ERB, очень многое в Middleman доступно стандартными средствами “из коробки” и не требует расширений.

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

Roots

Как и Middleman, Roots создан агентством, использующим генератор статического сайта для работы с клиентами. Это агентство ‘Carrot’, расположено в Нью-Йорке, сейчас является частью ‘Vice media group’, руководит разработкой Roots Джефф Эскаланте.

Roots основан на Node.js. Roots основан на Node.js.

Если Middleman можно назвать статической версией Ruby on Rails, то Roots пришел из мира фронтенд инструментов, основанных на Node.js.

Roots более специализирован в сравнении с Middleman и максимально эффективен при создании сайтов на основе стандартных инструментов от Carrot.

Движок шаблонов

Roots “из коробки” поддерживает Jade, этот шаблонизатор сокращает традиционный синтаксис HTML, убирая из него все излишества; это облегчает вставку в шаблоны фрагментов JavaScript. Внешне он сильно отличается от обычного HTML, поэтому, вставка фрагментов HTML, наоборот, затруднена — их сначала надо привести к синтаксису Jade.

Вы можете переключиться на шаблонизатор EJS, реализовать поддержку других шаблонизаторов тоже вполне реально, но так как Carrot встраивает Jade в свой инструментарий, все руководства и примеры предполагают, что вы используете Jade.

Система управления ресурсами

В Roots встроена поддержка CoffeeScript и Stylus. Также как и в случае с шаблонизатором Jade, их можно заменить другими инструментами, но так как все элементы рабочего процесса в Roots настроены и взаимосвязаны, проще потратить время на их изучение.

Как было сказано, система управления ресурсами в Roots легко расширяется. Одно из расширений дает поддержку Browserify, что позволяет использовать любые библиотеки NPM на фронтенде. Также Roots поддерживает многопоточную компиляцию ресурсов. При названии файла myfile.jade.ejs он будет сначала обработан EJS, а только затем Jade.

Система управления ресурсами Roots не обладает такой экосистемой как специализированные инструменты типа Grunt, Gulp и Brunch. Но если вы не будете особо переживать по этому поводу и адаптируетесь к рабочему процессу от Carrot, вы заметите, что здесь все легко настраивается, а возможностей хватает для большинства проектов.

Контентная модель

Изначально в Roots нет никакой контентной модели. Он просто берет шаблоны из папки views/ и делает из них HTML в папке public/. При желании, в Jade легко подключать Markdown, примерно так:

extends layout

block content
   :markdown
      ## This Is Markdown

      Everything in this block will be parsed as Markdown and inserted in the content
      block within the layout.jade template.

Расширения Roots

Контентной модели в Roots нет потому, что в этом он целиком полагается на расширения и этих расширений достаточно.

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

Есть расширение Roots Dynamic Content , дающее аналог коллекций из Jekyll с вводной и содержанием в Jade. Также есть расширение Roots Posts, добавляющее коллекции в Markdown и вводной.

Расширения Records и YAML добавляют поддержку файлов с данными, которые можно использовать в любом шаблоне. Первое может даже извлекать данные из любого URL и использовать их.

Еще одно расширение для контента это Roots Contentful, Carrot писали о нем в статье Building a Static CMS. Расширение добавляет контент из Contentful API и позволяет обрабатывать его фильтрами.

Приступить к написанию расширений для Roots очень легко, в документации есть действительно хорошее введение о работе хуков. Хотя более подробная документация о внутренней работе Roots не помешала бы.

К счастью, разработчики готовы отвечать на вопросы в чате Gitter.

Hugo

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

Популярность Hugo растет быстрее всех генераторов статики Популярность Hugo растет быстрее всех генераторов статики.

Hugo написан на Go, он единственный массово популярный генератор статических сайтов, написанный статически компилируемом языке. Большинство его основных достоинств также как и основной недостаток являются следствием этого факта.

Начнем с хорошего. Hugo быстрый. Даже не то, чтобы просто быстрый, а быстрый как интернет по выделенной линии в сравнении с интернетом по dial-up.

Известный бенчмарк на Youtube показывает сборку 5000 страниц за 6 секунд, в относительных цифрах это получается в 75 раз быстрее Middleman.

Hugo также невероятно прост в установке и обновлении. Ruby и Node.js хороши, если у вас уже настроено рабочее окружение; в ином случае вам надо тратить время. Hugo предлагает исполняемые файлы для всех основных платформ — просто скачайте и запускайте, нет никаких зависимостей и процессов установки. Надо обновить? Просто скачиваете новый исполняемый файл.

Движок шаблонов

Hugo использует стандартный шаблонизатор из библиотеки Go (html/template), но также поддерживаются и два альтернативных движка шаблонов, основанных на Go — Amber и Ace.

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

В Hugo есть хорошо продуманный набор вспомогательных методов, облегчающих фильтрацию, сортировку и условное ветвление в шаблонах.

Концепции макетов, реализованной в Jekyll, Roots и Middleman здесь нет, только фрагменты.

Переменные и функции вставляются с помощью фигурных скобок:

<h1>{{ .Site.Title }}</h1>

Одним из интересных аспектов встроенного шаблонизатора является контексто-зависимость вставляемых переменных, движок всегда экранирует вывод в соответствии с контекстом. Одно и то же содержимое выводится по разному в блоке HTML, внутри атрибута HTML и внутри тега <script>.

Система управления ресурсами

Это один из основных недостатков Hugo. Вы можете работать с простым CSS и JavaScript или интегрировать внешний инструмент типа Gulp или Grunt, так как в Hugo никакой системы управления ресурсами нет.

При сборке сайта Hugo просто копирует все файлы в каталог static. Хотите Sass, EcmaScript6, автопрефиксы CSS и все такое? Вам надо настроить внешний инструмент и подключить Hugo как часть сборочного процесса (из-за необходимости этой настройки простота установки Hugo уже не кажется такой значимой).

Единственное, что есть в Hugo, это LiveReload. Если вас устраивает работа с чистым CSS и JavaScript, то можете считать, что это все, что нужно.

Расширения

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

Это значит, что вам надо опираться исключительно на встроенные возможности Hugo, а не на свои. В этом плане Hugo практически полная противоположность Roots, в котором почти весь функционал выведен в плагины.

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

Максимально близкий аналог расширений в движке Hugo это внешние хелперы, которые добавляют поддержку форматов AsciiDoc и reStructuredText. Но у этих хелперов нет никаких возможностей взаимодействовать с движком шаблонов или контентной моделью.

Контентная модель

Итак, мы разобрались с недостатками — в Hugo нет ни системы управления ресурсами, ни расширений. Теперь перейдем к плюсам.

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

Содержимое (“записи”) группируется в каталоги (“разделы”), допустима вложенность каталогов.

└── content
   ├── post
   |  ├── firstpost.md   // <- http://1.com/post/firstpost/
   |  ├── happy
   |  |   └── ness.md  // <- http://1.com/post/happy/ness/
   |  └── secondpost.md  // <- http://1.com/post/secondpost/
   └── quote
      ├── first.md       // <- http://1.com/quote/first/
      └── second.md      // <- http://1.com/quote/second/

В данном примере post, post/happy и quote это разделы, а все файлы markdown — записи. Также как и в остальных генераторах, в записях есть метаданные во вводной части; вводная может быть в формате YAML, JSON или TOML.

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

Вот сжатая версия реального сниппета из Static Web-Tech , выводящего 3 последние записи в разделе “Презентации”.

<ul class="link-list recent-posts">
   {{ range first 3 (where .Site.Pages.ByDate "Section" "presentations")}}
   <li>
      <a href="{{ .Permalink }}">{{ .Title }}</a>
      <span class="date">{{ .Params.presenter }}</span>
   </li>
   {{ end }}
</ul>

К синтаксису фильтров range и where надо привыкнуть, но он достаточно мощный.

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

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

Современная технология статических сайтов

Несмотря на то, что история статических сайтов идет с начала интернета, современные генераторы статических сайтов находятся в начале пути.

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

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

Если вы начинающий, то самый сложный вопрос это “с чего начать?”. Ответ будет зависеть прежде всего от знакомых вам языков программирования и от того, дизайнер вы или разработчик:

  • Jekyll это проверенный способ для тех, кто немного знаком с Ruby и использует Mac или Linux (экосистема Ruby не очень дружелюбна к Windows).
  • Middleman ориентирован на тех, кто привык к Rubu On Rails. Если вы свободно пишете код на Ruby, то Middleman будет лучше Jekyll на больших и сложных сайтах.
  • Roots ориентирован на фронтенд-разработчиков, знающих JavaScript и желающих разрабатывать сайты с собственным дизайном.
  • Hugo хорош тем, что не требует никаких зависимостей и готов к работе; высокая скорость сборки подходит для сайтов с большим количеством контента. Основной его недостаток — нерасширяемость.