Gastby - Geração de miniaturas por contexto
Otimizando as imagens de thumbnail das postagens
No momento de estruturar os artigos costumo usar uma imagem para ilustrar, com direitos de uso permitido encontradas no Google Imagens ou WikiCommons, quando compartilhada nas redes sociais ela aparece juntamente com o título e descrição, como neste exemplo do twitter
Podemos fazer melhor a imagem não é o objetivo, diferente do Instagram ou outras redes sociais, temos de dar mais destaque o título, descrição e entre outras que fazem mais sentido
Gerei essa imagem para substituir a anterior
Solução
Existem plugins como o Gatsby Plugin: Open Graph Images que possuem problemas e está quebrando para algumas versões do Gatsby, depois vou investigar o motivo e fazer um Pull Request de correção
Nesse meio tempo resolvi criar minha própria solução me baseando no plugin, até para entender como deve funcionar
Gerando a página
Criei um template com o nome open-graph-image
, onde o elemento com o conteúdo adicionei atributo div="ogimage"
, dentro do gatsby-node.js
gerei as páginas dentro do caminho do /__generated
com o slug
da página
createPage({
path: `/__generated${node.fields.slug}`,
component: path.resolve(`src/templates/open-graph-image.jsx`),
context: {
slug: node.fields.slug,
},
})
Juntamente as outras páginas deve ser acessível quando gerada para produção ou em modelo de desenvolvimento pelo endereço /__generated/<slug do artigo>/index.html
Transformando em imagem
Depois de pronto, criei uma automação para tirar uma screenshot, para isso também precisei fazer o serviço funcionar dentro com as bibliotecas puppeteer
e express
npm install puppeteer express --save-dev
# or
yarn add puppeteer express -D
E gerando com arquivo get-open-graphic-images.js
com o conteúdo abaixo, alterando o script de build
para gatsby build && node get-open-graphic-images.js
const puppeteer = require("puppeteer")
const express = require("express")
const fs = require("fs")
const http = require("http")
async function getImage(servingUrl, page, slug) {
await page.goto(`${servingUrl}__generated/${slug}/index.html`, {
waitUntil: "networkidle0",
})
const elementThumbnail = await page.$("#ogimage")
await elementThumbnail.screenshot({
path: `./public/ogimages/${slug}.jpg`,
})
console.log(`get OpenGraphImage ${slug}`)
}
// Gerar os Open Graphics Images
async function navigateOpenGraphic() {
// Gerar pastas de origem para as imagens
if (!fs.existsSync("./public/ogimages")) {
fs.mkdirSync("./public/ogimages")
}
// Pegar caminhos gerados
const slugs = []
fs.readdir("./public/__generated", (_, files) => {
files.forEach((file) => slugs.push(file))
})
// Servir os arquivos index.html
const app = express()
app.use(express.static("public"))
const server = http.createServer(app)
await server.listen(0)
const servingUrl = `http://0.0.0.0:${server.address().port}/`
// Crawler das imagens
const browser = await puppeteer.launch({ headless: "new" })
const page = await browser.newPage()
for (const slug of slugs) {
await getImage(servingUrl, page, slug)
}
// Fechar o navegador e servidor
await browser.close()
await server.close((err) => {
console.log("OpenGraph server closed")
process.exit(err ? 1 : 0)
})
}
navigateOpenGraphic()
Depois foi atualizar o das metatags com os caminhos novos, como no exemplo
<meta
name="image"
property="og:image"
itemprop="image"
content="<url do sitem>/ogimages/<slug do artigo>.jpg"
/>