Это продолжение серии статей:
- Блог на Gatsby + Obsidian from scratch ч.1
- Блог на Gatsby + Obsidian from scratch ч.2
- Блог на Gatsby + Obsidian from scratch ч.3
- Блог на Gatsby + Obsidian from scratch ч.4
- Блог на Gatsby и Obsidian ч.5 <-- Вы тут
- Блог на Gatsby. Rss лента ч.6
- Блог на Gatsby. Разные изображения для микроразметки ч.7
Введение
В этой статье немного причешем наш блог перед публикацией, а именно:
- Добавим в Obsidian темплейты, чтобы было меньше рутины и чтобы немного расширить наши frontmatter поля - все что касается Obsidian пункт опциональный, если вы не используете Obsidian или уже разобрались с темплейтами
- Немного поменяем структуру frontmatter (этот пункт возможно уже реализован)
- Небольшие косметические изменения:
- Добавляем футер
- Исправляем сортировку постов
- Убираем посты, работа над которыми не закончена из сборки и публикации на сайте
- Опубликуем сайт 🔥
Добавляем templates (шаблоны)
Делается это достаточно просто и быстро, но у меня сходу не завелось, как я понял потом, дело было в том, что я создавал папку для шаблонов не через интерфейс Obsidian, а через файловый менеджер.
- Создаем директорию, в которой будут храниться файлики с шаблонами - темплейты (templates).
Называем ее Templates и переходим в настройки
- В настройках выбираем Только что созданную папку
Предварительно надо убедиться в настройках Core Plugins, что template plugin включен
- Создаем в созданной папке
new notec таким содержимым
Особое внимание надо уделить полю date и его значению {{date}} - при вставке шаблона будет подставляться актуальная дата, а формат можно поменять в настройках Templates
Обновленное содержимое frontmatter
---
date: {{date}}
tags: ["oneTag"]
stage: inProgress | readyToPublish | finished
seoImage:
---Я добавил поле stage, которое может принимать три значения:
- inProgress - статья в работе
- readyToPublish - статья готова к публикации, но еще будет дополняться
- finished - статья закончена, правок не ожидается
Так мы сможем избавиться от создания страниц для недописанных статей, а для тех статей, которые еще будут дополняться - можно показывать какую-нибудь симпатичную плашку.
Еще одно поле seoImage - там будет картинка для микроразметки поста, в противном случае подставится картинка профиля. Так что это поле опционально.
Это изображение будет видно при шеринге постов в социальных сетях.
Немного косметических изменений
Футер
Расписывать особо нечего - вынес иконки из UserInfo в общие компоненты и накидал немного стилей
// components/Footer/Footer.js
import React from 'react';
import { useSiteMetadata } from '../../hooks/use-site-metadata';
import { GithubIcon, TwitterIcon } from '../Icons';
export function Footer() {
const { social: { github, twitter }, title, } = useSiteMetadata();
const currentYear = new Date().getFullYear();
return (
<footer className='bg-gray-100 py-4 mt-6'>
<div className='container mx-auto px-4'>
<div className='flex justify-center gap-4'>
<a className='w-6 h-6' href={github} target='_blank' rel='noreferrer'>
<GithubIcon />
</a>
<a href={twitter} target='_blank' rel='noreferrer'>
<TwitterIcon />
</a>
</div>
<div className='flex justify-center mt-4'>
<p className='text-indigo-500'>
© {currentYear} {title}
</p>
</div>
</div>
</footer>
);
}Далее, помещаем этот компонент на имеющиеся у нас страницы BlogList и BlogPost
import { Footer } from '../components/Footer';
// ...another code
return (
<>
<div className='container mx-auto px-4 mt-16 relative'>
...
</div>
<Footer />
<>
)Исправляем сортировку постов
Заметил досадную штуку, после того, как я поменял формат данных на тот, который мне кажется понятным и привычным (DD-MM-YYYY) стала падать сборка, а до этого сортировка работала неверно. Надо с этим что-то делать, блог с неправильной сортировкой постов - неправильный блог, мне нужен правильный 😁
Решение - нужно немного подправить файлик gatsby-node.js:
exports.onCreateNode = ({ node, actions, getNode }) => {
// ... another code
if (node.internal.type === `MarkdownRemark`) {
if (node.frontmatter.date) {
const [day, month, year] = node.frontmatter.date.split('-');
const date = new Date(`${year}-${month}-${day}`).toISOString();
node.frontmatter.date = date;
}
// ... another code То есть мы просто исправляем формат дат создания постов, приводя его к виду, который нормально сортируется YYYY-MM-DDT00:00:00.000Z
Я так до конца и не понял, что именно отвечало за сортировку, то ли сам graphql, то ли плагин gatsby-transformer-remark, но этот маленький хак помог исправить ситуацию и теперь посты отображаются в нужном формате
Убираем из сборки неготовые посты
Выше по тексту я уже говорил, что мы добавили поле stage, которое указывает на степень готовности/неготовности к публикации статьи. Теперь нужно выпилить ненужные статьи из сборки и отображения на сайте )
- Правим
gatsby-node.js, чтобы убрать сборку ненужных страниц и прокидываем stage в контекст компонентаBlogPost.js:
// gatsby-node.js
/* Делаем поле stage доступным в fields на этапе сборки */
exports.onCreateNode = ({ node, actions, getNode }) => {
if (node.internal.type === `MarkdownRemark`) {
createNodeField({
name: `stage`,
node,
value: node.frontmatter.stage,
})
// ...остальной код
/* Фильтруем посты с помощью fields.stage */
exports.createPages = async function ({ actions, graphql }) {
const { data } = await graphql(`
query {
allMarkdownRemark {
edges {
node {
fields {
slug
stage <<---- Добавляем в запрос всех страниц поле stage
}
}
}
}
}
`)
/* Добавляем фильтрацию постов */
const posts = data.allMarkdownRemark.edges
.filter(({ node }) => !(node.fields.stage || '').includes('inProgress'));
/* Пробрасываем stage в контекст */
posts.forEach((edge) => {
const { slug, title, stage } = edge.node.fields
actions.createPage({
path: slug,
component: path.resolve(process.cwd(), `src/templates/BlogPost.js`),
context: { slug, title, stage },
})
})
}- Правим
graphqlзапрос вBlogList.js- нужно добавить фильтрацию по полю stage:
// src/templates/BlogList.js
export const blogListQuery = graphql`
query BlogListQuery($skip: Int!, $limit: Int!) {
allMarkdownRemark(
sort: { frontmatter: { date: DESC }}
limit: $limit
skip: $skip
filter: {fields: {stage: {ne: "inProgress"}}} <<--- Добавляем фильтрацию
) {
// ...остальной запрос
}
}
`Теперь посты, которые находятся в работе, не будут отображаться, теперь можно переходить к публикации блога
Публикация блога
Я намеренно не рассматриваю процесс регистрации домена, настройки ssl и привязку домена к ip конкретного сервера, так как тут очень много переменных. Все зависит от того, какой у вас регистратор, хостинг или одно из облачных решений.
Предполагается что это все уже настроено, как именно настроить все перечисленное часто можно найти в документации продукта, который вы используете.
Лично я для публикации блога использую платный хостинг, который позволяет сделать все вышеописанное в одном месте.
Про подход к деплою блога
Так как для меня Obsidian является по сути CMS, в которой я создаю свои посты и посты хранятся только локально (в проекте только символьная ссылка на директорию) - я собираюсь публиковать свой бложик вручную (со своего ноутбука запускать скрипт публикации).
Такой подход как мне кажется вполне оправдан для проекта такого масштаба, тут не нужен сложный CI - так как сам блог максимально простая штука.
Понадобится подключение ssh к вашей директории, где будет храниться ваш блог. Задача просто переложить содержимое папки public после сборки в эту директорию, я буду использовать для этого scp
SCP - это аббревиатура от Secure Copy Protocol. Это утилита командной строки, которая позволяет пользователю безопасно копировать файлы и каталоги между двумя местоположениями, обычно между системами unix или Linux.
- Настраиваем подключение по ssh для вашего хостинга. Думаю разберетесь как это сделать. Тут зависит от вашей ОС, если у вас unix/linux система, то все необходимое уже скорее всего установлено, если windows - потребуется какой-то клиент, например putty (В общем в этом шаге надо погуглить)
- Создаем ssh ключ, чтобы не вводить пароль при каждой публикации блога. Если ключ уже есть или просто в кайф постоянно вводить пароль, то можете ничего не делать 😁. тут есть инструкция, как сгенерировать ssh ключ на MacOS и Linux. Дальше подразумевается, что публичная часть ключа у вас лежит по такому пути:
~/.ssh/id_rsa.pub - Копируем публичную часть ключа на удаленный сервер с помощью
ssh-copy-idПроверить наличие этой программы можно так:ssh-copy-id --versionКопируем ключ командой
ssh-copy-id -i ~/.ssh/id_rsa.pub user@remote.host- Если все сделано верно, теперь вы можете входить на ваш сервер по ssh без пароля:
ssh user@remote.host- Все, что нужно у нас есть, теперь напишем скрипт для публикации - он будет запускать сборку, после чего копировать содержимое папки
publicна наш удаленный сервер
Пишем скрипт
- Добавим парочку переменных окружения в
.env, чтобы не хранить имя пользователя и сервер для подключений и путь до блога под гитом, эти переменные динамически подставятся из окружения при подключении по ssh - об этом чуть ниже
# .env
DEPLOY_USER=username
DEPLOY_HOST=hostname
DEPLOY_PATH=/path/to/remote/blog/directory- Создадим директорию
src/scripts, положим туда файликdeploy.js:
// src/scripts/deploy.js
require('dotenv').config();
const { execSync } = require('child_process');
const deploy = () => {
const command = `scp -r public/* ${process.env.DEPLOY_USER}@${process.env.DEPLOY_HOST}:${process.env.DEPLOY_PATH}`;
const result = execSync(command, { stdio: 'inherit', encoding: 'utf8' });
console.log(result);
}
deploy();Пару слов о скрипте - мы тут используем модуль nodejs child_process, который(как понятно из названия) позволяет создавать подпроцессы, мы же с помощью метода exexSync можем написать обертку, которая позволит нам из JS кода вызывать команды, которые нам лень писать в терминале, конечно можно писать гораздо более сложные сценарии, но нас сейчас интересует только копирование файлов
Как видно, мы используем уже знакомый нам модуль dotenv, который позволяет достать из файлика .env все переменные окружения. О нем я немного писал в одной из предыдущих частей.
Суть этого скрипта в выполнении команды:
scp -r public/* sshusername@sshhost:/path/to/blogТеперь можно создать скрипт в package.json, который будет отвечать за запуск деплоя бложика:
{
"scripts": {
"deploy": "npm run build && node src/scripts/deploy"
}
}Теперь в любой момент, просто запускаем npm run deploy и обновленная версия блога в интернете через пару минут 🤘
В следующей статье добавим отображение тегов, которые у нас появились в frontmatter! До встречи!










