Хабрахабр

Генератор статических сайтов metalsmith

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

  • Прототип web-интерфейса
  • Блог с редко обновляемым контентом
  • Отдельная статическая часть другого web-приложения
  • Сайт-визитка или landing-page
  • Онлайн-документация

Более подробный сравнительный анализ различных генераторов можно найти в этой статье, а также посмотреть рейтинг, основанный на активности соответствующих проектов на github. Мы же рассмотрим хоть и не самый популярный, но, тем не менее, элегантный и простой представитель данного класса инструментов — metalsmith.

Metalsmith

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

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

function plugin() ;
}

Хотя, если вам необходимо (например для отладки), вы можете воспользоваться моим плагином — metalsmith-inspect-files, который визуализирует дерево файлов и каталогов в момент своего использования в цепочке плагинов.

Делаем простой блог

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

const Metalsmith = require('metalsmith');
const timer = require('./plugins/timer');
const jade = require('metalsmith-jade');
const layouts = require('metalsmith-layouts');
const permalinks = require('metalsmith-permalinks');
const collections = require('metalsmith-collections');
const less = require('metalsmith-less');
const ignore = require('metalsmith-ignore');
const cleanCss = require('metalsmith-clean-css');
const metalsmithInspectFiles = require('metalsmith-inspect-files');
const partial = require('metalsmith-partial'); Metalsmith(__dirname) .source('./source') .metadata({ // глобальные переменные доступные в каждом шаблоне title: 'Example blog', layout: 'index.jade', menuLinks: [ {title:'Home', url: '/'}, {title:'Articles', url: '/articles/'}, {title:'About', url: '/about/'} ] }) .destination('./build') .clean(true) .use(collections({ // коллекции страниц определяемые шаблоном articles: { pattern: [ 'articles/**', '!articles/index.jade' ], sortBy: 'title' }, })) .use(partial({ // шаблоны вставки внутри других шаблонов directory: './partials', engine: 'jade' })) .use(jade({ // шаблонизатор useMetadata: true })) .use(permalinks({ // красивые url /about.html => /about/index.html relative: false })) .use(layouts({ // шаблон-каркас одинаковый для всех страниц engine: 'jade', default: 'index.jade', pattern: '**/*.html' })) .use(less()) // компиляция less в css .use(cleanCss()) // сжатие css .use(ignore([ // фильтрация файлов '**/*.less' ])) .use(metalsmithInspectFiles()) .build((err, files) => { if (err) { throw err; } timer('Build time: ')(); });

Наш блог состоит из нескольких отдельных обособленных страниц и одной коллекции однотипных страниц. Структура исходных директорий (без внешних директорий layouts и partials):

|-articles | |-article-one.jade | |-article-three.jade | |-article-two.jade | -index.jade |-assets | |-images | | -favicon.png | |-js | | -turbolinks.min.js | -stylesheets | -main.less |-about.jade -index.jade

А так выглядит результат работы(содержимое папочки build):

|-about | -index.html |-articles | |-article-one | | -index.html | |-article-three | | -index.html | |-article-two | | -index.html | -index.html |-assets | |-images | | -favicon.png | |-js | | -turbolinks.min.js | -stylesheets | -main.css -index.html

Сразу заметно работу плагина metalsmith-permalinks, который преобразует файлы *.html, чье имя отлично от index.html, в соответствующие директории с index.html, для того, чтобы url этих страниц выглядел более приятно. Основными особенностями любого генератора статических сайтов являются шаблоны (layouts и partials), как средство для соблюдения принципа DRY(Don't repeat yourself). В качестве языка шаблонизации использован jade(или pug), популярный среди представителей javascript-коммьюнити. Так в нашем случае выглядит основной layout, представляющий каркас страницы:

doctype html
html head meta(charset='utf-8') meta(name='description' content='Simple metalsmith blog') meta(name='viewport' content='width=device-width, initial-scale=1.0') title=title link(href='/assets/stylesheets/main.css', rel='stylesheet') link(rel="icon" href="/assets/images/favicon.png") body .container nav!=partial('menu.jade', {menuLinks, currentPath: path}) section.page-content!=contents footer!=partial('footer.jade') script(src='/assets/js/turbolinks.min.js')

Он в свою очередь использует шаблоны-вставки (partials), функциональность которых реализуется плагином metalsmith-partial (обратите внимание на явную передачу переменных для отрисовки шаблона). Включаемый шаблон меню выглядит следующим образом:

ul.menu each page in menuLinks - isActive = ('/'+currentPath+'/').startsWith(page.url) && (page.url != '/' || page.url === currentPath + '/') li(class=(isActive ? 'active' : '')) a(href=page.url)=page.title

Для итерации по страницам коллекции (articles) используется плагин metalsmith-collections, сами страницы для генерации списка доступны в переменной-массиве с именем коллекции.

Turbolinks

Библиотека turbolinks позволяет 'оживить' содержимое, отдаваемое сервером со статикой, добавив SPA-поведение при переходе по ссылкам внутри нашего сайта, загружая посредством AJAX содержимое каждой новой страницы и заменяя им текущее. В случае, если по какой-то причине запрос оказался долгим (более 500мс), будет показан progress-bar, который сообщит пользователю о том, что переход на другую страницу происходит (стандартные средства, с помощью которых браузер показывает это при обыкновенном переходе по ссылке, не будут задействованы по причине отсутствия перезагрузки страницы), хотя и медленно. Turbolinks в данном примере подключается в виде минифицированного файла-дистрибутива, так сказать «for the sake of simplicity». В случае, если javascript-часть сайта не такая простая, следует использовать что-то в духе metalsmith-webpack-2 или gulp-metalsmith.

Полезные ссылки и выводы

Несмотря на то, что metalsmith не самый популярный из генераторов, на мой взгляд, он заслуживает внимания, потому как прост и гибок (практически любой сторонний инструмент может быть внедрен в plugin-pipeline с помощью нескольких строк кода), а значит, может быть использован для создания различных сайтов, хотя, безусловно, он не является 'серебряной пулей' и имеет свои недостатки. Например у большинства плагинов, отсутствует детальная документация поэтому для того, чтобы понять детали их работы, частенько приходится изучать исходники, благо они почти всегда являются простыми фасадом, предназначенным для адаптации других популярных инструментов с хорошей документацией под metalsmith plugin-API.

Теги
Показать больше

Похожие статьи

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»
Закрыть