以前投稿していたブログでよく使っていた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というパッケージがあるので、これを使うのもいいかもしれない