Как создавать и развертывать статические веб-сайты с помощью Metalsmith

Сегодня я расскажу о своем процессе создания и развертывания статических веб-сайтов с помощью Metalsmith, генератора статических сайтов для NodeJS.

Статический веб-сайт подходит для различных проектов, таких как:

  • Блоги
  • Техническая документация
  • электронные книги
  • Небольшие сайты

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

Недавно я использовал Metalsmith для создания сайта документации для Bedrock и остался доволен процессом разработки. Вот скриншот сайта:

Стоит рассказать, как я его построил, поскольку не думаю, что многие люди использовали Metalsmith. Это хорошая альтернатива Jekyll, чрезвычайно популярному генератору статических сайтов, написанному на Ruby.

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

Вот что мы рассмотрим:

  • Как работает Metalsmith
  • Настройка проекта
  • Написание с использованием Markdown
  • Использование макетов и партиалов
  • Автоматическое оглавление и навигация
  • Подсветка синтаксиса
  • Разработка и Live Reload
  • Однострочное развертывание на Github Pages

Клонировать образец сайта на GitHub

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

Хорошо, а теперь поговорим о том, как я это построил.

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

Металлизм работает следующим образом:

  1. Требуется набор статических файлов из исходного каталога
  2. Применяет к ним набор преобразований.
  3. Он перемещает преобразованные файлы в целевой каталог.

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

Например, вот как выглядит мой build.js. Прочтите комментарии, чтобы понять трансформации.

var Metalsmith = require('metalsmith'),
    metallic = require('metalsmith-metallic'),
    drafts = require('metalsmith-drafts'),
    layouts = require('metalsmith-layouts'),
    markdown = require('metalsmith-markdown'),
    assets = require('metalsmith-assets'),
    collections = require('metalsmith-collections'),
    autotoc = require('metalsmith-autotoc'),
    browserSync = require('browser-sync'),
    argv = require('minimist')(process.argv);
// If I run node run deploy --prod, it should not use browser-sync to watch for changes.
// Otherwise, it should.
if (!argv.deploy) {
    browserSync({
        server: 'build',
        files: ['src/*.md', 'layouts/*.html', 'assets/*.css'],
        middleware: function (req, res, next) {
            build(next);
        }
    })
}
else {
    build(function () {
        console.log('Done building.');
    })
}
function build (callback) {
Metalsmith(__dirname)
        // This is the source directory
        .source('./src')
// This is where I want to build my files to
        .destination('./build')
// Clean the build directory before running any plugins
        .clean(true)
// Use the drafts plugin
        .use(drafts())
// Use metallic plugin to add syntax highlighting
        .use(metallic())
// Use Github Flavored Markdown for content
        .use(markdown({
            smartypants: true,
            gfm: true,
            tables: true
        }))
// Generate a table of contents JSON for every heading.
        .use(autotoc({
            selector:"h2, h3, h4, h5, h6",
            headerIdPrefix: "subhead"
        }))
// Group my content into 4 distinct collections. These collection names
        // are defined as `collection: <name>` inside the markdown YAML.
        .use(collections({
            "Get Started": {"sortBy": "date"},
            "Tutorials": {"sortBy": "date"},
            "User Authentication": {"sortBy": "date"},
            "Building with React & Flux": {"sortBy": "date"}
        }))
// Use handlebars as layout engine.
        .use(layouts('handlebars'))
// Use the assets plugin to specify where assets are stored
        .use(assets({
            source: './assets',
            destination: './assets'
        }))
// Build everything!
        .build(function (err) {
            var message = err ? err : 'Build complete';
            console.log(message);
            callback();
        });
}

Мы создаем файлы, запустив node build.js из командной строки.

Эти преобразования определяются разработчиком и передаются всему сообществу как плагины. Все эти плагины являются модулями npm. Для создания статического сайта Bedrock я использовал следующие плагины.

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

Выполните следующую команду, чтобы установить все это в свое приложение:

npm i metalsmith-assets metalsmith-autotoc metalsmith-collections metalsmith-drafts metalsmith-layouts metalsmith-markdown metalsmith-metallic browser-sync --save-dev

Настройка проекта

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

assets: В этом каталоге хранятся файлы CSS и JavaScript.

build: Содержимое этого каталога создается сборкой Metalsmith.

layouts: Здесь хранятся шаблоны макетов. Я использовал Handlebars в качестве движка компоновки. Подробнее о макетах и ​​шаблонах ниже.

src: Здесь размещается весь контент сайта. Контент записывается в уценке с помощью тегов YAML. Модуль metalmith-collections группирует файлы в коллекции и автоматически отображает их на панели навигации верхнего уровня.

build.js: Это файл сборки Metalsmith, описанный выше.

deploy.sh: это сценарий оболочки, который развертывает содержимое моего каталога build / на Github Pages. Подробнее читайте в разделе Развертывание ниже.

