MENU

【WordPress高速化】X・Instagramの遅延読み込み

【WordPress高速化】YouTube埋め込みを遅延読み込み
目次

はじめに

「WordPress高速化」シリーズの第8回です。XとInstagramの埋め込みは、記事のずっと下にあっても、ページを開いた直後に合わせて約1.1〜1.6MBを読み込みます。

この記事では、【WordPress高速化】YouTube埋め込みを遅延読み込み(以下「第3回」)と同じ Intersection Observer を使って、投稿の1000px手前に来るまで読み込まないようにします。途中で離れた読者には、XとInstagramの通信が一度も発生しません。表示されたときにずれないように、埋め込みの高さを先に確保する手順もセットで解説します。

WordPress 7.1.4、SWELL 2.19 で確認しています。SWELLの子テーマの functions.php を使います。編集する前に、必ずバックアップを取ってください。

当サイトでは、現在 X と Instagram の埋め込みを使用していませんが、今後使用する可能性があるかもしれないので Localのテスト環境を使って対策を検討していくこととします。

XとInstagramの埋め込みの仕組み

XとInstagramの埋め込みコードは、引用(<blockquote>)と、外部のスクリプトの組み合わせです。

<!-- Xの埋め込みコード -->
<blockquote class="twitter-tweet">…投稿の文章とリンク…</blockquote>
<script async src="https://platform.x.com/widgets.js" charset="utf-8"></script>

<!-- Instagramの埋め込みコード -->
<blockquote class="instagram-media" data-instgrm-permalink="…">…投稿へのリンク…</blockquote>
<script async src="//www.instagram.com/embed.js"></script>

スクリプトが読み込まれると、ページの中の blockquote を探して、投稿を表示する <iframe> に置き換えます。最初から iframe のYouTubeと違って loading="lazy" は使えないので、遅らせるのはスクリプトを読み込むタイミングです。

この記事では、どちらも公式の埋め込みコード(投稿の「…」メニューから取得)を、「カスタムHTML」ブロックに貼る形で進めます。WordPressのURL自動埋め込みは、Xは twitter.com のURLだけ、Instagramは対象外のうえ、後で説明する高さの確保もこの形のほうが簡単です。

いつ、どれくらい読み込んでいるか

Localのテスト記事で、本文の下のほうにXとInstagramの投稿を1つずつ埋め込み、スクロールせずに開いたままにして通信を測りました。比較のため、SWELLの「スクリプトの遅延読み込み」(後で説明します)も測っています。

方法開いて3秒後開いて8秒後(操作なし)埋め込みの近くまでスクロール
標準(そのまま埋め込む)約1.1〜1.6MB約1.1〜1.6MB約1.1〜1.6MB
SWELLの遅延読み込み0全部読み込む全部
Intersection Observer(この記事)00近づいた投稿の分だけ

SWELLの遅延読み込みは、読者が操作するか、数秒(初期設定は5秒)たつと、スクロールしていなくても全部読み込みます。Intersection Observerなら、1000px手前に来るまで、何秒たっても0のままです。

標準・SWELLの設定・Intersection Observerで、XとInstagramを読み込むタイミングの違い

遅らせるなら、高さの確保がセット

スクリプトが blockquote を iframe に置き換えると、埋め込みの高さが伸びます(Xはスマホで377px→630〜780px)。標準なら画面の外で伸びるので問題になりませんが、遅らせると読者がスクロールしている途中で、画面の近くで伸びます。

スマホ幅でスクロールしながら、ずれ(CLS)を測った結果です。

方法ゆっくりスクロール速くスクロール
標準00
Intersection Observer・高さの確保なし00.70〜1.01
Intersection Observer+高さの確保00〜0.006

CLSは、0.1以下が「良好」、0.25を超えると「不良」です。遅延読み込みと高さの確保は、セットで行ってください。考え方は、【WordPress高速化】SWELLのCLSをCSSで改善で目次や広告の枠に min-height を付けたのと同じです。

