【Gatsby】iframelyを使うためにやったこと

01-05-2021

以前投稿していたブログでよく使っていたiframelyを Gatsby でも使おうとしたが、同じ要領では表示されなかった

今回は Gatsby でiframelyを使うために調べたこと、やったことについてまとめる

iframely とは?

iframelyは一言でいうと、SNS やブログなどの共有時に使うHTML の埋め込みコードを簡単に取得するためのサービス

このサービスを使うことで便利になるのは以下の点

  • HTML の埋め込みコードを取得するのが簡単になる
  • 埋め込みコード未対応のサイトでも取得できるケースが多い
  • サービスに登録すると、文字色は背景色がカスタムできる(ただし、カスタマイズされた埋め込みコードは1000 リクエスト/月まで)

iframelyが提供する基本機能で十分な場合は、基本的に無料で利用ができる

iframely UI

サイトにて、上記の画像のように URL を入力して REFRESH をクリックすると、埋め込みコードとプレビューが表示される

問題だったこと

あとは、ブログに埋め込みコードを配置することで外部コンテンツへのリンクが使えるはずだが、実際はプレビューが表示されなかった

公式ドキュメントの説明によると React のように仮想 DOM を使う場合、素の状態では embed 機能が使えない

React has its own virtual DOM and doesn’t execute (eval) any inline scripts that go with HTML elements you add.

正確には、HTML 要素と一緒に書かれたインラインスクリプトを React が危険な HTML と判断して、実行をしないとのこと

Even when you use dangerouslySetInnerHTML. Even if that “dangerous” HTML is actually trusted to be safe. React considers that you expose yourself to the risks of out-of-sync virtual DOM.

解決策

注意事項

本記事はgatsby-starter-blogから生成していることを前提にしている
また、記事ではReactの関数コンポーネントでの実装を想定している

やることはシンプルで、iframely で提供しているグローバル CDN を headタグ に配置することで、解決できる
ただ、React で headタグmetaタグ を操作するためのライブラリを使う必要がある
これに関してはgatsby-starter-blogですでに使われているreact-helmetを使うことで実現できる

では、公式ドキュメントCDN スクリプト配置の例が載っている gistを参考に以下のように実装する

まず、今回の実装で使うファイルは以下の通り

src
├── components
│   ︙
│   └── iframely.js ※新規生成
└── templates
    └── blog-post.js (headに)

components/iframely.js を新規作成し、iframely の CDN スクリプトをコンポーネントで定義する

import React, { useEffect } from "react"
import { Helmet } from "react-helmet"

const Iframely = () => {
  // 古い記事に遷移したときにもCDNがロードされるように、rendering後loadする
  useEffect(() => {
    if (window && window.iframely) {
      window.iframely.load()
    }
  }, [])

  return (
    <Helmet>
      <script type="text/javascript" src="https://cdn.iframe.ly/embed.js" />
    </Helmet>
  )
}

export default Iframely

templates/blog-post.jsIframely を配置する

import React from "react"
import { Link, graphql } from "gatsby"

import Bio from "../components/bio"
import Layout from "../components/layout"
import SEO from "../components/seo"
/* ここ */
import Iframely from "../components/iframely"

const BlogPostTemplate = ({ data, location }) => {
  const post = data.markdownRemark
  const siteTitle = data.site.siteMetadata?.title || `Title`
  const { previous, next } = data

  return (
    <Layout location={location} title={siteTitle}>
      /* ここ */
      <Iframely />
      <SEO
        title={post.frontmatter.title}

上記のコードの修正/追加に加え、iframelyで生成した埋め込み用コードを貼り付けるたびに 1 点修正が必要になる

  • embed.jsの埋め込みを削除

    • iframely 専用のコンポーネント(components/iframely.js)で読み込むため

      // 埋め込みコード
      <div class="iframely-embed">
        <div
          class="iframely-responsive"
          style="height: 140px; padding-bottom: 0;"
        >
          <a
            href="https://expfrom.me"
            data-iframely-url="//cdn.iframe.ly/tn9cRBk"
          ></a>
        </div>
      </div>
      <!-- ココを削除 -->
      <script async src="//cdn.iframe.ly/embed.js" charset="utf-8"></script>

上記の設定をすることで、以下のようにiframelyの HTML の埋め込みコードが表示される

まとめ

jekyllで作ったブログでは、HTML の埋め込みコードがそのまま使えたが、React 製の静的ウェブサイトだと工夫が必要になることがわかった

実装時の手順や参照ページに関してはinouetakumonさんの記事が大変参考になった

余談だけど、素の状態の React で埋め込みコードを簡単に使いたい場合、react-embedというパッケージがあるので、これを使うのもいいかもしれない


カモ
普段はエンジニアをやっていて、たまに旅人になりたい カモ