Astro上でReactによるインタラクティブなコンポーネント:Link Cardを呼び出す
はじめに
このポストでは、ReactコンポーネントでのLink Cardの作成方法とAstro上での呼び出し方を記載していきます。 なお、Link Cardとは下のようなものとして指しています。
Link Cardコンポーネントの実装
Reactを統合する
Astroは様々なUIフレームワークに対応していますが、デフォルトでは統合されていないため利用することができません。 そこでまずは、AstroにReactを導入するところから始める必要があるかもしれません。 その場合は、rootディレクトリで以下のコマンドを実行します。 このコマンドを実行することで、Reactを利用するための最小限の準備がすべて整います。
$ yarn astro add react
Componentを実装する
上で下準備が完了したので実際にコンポーネントを実装していきます。実装の全体像はGitHubリポジトリをご確認ください。 ここでは、要点に絞っていきたいと思います。
対象URLのOGP情報を取得する
以下のコードはOGP情報を取得している部分に絞ったコードの記載になっています。
基本的な考え方としては、まず対象となるURLのHTMLを取得します。
次にhead
内のmeta
要素を探し出して、OGPに関わる属性であるpropertry
とcontent
を抽出しています。
const LinkCard = (props: LinkCardProps) => {
const { url } = props
const [ogpMap, setOgpMap] = useState<Map<string, string>>()
useEffect(() => {
const fetchMetaData = (async () => {
const response = await fetch(new URL(url))
const html = await response.text()
return new DOMParser().parseFromString(html, 'text/html')
})()
fetchMetaData.then((document) => {
const map = new Map<string, string>()
document.querySelector('head')?.querySelectorAll('meta').forEach((element) => {
const property = element.attributes.getNamedItem('property')
const content = element.attributes.getNamedItem('content')
if (property && property.value.includes('og:') && content) {
map.set(property.value, content.value)
}
})
setOgpMap(map)
}).catch((error) => {
console.log('Failed to fetch head: ', error)
return
})
}, [props])
... // ここからは下は描画要素が記載されています。
}
ここで取得できたogpMap
を利用してコンポーネントの要素を記述するのですが、その実装部分は単純なところだと思うので割愛します。
コンポーネントの呼び出し
AstroファイルやMDXファイルでこのコンポーネントを呼び出すためには、次のコードのようにclient:*
ディレクティブを利用する必要があります。
<LinkCard url="https://docs.astro.build/ja/basics/layouts/" client:load />
詳しくは、以下の公式ドキュメントをご覧ください。
さいごに
いかがでしたでしょうか。今回のLink Cardは突貫で作成した感が否めません。OGPの取得ロジックも甘いですし、Xの独自対応も行っていません。 個人的には、せっかくAstroを利用しているのにこのLink Cardコンポーネントはクライアントサイドで描画されている点です。 ここのあたりをもう少し深堀りしてみたいと思いました。