以前の記事の今後やっていきたいことにもあげていた外部リンクの見た目を良くするためにRichLinkコンポーネントを作成しました。
使い方
<RichLink href="https://www.deg84.com/create-sitemap-with-gatsby/" />
解説
レンダリング時に取得しようとするとCORS(Cross-Origin Resource Sharing)の対策が必要なのでgatsby-node.jsでビルド時に情報を取得しておきます。
基本的にはOGPの内容を取得します。設定がない場合はmetaなどの情報から取得するようにしてみました。
取得するURLの一覧はYAMLで別途管理しておきます。
gatsby-node.js
exports.onCreateNode = async ({ node, actions, getNode }) => {const { createNodeField } = actions// 中略if (node.internal.type === 'LinksYaml') {const data = {url: node.url,domain: url.parse(node.url).hostname,title: '',description: '',image: '',}const res = await axios.get(node.url) // axiosを使ってリクエストconst $ = cheerio.load(res.data) // 結果をcheerioでパース// urlif ($("meta[property='og:url']").attr('content'))data.url = $("meta[property='og:url']").attr('content')else if (res.request.res.responseUrl) {data.url = res.request.res.responseUrl}// domaindata.domain = url.parse(data.url).hostname// titleif ($("meta[property='og:title']").attr('content}'))data.title = $("meta[property='og:title']").attr('content}')else if ($('title').text()) {data.title = $('title').text()}// descriptionif ($("meta[property='og:description']").attr('content'))data.description = $("meta[property='og:description']").attr('content')else if ($("meta[name='description']").attr('content')) {data.description = $("meta[name='description']").attr('content')}// imageif ($("meta[property='og:image']").attr('content'))data.image = $("meta[property='og:image']").attr('content')else if ($("meta[name='image']").attr('content')) {data.image = $("meta[name='image']").attr('content')}// GraphQLで取得できるようにfieldsに入れるcreateNodeField({ name: 'url', node, value: data.url })createNodeField({ name: 'domain', node, value: data.domain })createNodeField({ name: 'title', node, value: data.title })createNodeField({ name: 'description', node, value: data.description })createNodeField({ name: 'image', node, value: data.image })}}
出力結果
おわりに
はじめはogp-parserを使おうと思ったんですがインストール上手くいかなかったので、Axiosとcheerioでやってみることにしました。
ちなみにrequest npmは現在非推奨になっているので要注意です。