【Astro】自動で情報を取得するリンクカードコンポーネントを作る
目次
執筆時の作業環境は以下のとおりです。
- MacOS: Sonoma 14.2.1
- Node.js: v21.6.1
- npm: v10.2.4
- Astro: v4.4.0
- open-graph-scraper: v6.5.0
はじめに
ブログの記事内に外部サイトへのリンクを貼るとき用にリンクカードを作成しました。
↓これです
Astro
Astro builds fast content sites, powerful web applications, dynamic server APIs, and everything in-between.
ビルド時にリンク先の情報を読み取ることで、画像やタイトルなどのデータを入れた状態でHTMLを生成しているので、ページロード時に毎回情報を取得するよりもパフォーマンス面で優れています。
情報を取得する方法
Open Graph Scraper をインストール
Astroのビルド時のスクリプトはNode.js上での動作なので、通常のJavaScriptのDOMPerser
インターフェイスなどは使用できません。
今回はDOMを解析するために Open Graph Scraper(以下OGS)というライブラリを使用します。
open-graph-scraper
Node.js scraper module for Open Graph and Twitter Card info. Latest version: 6.8.0, last published: 9 days ago. Start using open-graph-scraper in your project by running `npm i open-graph-scraper`. There are 66 other projects in the npm registry using open-graph-scraper.
npm i --save open-graph-scraper
OGSで情報を取得する
OGSで情報を取得する関数は以下のとおりです。関数を呼び出すときに引数に渡すURLはpropsとして受け取ります。
---
import ogs from 'open-graph-scraper'
async function getOpenGraphData(url: string) {
const options = { url }
try {
const { result } = await ogs(options)
return result
} catch (error) {
console.error('Error fetching Open Graph Data:', error)
return {}
}
}
---
取得した情報を使用する
取得した情報は、コンポーネントのテンプレート部分で使っていきます。
基本的にはpropsにはslug
というURL情報しか渡さなくてもいいのですが、必要があればcaption
にリンクのキャプションを表示できる他、title
やdescription
、image
を手動で設定することもできるようにしました。||
演算子を使うことで、手動で設定した内容が優先的に反映されるようにしています。
また、OG画像が取得できなかったときはNO IMAGE
と書かれた画像が表示されるようになっています。
---
// インポート
import ogs from 'open-graph-scraper'
import { Icon } from 'astro-icon/components'
import Noimage from '@/images/noimage_placeholder.png'
// propsの指定
interface Props {
slug: string
caption?: string
title?: string
image?: string
description?: string
}
// propsを分割代入
const { slug, caption, title, image, description } = Astro.props
// OGSで情報を取得
async function getOpenGraphData(url: string) {
const options = { url }
try {
const { result } = await ogs(options)
return result
} catch (error) {
console.error('Error fetching Open Graph Data:', error)
return {}
}
}
// 情報を変数に格納(自分でpropsにせってした場合はそれが優先される)
const websiteData = await getOpenGraphData(slug)
const ogImage = image || websiteData?.ogImage?.[0]?.url || Noimage.src
const ogTitle = title || websiteData?.ogTitle || 'タイトルの取得に失敗しました'
const ogDescription = description || websiteData?.ogDescription || ''
---
<a href={slug} target="_blank">
{caption && <p>{caption}</p>}
<div>
<div>
<img src={ogImage} alt="" />
</div>
<div>
<h1>{ogTitle}</h1>
<p>{ogDescription}</p>
</div>
<Icon name="mdi:open-in-new" width={24} height={24} />
</div>
</a>
コンポーネントを使用する
完成したコンポーネントはimport LinkCard fron 'path/to/file/LincCard.astro'
でインポートし、以下のように記述して使用します。
<LinkCard slug="https://astro.build/" caption="キャプションです" />
↓このコードで生成されるリンクカードがこちらです。
キャプションです
Astro
Astro builds fast content sites, powerful web applications, dynamic server APIs, and everything in-between.
おわり
自動で情報を取得するリンクカードのコンポーネントの作り方でした。
OGSは初めて使ったのですが、簡単にOGPデータを取得できて便利でした。画像が取得できなかったらどうするかなど、作りながら出てきた問題に逐一対処するのも楽しかったです。
以上