Twitter・Instagram の埋め込みが重いのは万能な遅延読み込みで解決
Twitter や Instagram の投稿をフツーに記事に埋め込むと、ページの表示速度が遅くなります。 PageSpeed Insights のスコアも一気に悪化してしまいます。
原因は埋め込みコード内にある JavaScript。
なので、スクリプトを遅延読み込みさせれば Twitter・Instagram の埋め込みが重い問題は解決します。
一般的によくある遅延読み込みの方法は「最初のスクロール操作で読み込む」というものですが、この記事では Shin さんが作成された defer.js を使って、
スクロールの有無にかかわらず、設定した秒数後に読み込む
という方法を紹介します。ページスピード向上に有効です。
この方法は、スクロールをトリガーにする方法とは違って、スクリプトごとに遅延の秒数を指定できます。また、設定次第で YouTube などの遅延読み込みにも対応できるので非常におすすめです。
Twitter・Instagram の埋め込みに関しては、記事内に埋め込みがある場合のみ読み込むようにするので、埋め込みがない記事には影響しません。
今回紹介する defer.js の存在は、以下の記事にて知ることができました。ありがとうございます。
外部のJavaScriptやCSSを遅延読み込みする方法 - after work lab
目次
Twitter・Instagram 埋め込みの遅延読み込み方法
Twitter・Instagram の埋め込みは、以下の手順で遅延読み込みできます。
1.defer.js を head 内に設置
Shin さんが作成された defer.js の機能を使用します。
shinsenter/defer.js · GitHub
まずは、以下をテンプレートの<head>
~</head>
の間に設置します。
※ JetTheme を利用中の場合は、すでにテンプレートに組み込まれているため設置は不要です。
<script src="https://cdn.jsdelivr.net/npm/@shinsenter/defer.js@3.5.0/dist/defer.min.js"></script>
@3.5.0
の部分はバージョンなので、念のため上記公式ページで最新版を確認の上でご使用ください。
<body>
内に設置しても動くようですが、公式説明では<head>
内に設置となっています。自己判断で<body>
内に設置しても良いかとは思います。
この defer.js を導入することで、後述しますが Twitter・Instagram に限らずさまざまな要素を遅延できます。
2./body 直前に、遅延読み込み用コードを設置
次に、テンプレートの</body>
直前に以下のコードを設置します。
const twitterEmbed = document.getElementsByClassName('twitter-tweet');
const instaEmbed = document.getElementsByClassName('instagram-media');
try {
if (twitterEmbed.length !== 0) Defer.js('//platform.twitter.com/widgets.js','widgets-js',1000);
if (instaEmbed.length !== 0) Defer.js('//www.instagram.com/embed.js','embed-js',1000);
} catch (error) {
console.log(error);
}
※ JetTheme を利用中の場合は、/*Your Script is here to maintain performance.*/
の下に設置してください。
※ 他のテンプレートの場合は、上記コードを次のように囲んで設置してください。
<script>/*<![CDATA[*/
遅延読み込み用コード
/*]]>*/</script>
上記コードは、
- Twitter の埋め込み(twitter-tweet というクラス名)がある場合は Twitter のスクリプトを遅延して読み込む
- Instagram の埋め込み(instagram-media というクラス名)がある場合は Instagram のスクリプトを遅延して読み込む
というものです。クラス名は公式の埋め込みコードで使われているものを指定しています。
コード内の1000の数値が遅延読み込みする秒数(ミリ秒単位)です。好きなように変更可。1000ミリ秒は1秒です。
埋め込みを記事上部で使う場合は1000ミリ秒程度、記事下部でしか使わない場合は2000~3000ミリ秒程度にしておくと、他の読み込みと重なるリスクを避けやすいのではと思います。
特定のクラスがある場合のみ読み込むという記述方法については、以下サイトを参考にさせていただきました。
WordPressでTwitterとInstagramの埋め込みを遅延読み込みさせる方法 | Code&Dev
3.Twitter の埋め込みコードから script タグを削除
Twitter・Instagram の投稿は、埋め込みコードから<script>タグを削除したうえで記事に埋め込みます。
<script>
タグは、公式埋め込みコードの末尾にあります。
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">wanna know what the drivers do outside of the car to setup a car during an F1 weekend? 🤔 our new Behind the Visor episode goes technical! 👇 <a href="https://t.co/67gRTgxfUu">pic.twitter.com/67gRTgxfUu</a></p>— Scuderia AlphaTauri (@AlphaTauriF1) <a href="https://twitter.com/AlphaTauriF1/status/1534560403811868673?ref_src=twsrc%5Etfw">June 8, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> ←ここを削除
<blockquote class="twitter-tweet"><p lang="en" dir="ltr">wanna know what the drivers do outside of the car to setup a car during an F1 weekend? 🤔 our new Behind the Visor episode goes technical! 👇 <a href="https://t.co/67gRTgxfUu">pic.twitter.com/67gRTgxfUu</a></p>— Scuderia AlphaTauri (@AlphaTauriF1) <a href="https://twitter.com/AlphaTauriF1/status/1534560403811868673?ref_src=twsrc%5Etfw">June 8, 2022</a></blockquote>
<blockquote class="instagram-media" data-instgrm-permalink="https://www.instagram.com/p/CegmCzEMnNn/?utm_source=ig_embed&utm_campaign=loading" data-instgrm-version="14"
...略...
Scuderia AlphaTauri(@alphataurif1)がシェアした投稿</a></p></div></blockquote> <script async src="//www.instagram.com/embed.js"></script> ←ここを削除
<blockquote class="instagram-media" data-instgrm-permalink="https://www.instagram.com/p/CegmCzEMnNn/?utm_source=ig_embed&utm_campaign=loading" data-instgrm-version="14"
...略...
Scuderia AlphaTauri(@alphataurif1)がシェアした投稿</a></p></div></blockquote>
これで遅延読み込みできているはずです!
動作確認としては、以下を確認してみてください。
- Twitter・Instagram の埋め込みが問題なく表示されているか
※ 遅延読み込みが正しく動作してないと、埋め込みが画像つきで正しく表示されません - Twitter・Instagram を埋め込んだページで PageSpeed Insights のスコアが悪化していないか
- Twitter・Instagram を埋め込んでいないページで、JavaScript の読み込みが発生していないか
※ブラウザの検証ツールの「ネットワーク」タブで確認できます
問題がなければ完了です。
問題があったら、、、記述ミスがないか、<script>タグの削除漏れがないかどうか等を確認してみてください。
記事内の埋め込み数・もともとのテンプレートの速度・設定する遅延秒数により、ページスピードのスコアが上下する場合があります。記事の下部にしか埋め込みを使わない場合は、遅延秒数を多めに設定することをおすすめします。
記事内の埋め込み数が多い場合
記事内の埋め込み数がかなり多い場合、スクリプトの遅延読み込み後にページ動作が一時的に重くなる場合があります(特にモバイル)。
その場合は、以下の記事で紹介する方法をご検討ください。埋め込みコードのクラスを書き換えるひと手間が必要ですが、ページの重さを改善できると思います。
※追記:Defer.js 適用のデモページを作成しました。
demo by Limosuki
デモ①が本記事で紹介している方法、デモ②③が以下記事の方法です。
Twitter・Instagram の遅延読み込みについては以上です。
以下、今回使用させていただいた defer.js のその他機能を簡単に紹介します。YouTube や画像なども遅延させることができます。
defer.js の機能
defer.js で遅延できるもの
defer.js では、Twitter・Instagram に限らずさまざまなものを(たぶん何でも)遅延読み込みできます。
- 外部の JavaScript
- Twitter など SNS の埋め込みコード
- highlight.js などのシンタックスハイライター
- 外部の CSS
- Font Awesome など
- 画像
- iframe
- YouTube 動画 など
- アナリティクスやアドセンス
使い方は作者さんの defer.js 公式ページ(shinsenter/defer.js · GitHub)にて説明されていますが、英語なので、ここでは私が理解した機能の内容、当ブログで利用している内容を簡単に紹介したいと思います。
本記事に掲載しているコードを使用される場合は、公式ページを参照の上でご自身の責任にてお願いいたします。高度な使用例、応用例などは公式ページをご参照ください。
外部スクリプトの遅延読み込み例(Defer.js)
Twitter・Instagram 以外の外部スクリプトも遅延できます。
基本的に、</body>
前に次のように記述すればスクリプトが遅延読み込みされます。
Defer.js('遅延させたいjsファイル','ID',遅延の秒数);
ID
の部分は、他のファイルと重複しないよう自分で設定します。
遅延の秒数の部分は、ミリ秒単位で指定します。
前の章で紹介した通り、Twitter の埋め込みスクリプトを1秒(1000ミリ秒)遅延読み込みさせる場合は次の例のようになります。
Defer.js('//platform.twitter.com/widgets.js','widgets-js',1000);
特定のクラスがある場合のみ読み込みたい場合は、前の章で紹介した Twitter・Instagram の遅延読み込みコードをサンプルとしてご参照ください。
外部 CSS の遅延読み込み例(Defer.css)
Font Awesome などの外部 CSS ファイルを CDN で利用する場合も遅延読み込み可能です。
</body>
前に次のように記述します。
Defer.css('遅延させたいCSSファイル','ID',遅延の秒数);
ID
の部分は、他のファイルと重複しないよう自分で設定します。
遅延の秒数の部分は、ミリ秒単位で指定します。
Font Awesome 6 バージョンの CSS ファイルを1秒(1000ミリ秒)遅延読み込みさせる場合は次の例のようになります。
Defer.css('//cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css','fontawesome6-css',1000);
YouTube(iframe)の遅延読み込み例(Defer.dom)
YouTube 動画の埋め込みなどの iframe は次の手順で遅延読み込みできます。
基本的な使い方
手順1.YouTube 埋め込みコードの src を data-src に変更
YouTube の埋め込みコードの一部を、次のように変更して記事に載せます。
<iframe width="560" height="315" src="https://www.youtube.com/embed/X3GxcMUYLgs?start=415" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
↓↓↓ src
の前に data-
を追記する
<iframe width="560" height="315" data-src="https://www.youtube.com/embed/X3GxcMUYLgs?start=415" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
手順2.遅延読み込み用のコードを</body>
前に追記
Defer.dom('iframe');
YouTube 動画を載せている箇所までページがスクロールされたら、iframe を読み込むという仕組みです。(たぶん)
Intersection Observer という、スクロール時に要素の位置をチェックできる機能が使われているようです。
Intersection Observer API(交差オブザーバー API) - Web API | MDN
読み込みタイミングを早める使い方
もし、動画が画面に表示されるより少し前のタイミングで読み込みたい場合は、遅延読み込み用コードを次のようにします。
※ JetTheme 以外の場合(公式に準拠)
Defer.dom('iframe', 200, null, null, {
rootMargin: "200%"
});
上記は、ページが完全に読み込まれてから 200 ミリ秒後、iframe が画面の大きさ2倍分手前の位置に来たら読み込むという記述です。(たぶん)
rootMargin: "200%"
の部分が要素を読み込む位置を指示しているので、数値を変えれば読み込むタイミングを変えられます。100px のようにも指定できます。
※ JetTheme の場合
JetTheme では、上記のように公式ページの説明通りに試したところなぜか動作しませんでした。おそらく JetTheme 独自のカスタマイズが入っているのかなと思います。
いろいろ試していたところ、次のように記述したら希望通りに読み込まれました。
Defer.dom('iframe', 200, null, null, null, {
rootMargin: "200%"
});
当ブログではrootMargin: "200%"
を指定したバージョンを使っています。
※追記:本記事執筆時点では、JetTheme 2.9 に組み込まれている defer.js@2.5.0 を利用しています
なお公式ページには、「読み込み成功後に要素にクラス名を付与する」設定例などもあります。
その他、画像などの遅延読み込み(Defer.dom)
上記の Defer.dom 機能のiframe
の部分は CSS のセレクタを何でも指定できるようです。
※公式ページに例あり
例:特定のクラス名をつけた要素を遅延させる
Defer.dom('.特定のクラス名');
例:lazy
のクラス名をつけた画像を遅延させる
Defer.dom('img.lazy');
画像を遅延させる場合は iframe と同様に、画像タグ内のsrc="画像URL"
の部分にdata-
を追記して記事に載せます。
以下は、lazy
のクラス名をつけた画像を遅延させる例です。
<img class="lazy" alt="" width="889" height="594" data-src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0efl...9Bz-pCVDhng/s1600/eyecatch.jpg"/>
Defer.dom('img.lazy');
私は、画像の遅延読み込みはブラウザ機能のネイティブ Lazyload でいいかなと思っているので、今のところ defer.js では遅延させていません。
さいごに:defer.js はすごい
defer.js を知るまで、遅延読み込みといえば「スクロールしたらタグ発火」の方法しか知らなかったので、スクロール動作に依存せずにこんな風に遅延読み込みできてすごい! という感想です。
スクロール動作をトリガーにすると、その瞬間に一気に全スクリプトの読み込みが発動するので、場合によってはスクロールが若干カクつくなと感じたことがあります。defer.js であればそのようなことにならないのでとても満足です。