Reactで作ったページにTwitterCardsとOGPのメタデータを埋める

(2016-07-02)

せっかくページを作ったので、SNSにシェアするときに見栄えをよくしようと思った。

Facebookに表示される例

Twitter CardsやOGPのmetaタグを埋めるとTwitterやFacebookにURLを貼ったときに上のように表示されるようになる(上はFacebookの例)。そこで、react-helmetでこんな感じで動的に埋め込んだんだけど読んでくれない。

<Helmet title={'sambaiz.net'}
        meta={[
            {"name": "twitter:card", "content": "summary"},
            {"name": "twitter:site", "content": "@sambaiz"},
            {"name": "twitter:title", "content": "sambaiz.net"},
            {"name": "twitter:description", "content": "僕のホームページ"},
            {"property": "og:title", "content": "sambaiz.net"},
            {"property": "og:type", "content": "blog"},
            {"property": "og:image", "content": "http://d2wgaf7ubdj1mv.cloudfront.net/my.jpg"},
            {"property": "og:url", "content": "http://sambaiz.net"}
        ]}
/>

GoogleのクローラーのようにJavascriptを解釈してくれる と思ってた。残念。

しょうがないのでここだけサーバーサイドレンダリングすることにした。

'use strict'

import express from 'express'
import path from 'path'
import compression from 'compression'

require('isomorphic-fetch');

var app = express()

app.use(compression())

// serve our static stuff
app.use(express.static(path.join(__dirname, '..', '..', 'public')))

app.get('/', function (req, res) {
  res.status(200).send(page('http://sambaiz.net', 'sambaiz.net', '僕のホームページ'));
})

app.get('/article/:articleId', function (req, res) {
  fetch(`https://zx9h12n6jb.execute-api.ap-northeast-1.amazonaws.com/api/articles/${req.params.articleId}`).then(function(response){
    if (response.status == 404) {
      res.status(404).send('not found')
    }else if(response.status != 200){
      res.status(response.status).send(`API error ${response.status}`)
    }else{
      return response.json();
    }
  }).then(function(json) {
    if(json){
      res.status(200).send(page(`http://sambaiz.net${req.url}`, json.title, '書いた'));
    }
  })
})

function page(fullUrl, title, description)  {
  return `
    <!doctype html>
    <html>
      <head>
        <title>${title}</title>
        <meta charset="utf-8">
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">
        <meta name="twitter:card" content="summary">
        <meta name="twitter:site" content="@sambaiz">
        <meta name="twitter:title" content="${title}">
        <meta name="twitter:description" content="${description}">
        <meta property="og:title" content="${title}">
        <meta property="og:type" content="blog">
        <meta property="og:image" content="http://d2wgaf7ubdj1mv.cloudfront.net/my.jpg">
        <meta property="og:url" content="${fullUrl}">
      </head>
      <body>
        <div id="app"></div>
        <script src="/bundle.js"></script>
      </body>
    </html>
    `
}

var PORT = process.env.PORT || 8080

app.listen(PORT, function() {
  console.log('Production Express server running at localhost:' + PORT)
})

ちゃんと読まれているかは以下のページで確認できる。

が、結局全部サーバーサイドレンダリングすることになった。