gatsby-starter-blogをカスタムする。今回は投稿記事を簡単にsnsで共有できるようにボタンを設置し、共有時の情報を設定する
必要なのはreact-share
というもの
$ yarn add react-share
共有ボタンを設置するのは投稿記事にする
src/templates/blog-post.jsを編集していく
追加する部分は生地とフッターの間に、
graphqlのsiteMetadataにsiteUrl項目
import * as React from "react"
import { Link, graphql } from "gatsby"
import _ from "lodash"
import Bio from "../components/bio"
import Layout from "../components/layout"
import Seo from "../components/seo"
import ShareSns from "../components/share-sns"
const BlogPostTemplate = ({ data, location }) => {
const post = data.markdownRemark
const siteTitle = data.site.siteMetadata?.title || `Title`
const { previous, next } = data
return (
...
<section
dangerouslySetInnerHTML={{ __html: post.html }}
itemProp="articleBody"
/>
{/* 日本語を含むためエンコードする */}
<ShareSns title={post.frontmatter.title} url={encodeURI(`${data.site.siteMetadata?.siteUrl}${post.fields.slug}${post.frontmatter.title}`)} />
<hr />
<footer>
<Bio />
</footer>
...
export const pageQuery = graphql`
query BlogPostBySlug(
$id: String!
$previousPostId: String
$nextPostId: String
) {
site {
siteMetadata {
title
siteUrl
}
}
...
ShareSnsコンポーネントは
import React from 'react'
import styled from '@emotion/styled'
import {
FacebookIcon,
FacebookShareButton,
HatenaIcon,
HatenaShareButton,
LineIcon,
LineShareButton,
TwitterIcon,
TwitterShareButton
} from 'react-share'
const Wrapper = styled.div`
display: flex;
padding-bottom: 24px;
`
const ButtonWrapper = styled.div`
padding-right: 12px;
`
const ShareSns = ({title, url}) => {
return (
<Wrapper>
<ButtonWrapper>
<FacebookShareButton url={url}>
<FacebookIcon size={40} round />
</FacebookShareButton>
</ButtonWrapper>
<ButtonWrapper>
<LineShareButton url={url} >
<LineIcon size={40} round />
</LineShareButton>
</ButtonWrapper>
<ButtonWrapper>
<TwitterShareButton title={title} url={url} >
<TwitterIcon size={40} round />
</TwitterShareButton>
</ButtonWrapper>
<ButtonWrapper>
<HatenaShareButton url={url} >
<HatenaIcon size={40} round />
</HatenaShareButton>
</ButtonWrapper>
</Wrapper>
)
}
export default ShareSns
表示させると
OGPとは「Open Graph Protcol」の略で、FacebookやTwitterなどのSNSでシェアした際に、設定したWEBページのタイトルやイメージ画像、詳細などを正しく伝えるためのhtml要素
react-helmet
がパッケージに入っていないのならインストールする。
gatsby-starter-blogには初めから入っていて設定もある程度してある
画像の設定はしていないので今回は画像設定をする
import * as React from "react"
import PropTypes from "prop-types"
import { Helmet } from "react-helmet"
import { useStaticQuery, graphql } from "gatsby"
import defaultOgpImage from "../images/default-ogp-image.png";
const Seo = ({ description, lang, meta, title, image}) => {
const { site } = useStaticQuery(
graphql`
query {
site {
siteMetadata {
title
siteUrl
description
social {
twitter
}
}
}
}
`
)
const metaDescription = description || site.siteMetadata.description
const defaultTitle = site.siteMetadata?.title
const ogpImage = image ? `${site.siteMetadata.siteUrl}${image.images.fallback.src}` : `${site.siteMetadata.siteUrl}${defaultOgpImage}`
return (
<Helmet
htmlAttributes={{
lang,
}}
title={title}
titleTemplate={defaultTitle ? `%s | ${defaultTitle}` : null}
meta={[
{
name: `description`,
content: metaDescription,
},
{
property: `og:title`,
content: title,
},
{
property: `og:description`,
content: metaDescription,
},
{
property: `og:image`,
content: ogpImage,
},
{
property: `og:type`,
content: `website`,
},
{
name: `twitter:card`,
content: `summary_large_image`,
},
{
name: `twitter:creator`,
content: site.siteMetadata?.social?.twitter || ``,
},
{
name: `twitter:title`,
content: title,
},
{
name: `twitter:description`,
content: metaDescription,
},
{
property: `twitter:image`,
content: ogpImage,
},
].concat(meta)}
/>
)
}
Seo.defaultProps = {
lang: `jp`,
meta: [],
description: ``,
}
Seo.propTypes = {
description: PropTypes.string,
lang: PropTypes.string,
meta: PropTypes.arrayOf(PropTypes.object),
title: PropTypes.string.isRequired,
}
export default Seo
Seoコンポーネントにimageの引数を持たせるようにし、そのimageを
const ogpImage = image ? `${site.siteMetadata.siteUrl}${image.images.fallback.src}` : `${site.siteMetadata.siteUrl}${defaultOgpImage}`
絶対パスに変換し
{
property: `og:image`,
content: ogpImage,
},
セットする
{
name: `twitter:card`,
content: `summary_large_image`,
},
contentをsummary_large_image
にする。summary
だと小さい画像になる
これでシェア投稿に画像がつく
インデックスページでは画像がつくけど、ブログページではメタタグが見つからないとなってしまう。。
ブラウザで確認してもメタタグはついている。。謎
URLが長すぎるとダメ?短いURLならうまくいった
参考 :