埋め込みの高さを確保しない場合とする場合。確保しないと、表示されたときに下の本文が押し下げられる

手順:埋め込みに近づいてから表示する

Step1:functions.phpにコードを追加する

子テーマの functions.php に、次のコードを追加します。

// X・Instagramの埋め込みを、画面に近づいてから表示する
add_filter('the_content', function ($content) {
	if (is_admin() || is_feed() || wp_is_json_request()) { return $content; }
	// 埋め込みに付いてくるスクリプトを外す
	$content = preg_replace('#<script[^>]+src="https://platform\.(twitter|x)\.com/widgets\.js"[^>]*></script>#', '', $content);
	$content = preg_replace('#<script[^>]+src="(https:)?//www\.instagram\.com/embed\.js"[^>]*></script>#', '', $content);
	// スクリプトがまとめて表示しないように、classを変えておく
	$content = str_replace('class="twitter-tweet', 'class="lazy-twitter-tweet', $content);
	$content = str_replace('class="instagram-media', 'class="lazy-instagram-media', $content);
	return $content;
}, 20);

add_action('wp_enqueue_scripts', function () {
	if (!is_singular()) { return; }
	wp_enqueue_script('embed-lazy', get_stylesheet_directory_uri() . '/js/embed-lazy.js', [], '1.0', ['in_footer' => true, 'strategy' => 'defer']);
});
  • preg_replace(…):本文の中の widgets.js と embed.js の <script> を削除します。Xは、古い platform.twitter.com と新しい platform.x.com の両方に一致させています
  • str_replace(…):blockquote のクラス名を lazy-〜 に変えます。スクリプトは、ページの中の twitter-tweet・instagram-media をすべて表示してしまうためです。【WordPress高速化】AdSenseを枠ごとに遅延読み込みで、広告の枠のクラス名を変えたのと同じ考え方です
  • 優先度 20:ブロックやショートコードを展開した後に書き換えるためです

Step2:JavaScriptのファイルを作る

子テーマの js フォルダに、embed-lazy.js というファイルを作ります。

// X・Instagramの埋め込みを、画面に近づいたときに表示する
document.addEventListener('DOMContentLoaded', () => {
	const targets = document.querySelectorAll('.lazy-twitter-tweet, .lazy-instagram-media');
	if (!targets.length) return;

	// スクリプトは1回だけ読み込む
	const loaded = {};
	const loadScript = (src) => {
		if (!loaded[src]) {
			loaded[src] = new Promise((resolve) => {
				const s = document.createElement('script');
				s.src = src;
				s.async = true;
				s.onload = resolve;
				document.body.appendChild(s);
			});
		}
		return loaded[src];
	};

	const observer = new IntersectionObserver((entries) => {
		entries.forEach((entry) => {
			if (!entry.isIntersecting) return;
			const el = entry.target;
			observer.unobserve(el);

			if (el.classList.contains('lazy-twitter-tweet')) {
				el.classList.replace('lazy-twitter-tweet', 'twitter-tweet');
				loadScript('https://platform.twitter.com/widgets.js')
					.then(() => window.twttr.widgets.load(el.parentNode));
			} else {
				el.classList.replace('lazy-instagram-media', 'instagram-media');
				loadScript('https://www.instagram.com/embed.js')
					.then(() => window.instgrm.Embeds.process());
			}
		});
	}, { rootMargin: '1000px 0px' });

	targets.forEach((el) => observer.observe(el));
});
  • classList.replace(…):近づいた埋め込みだけ、クラス名を元に戻します
  • twttr.widgets.load(el.parentNode):指定した要素の中のXの投稿だけを表示します
  • instgrm.Embeds.process():まだ表示していないInstagramの投稿を表示します
  • rootMargin: '1000px 0px':画面の下端から1000px手前に来たら、読み込みを始めます。値の決め方は、後の「rootMarginの値の決め方」で説明します

Step3:埋め込みをdivで囲んで、高さを確保する

