ある団体のホームページ(Cocoonテーマを使用したWordPressサイト)を運営しています。
このサイトでは、複数のRSS情報を統合表示しています。
従来はページ表示時にRSS取得処理を同時実行していたため、WordPressのRSSキャッシュ更新タイミングでは、表示まで約15秒程度かかり、その間はなにも表示されない画面となっていました。
この問題を改善するため、RSS表示を「LazyLoad(遅延読み込み)」方式へ変更しました。
■ 変更前の動作
- ページ表示開始
- WordPressがRSS取得
- RSS生成完了後にページ表示
この方式では、RSS取得中にページ全体の表示が待たされる場合がありました。
■ 変更後(LazyLoad)の動作
- 先にページ本体を表示
- JavaScript が実行
- admin-ajax.php 経由でRSSを非同期取得
- RSS取得後に該当部分へ表示
これにより、
- ページの初期表示速度向上
- RSS更新時の無表示時間を軽減
- ユーザー体感速度の改善
を実現しています。
■ 処理イメージ
ページ表示
↓
JavaScript 実行
↓
admin-ajax.php にRSS取得要求
↓
WordPress がRSS HTML生成
↓
ページへ差し込み表示
■ LazyLoad 対応コード
① ショートコード:HTML を作らず、プレースホルダーだけ返す(functions.php)
// ------------------------------------------------------------
// LazyLoad 用ショートコード
// ここでは RSS の HTML を作らず、空の div(プレースホルダー)だけ返す
// ------------------------------------------------------------
add_shortcode('rss_merge', function($atts) {
// ショートコードの初期値
$atts = shortcode_atts([
'url' => '',
'count' => 5,
'cache_minute' => 60,
], $atts, 'rss_merge');
// URL が無ければ何も表示しない
if (empty($atts['url'])) {
return '';
}
// Ajax で識別するための一意 ID を生成
$id = 'rss_merge_' . md5(json_encode($atts));
// Ajax 側で使うため、ショートコードの属性を一時保存
set_transient($id . '_atts', $atts, 60 * 60);
// ページには RSS の HTML を出さず、空の div だけ返す
return '<div class="rss-merge-lazy" data-id="' . esc_attr($id) . '">読み込み中...</div>';
});
② Ajax フック:RSS を取得して HTML を返す(functions.php)
// ------------------------------------------------------------
// Ajax フック登録(ログイン・非ログイン両方対応)
// admin-ajax.php?action=rss_merge_load が呼ばれると実行される
// ------------------------------------------------------------
add_action('wp_ajax_rss_merge_load', 'rss_merge_load');
add_action('wp_ajax_nopriv_rss_merge_load', 'rss_merge_load');
function rss_merge_load() {
// JavaScript から送られた ID を取得
$id = sanitize_text_field($_GET['id'] ?? '');
if (!$id) wp_die();
// ショートコードで保存した属性を取得
$atts = get_transient($id . '_atts');
if (!$atts) wp_die('No data');
// ------------------------------------------------------------
// ここに元の RSS 取得処理をそのまま移植
// (fetch_feed → items → ソート → HTML生成)
// ------------------------------------------------------------
echo $feed_contents; // 生成した HTML を返す
wp_die(); // Ajax 終了
}
③ JavaScript に admin-ajax.php の URL を渡す(functions.php)
// ------------------------------------------------------------
// javascript.js を読み込み、admin-ajax.php の URL を JS に渡す
// ------------------------------------------------------------
function rss_merge_enqueue_js() {
// javascript.js を読み込む
wp_enqueue_script(
'rss-merge-js',
get_stylesheet_directory_uri() . '/javascript.js',
[],
null,
true // フッターで読み込む
);
// admin-ajax.php の URL を JS に渡す
wp_localize_script('rss-merge-js', 'rssMergeAjax', [
'url' => admin_url('admin-ajax.php'),
]);
}
add_action('wp_enqueue_scripts', 'rss_merge_enqueue_js');
④ JavaScript:ページ読み込み後に Ajax を実行(javascript.js)
// ------------------------------------------------------------
// ページ読み込み後に実行
// プレースホルダー(.rss-merge-lazy)を探し、Ajax で RSS を取得する
// ------------------------------------------------------------
document.addEventListener("DOMContentLoaded", function() {
// すべてのプレースホルダーを取得
document.querySelectorAll(".rss-merge-lazy").forEach(function(box) {
// data-id 属性から Ajax 用の ID を取得
const id = box.dataset.id;
// WordPress の admin-ajax.php に RSS を要求
fetch(rssMergeAjax.url + "?action=rss_merge_load&id=" + id)
// WordPress が返した HTML をテキストとして受け取る
.then(res => res.text())
// プレースホルダーの中身を RSS の HTML に置き換える
.then(html => {
box.innerHTML = html;
});
});
});