Все остальное довольно понятно.

Написание с использованием Markdown

Страницы написаны с использованием Markdown и хранятся в каталоге src /. Над каждым файлом уценки есть содержимое YAML. Вот фрагмент одного из них:

---
title: Building with React & Flux
draft: false
collection: Building with React & Flux
layout: layout.html
date: 2016-12-28
autotoc: true
---
Bedrock ships with React, React Router and Flux. This allows you to start using React components inside your web application. Let's walk through an example of how to use React and Flux to build client-side

YAML вверху определяет некоторые переменные, которые используются различными плагинами.

  • title: Преобразуется в переменную {{title}}, доступную в файле макета.
  • draft: Используется плагином metalmith-drafts, чтобы указать, черновик это или нет.
  • collection: Используется плагином metalmith-collections для определения коллекции, к которой принадлежит этот файл.
  • layout: указывает макет для этого файла.
  • date: Используется плагином metalmith-collections для сортировки файлов в коллекции по дате.
  • autotoc: указывает, должно ли создаваться автоматическое оглавление. Используется плагином Metalsmith-autotoc.

Эти файлы уценки будут преобразованы в файлы HTML посредством преобразований, указанных в build.js выше.

Использование макетов и частей

Макеты предоставляются через плагин metalmith-layout. Он поддерживает множество различных механизмов компоновки.

Для использования определите механизм компоновки в build.js:

...
.use(layouts('handlebars'))
...

Metalsmith определяет используемый шаблон макета на основе ключа макета YAML. Вот как выглядит мой файл layout.html. Вы заметите, что там определены несколько переменных YAML. Переменная {{{contents}}} будет заполнена содержимым файла Markdown.

Я не использовал partials для этого проекта, но вы можете использовать для него плагин metalmith-partial.

Навигация и содержание

В файле макета проекта есть несколько интересных фрагментов, на которые стоит обратить внимание. Первый - это перебор коллекций.

<nav class="navigation-nav">
    {{#each collections}}
         <a class="navigation-nav-item" href="{{this.0.path}}">{{@key}}</a>
    {{/each}}
</nav>

Плагин Metalsmith-collections генерирует объект коллекции, который я использую здесь для создания динамической навигации верхнего уровня. Вот фрагмент в build.js:

// Group my content into 4 distinct collections. These collection names
// are defined as `collection: <name>` inside the markdown YAML.
.use(collections({
    "Get Started": {"sortBy": "date"},
    "Tutorials": {"sortBy": "date"},
    "User Authentication": {"sortBy": "date"},
    "Building with React & Flux": {"sortBy": "date"}
}))

Далее идет код для оглавления.

{{#if toc}}
    <section class="toc sticky">
        {{#each toc}}
            <a class="toc-item" href="#{{id}}">{{text}}</a>
        {{/each}}
     </section>
{{/if}}

Не все страницы будут иметь оглавление, но если оно есть, плагин Metalsmith-autotoc предоставит массив для создания связанного оглавления.

{{#if toc}}
    <section class="toc sticky">
        {{#each toc}}
            <a class="toc-item" href="#{{id}}">{{text}}</a>
        {{/each}}
     </section>
{{/if}}

Подсветка синтаксиса

Подсветка синтаксиса важна для сайтов документации. К счастью, это действительно легко добавить с помощью плагина metalmith-metallic.

...
// Use metallic plugin to add syntax highlighting
.use(metallic())
...

Убедитесь, что вы применили это преобразование, прежде чем преобразовывать разметку в HTML. Поскольку подсветка синтаксиса выполняется с помощью Highlight.js, вам также необходимо добавить соответствующий файл темы подсветки синтаксиса. Я добавил в тему Atom Dark.

<link rel=”stylesheet” href=”https://highlightjs.org/static/demo/styles/atom-one-dark.css">

После этого вы можете писать фрагменты кода в Markdown.

Разработка и Live Reload

При разработке своего сайта запустите

node build.js

Это запустит сервер синхронизации браузера, который будет автоматически искать изменения в каталогах src/, assets/ и layouts/ . Когда произойдут изменения, он перестроит Metalsmith и перезагрузит страницу.

Я предпочитаю синхронизацию браузера, а не metalmith-watch, у которого есть проблемы с восстановлением кодовой базы, когда ему приходится прослушивать несколько каталогов.

Развертывание на страницах Github

Когда все будет готово к выпуску, вы можете развернуть его на Github Pages, выполнив:

node run deploy --prod

Это запустит сценарий оболочки внутри ./deploy.sh. Сценарий выполнит отправку из build/ каталога проекта в origin/gh-pages. Я получил этот сценарий оболочки из репозитория Metalsmith-gh-pages-deploy.

Первоначально опубликовано на сайте nodewebapps.com 15 января 2017 г. Автор: Тило Митра.