「カスタムHTML」ブロックに、埋め込みコードを embed-box というクラスの div で囲んで貼ります。--h-sp にスマホの高さ、--h-pc にPCの高さを書きます。

<div class="embed-box" style="--h-sp: 780px; --h-pc: 820px;">
(ここにXまたはInstagramの埋め込みコードをそのまま貼る)
</div>

-- で始まる名前はCSS変数です(【WordPress高速化】目次の高さを見出しの数で自動設定でも使いました)。続けて、外観 > カスタマイズ > 追加CSS に、次のCSSを1回だけ書きます。

/* X・Instagramの埋め込みの高さを確保する */
.embed-box {
	min-height: var(--h-sp);
}
@media (min-width: 600px) {
	.embed-box {
		min-height: var(--h-pc);
	}
}

幅600pxを境にしているのは、SWELLがそこでスマホとPCのレイアウトを切り替えるためです。

Step4:高さを測る

埋め込みの高さは、投稿の内容と画面の幅によって変わります。今回の投稿では、次のようになりました。

画面の幅XInstagram
360px672px372px
375px641px379px
390px648px385px
412px772px396px
430px780px404px
600px以上(PC)820px488px

Xは文章の折り返しで高さが変わるので、幅が広いほど高いとは限りません。スマホは360〜430pxの中で一番高い値を --h-sp に、PCの値を --h-pc に書きます。

測るときは、Chromeの検証ツール(F12)でスマホの幅に切り替え、埋め込みが表示されるまでスクロールしてから、「Console」タブで次のコードを実行します。

document.querySelectorAll('.embed-box').forEach((box) => {
	box.style.minHeight = '0px';
	console.log(Math.ceil(box.getBoundingClientRect().height));
	box.style.minHeight = '';
});

確保した高さを一時的に外して、埋め込みそのものの高さを上から順に表示します。幅を変えながら測ってください。幅の切り替え方は、【WordPress高速化】CLSの原因を検証ツールで探す方法で解説しています。

一番高い値に合わせるので、幅によっては下に余白ができます(今回のXは幅375pxで約140px)。余白はずれではないので、CLSには影響しません。

Step5:動作を確かめる

  1. ページのソース(Ctrl+U)で widgets.js と embed.js を検索する → 本文の中の <script> が見つからない
  2. 検証ツールの「ネットワーク」タブを開いて再読み込みする → スクロールしなければ、しばらく待っても x.com・instagram.com の通信がない
  3. 埋め込みまでスクロールする → 1000px手前で通信が始まり、投稿が表示される

Localで確かめると、幅375px・412px・1366pxのどれでも、投稿は標準と同じ高さで表示され、CLSは0〜0.006でした。

rootMarginの値の決め方

rootMargin は、画面の下端から何px手前で読み込みを始めるかを決める値です。0px なら埋め込みが画面に入った瞬間、1000px なら画面の1000px手前で始めます。

rootMarginの値と、読み込みを始める位置。値が大きいほど、画面より手前で読み込みを始める

画面に入る前に表示を終えるには、次の距離が必要です。

必要な距離 = 読み込みを始めてから表示が終わるまでの時間 × スクロールの速さ

Localで測ると、表示までの時間は、通信制限なしで約1〜2秒、検証ツールの「高速4G」で約2.5〜3.5秒でした。スクリプト・投稿のデータ・画像を順に取りにいくので、YouTube(第3回は200px)より大きな値が必要です。

スマホ幅で、読みながらの速さ(毎秒500pxと想定)でスクロールしたときの、埋め込みが画面に入ってから表示が終わるまでの遅れです。

rootMargin通信制限なし高速4G
0px0.9〜1.6秒2.6〜3.0秒
300px0.4〜0.9秒2.0〜2.9秒
600px0〜0.3秒1.3〜1.4秒
1000px遅れなし0.6〜0.8秒

0pxでは、1秒以上、文章とリンクだけの状態が見えます。1000pxなら通信制限なしでは間に合いますが、スマホの回線や速いスクロールでは少し遅れます。すべての条件で間に合わせるには数千px必要で、そこまで広げると、手前で離れた読者にも読み込んでしまいます。

