Gatsby.jsでTwitter Cardが表示されなくて苦悩した件
TOC
この記事が役に立つ可能性がある方
この記事をご覧になられているということは、Twitter CardやFacebook Shareが意図した表示にならずお困りになられている方かと思います。 本記事はエラーとなる原因を、全て網羅している記事ではありません。 以下の条件に合致された方は、これから書く内容を試していただくと解決する可能性がありますので、是非試してみてください。
- Twitter Card validatorで
No card found (Card error)
となってしまう - cssをjsからimportしてGatsbyアプリケーションのスタイリングを行っている
Twitter Card validatorでTwitter Cardが表示されない
react helmetを使用してmetaタグを正しく設置しているのに、Card validatorでエラーが発生していました。
Helmetタグ使用方法や、プラグインの見直しを行っても一向に表示されず、諦めかけていました・・・。
metaタグの上にinline styleが多数ある場合表示されない
でもどうしても納得がいかず永遠とGoogleさんとにらめっこをしていたところ、とあるGatsby公式リポジトリのIssueを見つけました。
https://github.com/gatsbyjs/gatsby/issues/22908
この中でやりとりされているコメントをみるとどうやら、<head>
タグ内に多数のインラインスタイルがあり、その後にogpやtwitter:cardの<meta>
タグが設定されていると、上手く表示されない模様。
Twitter CardやFacebookのシェアリンクは、パブリックサーバーでホスティングされているWebページをスクレイプし、その中の<meta>
タグを検知し表示しているらしいく、そのスクレイピングが恐らく<head>
タグ内の最初の数KBしか読み取らないため、エラーとなってしまうということでした。
このブログのスタイリングはtailwindやmarkdownなどのcssファイルをgatsby-browser.js
でimportしているため、<head>
タグ内に大量のインラインスタイルが定義されていました。
この大量のインラインスタイルと、ogp関連の<meta>
タグの順序を入れえれば、スクレイピング時<meta>
タグ取得してくれて、上手く表示してくれそうです。
上記のIssueに修正の参考となるリンクが貼ってあったので、そのまま拝借したいと思います。
gatsby-ssr.js
はbuild時に実行したい処理を記述する事ができます。
詳しいAPIなどは公式ドキュメントに書かれているので割愛しますが、今回は<head>
内のコンポーネントを取得するgetHeadComponents
と、<head>
内のコンポーネントを渡したオブジェクトに置換するreplaceHeadComponents
を使って、<head>
内のタグの順番を入れ替えたいと思います。
getHeadComponents
で取得した中身を見てみると、配列の中に各コンポーネントのオブジェクトが格納されているのがわかります。
[
{
'$$typeof': Symbol(react.element),
type: 'style',
key: null,
ref: null,
props: {
'data-href': '/styles.a868d7354fa00a91b7b8.css',
dangerouslySetInnerHTML: [Object]
},
_owner: null
},
{
'$$typeof': Symbol(react.element),
type: 'meta',
key: 'generator-2.24.91',
ref: null,
props: { name: 'generator', content: 'Gatsby 2.24.91' },
_owner: null
},
{
'$$typeof': Symbol(react.element),
type: 'title',
key: 'Gatsby.jsでTwitter Cardが表示されなくて苦悩した件',
ref: null,
props: {
'data-react-helmet': true,
children: 'Gatsby.jsでTwitter Cardが表示されなくて苦悩した件'
},
_owner: null
},
.
.
.
]
このオブジェクト内のtype: 'style'
に対しソートを実行し、<head>
内タグ
の順番を入れ替えます。
exports.onPreRenderHTML = function onPreRenderHTML({
getHeadComponents,
replaceHeadComponents,
}) {
const headComponents = getHeadComponents();
headComponents.sort((a, b) => {
if (a.type === b.type || (a.type !== 'style' && b.type !== 'style')) {
return 0;
}
if (a.type === 'style') {
return 1;
} else if (b.type === 'style') {
return -1;
}
return 0;
});
replaceHeadComponents(headComponents);
};
この記述を追記し、$ gatsby build
を実行すると、各<style>
タグが<head>
タグの後ろに来るようソートされます。
再度Card validatorを使い、正常に表示されるか確認してみましょう。
無事表示されるようになりました!
まとめ
今回エラーを吐き続けていた原因は、React Helmetやgatsby-plugin-react-helmetの設定ミスなどはなく、TwitterやFacebookのリンクを生成する仕組みに対しての理解が不足していた事でした。
SNSリンクなど業務で全く扱わない為、個人ブログを始めたおかげで知識が1つ増えました。
あまりいないとは思いますが、同様の事象でお困りの方は是非今一度<head>
タグ内を見直してみてください。