以前投稿していたブログでよく使っていたiframelyを Gatsby でも使おうとしたが、同じ要領では表示されなかった
今回は Gatsby でiframelyを使うために調べたこと、やったことについてまとめる
iframely とは?
iframelyは一言でいうと、SNS やブログなどの共有時に使うHTML の埋め込みコードを簡単に取得するためのサービス
このサービスを使うことで便利になるのは以下の点
- HTML の埋め込みコードを取得するのが簡単になる
- 埋め込みコード未対応のサイトでも取得できるケースが多い
- サービスに登録すると、文字色は背景色がカスタムできる(ただし、カスタマイズされた埋め込みコードは1000 リクエスト/月まで)
iframelyが提供する基本機能で十分な場合は、基本的に無料で利用ができる
サイトにて、上記の画像のように 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.js
に Iframely
を配置する
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というパッケージがあるので、これを使うのもいいかもしれない