そこで、1000pxを基準にして、間に合わない分は高さの確保で吸収します。高さを確保していれば、表示が遅れても枠の中に文章とリンクが見えるだけで、ずれは起きません(確保しないと、300pxでスマホのCLSが0.33になりました)。

自分のサイトで確かめるときは、「ネットワーク」タブの通信制限で「高速4G」を選び、ふつうに読む速さでスクロールします。表示が遅すぎると感じたら値を大きく、記事の後半まで読まれることが少ないなら値を小さくしてください。

SWELLの「スクリプトの遅延読み込み」との違い

SWELLにも、スクリプトを遅らせる機能があります(SWELL設定 > 高速化 > 遅延読み込み機能 > スクリプトの遅延読み込み)。コードは不要ですが、次の点が違います。

  • 操作か数秒で、全部読み込む:マウス・ホイール・タップ・キー操作、または指定の秒数(初期設定は5秒)で、スクロールしていなくてもページの中の埋め込みをすべて読み込みます
  • Xは x.com/widgets.js を足す:キーワードの初期設定は twitter.com/widgets.js で、いまのXの埋め込みコード(platform.x.com/widgets.js)に一致しません。Localでは、x.com/widgets.js, を1行足すと遅延されました
  • 高さの確保は、こちらでも必要:Step3・Step4は、SWELLの機能で遅らせる場合にも使えます

この記事のコードは本文からスクリプトを削除するので、SWELLの設定と両方使っても、二重に読み込まれることはありません。

注意点

  • 投稿を差し替えたら、高さを測り直す:Xの引用ポストや、Instagramの複数枚の投稿は、高さが大きく変わります
  • ページの冒頭の埋め込みは遅らせない:開いてすぐ見える位置の埋め込みは、遅らせると表示が遅れて見えます
  • キャッシュを削除してから確かめる:SWELLのキャッシュやキャッシュ系のプラグインを使っている場合は、コードを変えたら削除してください

よくある質問・エラー対処

Q. Instagramの埋め込みが、リンクだけの表示になります

→ Instagramは、公開アカウントの投稿しか埋め込めません。非公開アカウントの投稿ではないか確認してください。あわせて、ページのソースで embed-lazy を検索し、JavaScriptが読み込まれているかも確認してください。


Q. 埋め込みブロック(URLを貼る方法)のままでも使えますか

→ コードは動きますが、埋め込みブロックは div で囲めないので、高さを確保できません。カスタムHTMLブロックに貼ってください。

おわりに(まとめ)

まとめ

Intersection Observerを使えば、XとInstagramの埋め込みを、読者が近づくまで一切読み込まずに済みます。

  • ✅ XとInstagramの埋め込みは、画面の外にあっても、ページを開いた直後に合わせて約1.1〜1.6MBを読み込む
  • ✅ Intersection Observerなら、1000px手前に来るまで0のまま。近づいた投稿だけを読み込む
  • ✅ rootMarginは「表示までの時間 × スクロールの速さ」で考える。1000pxを基準にし、間に合わない分は高さの確保で吸収する
  • ✅ SWELLの遅延読み込みは、操作か数秒でスクロールしていなくても全部読み込む。Xは x.com/widgets.js を足す
  • ✅ 遅らせると、表示されたときに高さが伸びてCLSが悪化する。min-height で高さを確保する
  • ✅ 高さは投稿と画面の幅で変わる。スマホは360〜430pxで一番高い値を使う

この記事が、少しでも誰かのお役に立てれば幸いです。

関連記事

当サイトの記事で使用したVBAなどのサンプルをDLできます

この記事のサンプルはありません!

ダウンロードページへは下のカードをクリックすればジャンプできます。
よろしければご利用ください!


【CSS】テキスト関連プロパティについて基本解説|Webの基礎


よかったらシェアしてね!
  • URLをコピーしました!
目次