Предыдущие статьи
- Блог на 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 <-- Вы тут
Привет, в этой короткой заметке расскажу, как я прикрутил разные картинки к микроразметке своего блога. В пятой части серии (Блог на Gatsby и Obsidian ч.5) статей о создании с нуля своего блога на Gatsby я описывал создание темплейтов и одним из полей темплейтов было поле seoImage.
Предполагалось, что именно в этом поле я буду самостоятельно указывать картинку, которая затем будет прорастать в компонент SEO, который был написан в части #4 (Блог на Gatsby + Obsidian from scratch ч.4)
Но я понял, что я очень ленив, чтобы вручную указывать путь к картинке, к тому же такой способ обязал бы меня копировать изображения, в папку public, ведь во время сборки изображение копируется в папку static и путь к нему меняется.
Вообще, для чего нужна микроразметка ? Микроразметка на сайте нужна для того, чтобы помочь поисковым системам, таким как Google, лучше понимать структуру и содержание страницы. Плюс, во время шеринга ссылок на ваш блог в социальных сетях, при правильной разметке, люди будут видеть корректное превью с картинкой, заголовком и описанием, считаю, что этого достаточно, чтобы немного заморочиться на этот счет 😁
Решение
Я подумал, ведь в большинстве заметок, я и так указываю изображение в тексте и почему бы не использовать первое изображение в статье, как изображение для микроразметки.
Но парсить html в поисках тега img не очень хотелось. Я заметил, что можно вытащить из graphql не только итоговый html, но и ast деверо для html, с такой структурой довольно легко работать
Чтобы вытащить astHtml нужно просто добавить это поле в запрос в src/templates/BlogPost.js
export const query = graphql`
query BlogPageQuery($slug: String!) {
markdownRemark(fields: {slug: {eq: $slug}}) {
html
htmlAst <== Вот тут!
excerpt
frontmatter {
date
stage
}
fields {
title
}
}
}
`Само содержимое htmlAst выглядит примерно так:
// Примерная структура ast дерева для поста
const htmlAst = {
type: 'root',
children: [
{
type: 'element',
tagName: 'p',
properties: {
...
},
children: [
{
type: 'element',
tagName: 'img',
properties: {
...,
src: '/path/to/image' // <== Поле, которое нам нужно
},
children: [
...
]
}
]
}
]
}Как видно из примера это довольно понятная рекурсивная структура, из которой мы легко сможем вытащить необходимое поле, функция которая этим занимается у меня получилась такая (оставил ее в том же файле src/templates/BlogPost.js):
// src/templates/BlogPost.js
function findFirstImage(astNode) {
if (astNode?.type === 'element' && astNode?.tagName === 'img') {
return astNode.properties.src;
}
let imgSrc = null;
let i = 0;
while (astNode && typeof astNode?.children?.[i] === 'object') {
imgSrc = findFirstImage(astNode.children[i]);
if (imgSrc) {
break;
}
i++;
}
return imgSrc;
}
export const Head = (props) => {
const { markdownRemark } = props.data;
const { excerpt, fields, htmlAst } = markdownRemark;
const { title } = fields;
return (
<SEO
image={findFirstImage(htmlAst)} // <== Добавил в компонент SEO дополнительное поле
title={title}
description={excerpt}
/>
)
}Готово, теперь в теге <head /> в метатегах image и twitter:image будут подходящие картинки! Теперь после публикации обновленной версии блога можно увидеть результат, если переслать кому-нибудь ссылку на статью. Было бы очень здорово, если бы и эту статью кому-нибудь переслали и она оказалась полезной 😁






