menu

WordPress高速化&表示トラブル対応・完全ガイド

WordPress高速化&表示トラブル対応・完全ガイド

— LCP・YouTube・LazyLoad・Async/Defer・「ページ上へ」ボタンまで、一般ユーザーが安全に直す手順

はじめに:このガイドでできること

このコラムは、WordPress を利用する一般ユーザー向けに、ページの表示速度を底上げしつつ、アップデート後に起こりがちな「ボタンが消えた」「動画で重い」「画像が遅い」などの不具合を安全に改善するための実践手順をまとめました。
難しい専門用語は最小限に、コピペできるコード設定例を豊富に載せています。必要な箇所だけ拾い読みしてOKです。


1. まずは考え方:最短で効く順にやる

サイトが重い/不安定な原因はさまざまですが、一般的には次の優先順位で直すと早く体感が上がります

  1. **LCP(最大コンテンツの描画)**を最短にする

  2. JavaScriptの重さ(特に YouTube・解析タグ)を初期表示から外す

  3. CSS/JS の読み込み順を安定化(Async/Deferの当て方・除外)

  4. 画像のサイズ/形式/遅延の整理(LazyLoadは1本化、LCPは遅延しない)

  5. サーバー/キャッシュの基本(ページキャッシュ・オブジェクトキャッシュ)

以降は、この順で「何をどうやるか」を具体的に説明します。


2. LCP最適化:最初に見える“あの画像”を最短に

LCPとは、ページで一番大きく目立つコンテンツ(多くはヒーロー画像や太い見出し)の描画完了までの時間です。ここが速いと“立ち上がりが速い”と感じます。

2-1 LCP画像が <img> の場合

  • fetchpriority="high" を付ける(最優先で取りに行く合図)

  • loading="eager" にする(LCPは遅延しない)

  • width/height を明示(CLS対策)

<img
src="/path/hero.webp"
alt="ヒーロー画像"
width="1200" height="675"
fetchpriority="high"
loading="eager"
decoding="async">

2-2 背景画像(CSS background-image)がLCPなら

fetchpriority<img> 専用なので使えません。代わりに <link rel="preload" as="image"><head> の早い位置へ入れます。

functions.php で <head> に差し込む例(推奨)

add_action('wp_head', function () {
if (is_front_page()) {
$href = get_template_directory_uri() . '/images/hero.webp';
echo '<link rel="preload" as="image" href="' . esc_url($href) . '" imagesizes="100vw">' . "\n";
}
}, 1);

注意index.php(本文側)に preload を書いても 間に合わないことが多いです。header.phpwp_head で入れてください。


3. 画像最適化:軽く・正しく・1本化

  • 形式:WebP/AVIF を基本に。PNG はロゴや透過だけ。

  • サイズ:表示サイズぴったりの画像を用意(過剰解像度禁止)。

  • レスポンシブsrcset/sizes でデバイスに合わせて配信。

  • LazyLoadは1つに統一:複数プラグインの重複は不具合の温床。

  • LCP画像だけは Lazy 対象から除外loading="eager" か、プラグインの除外属性 data-no-lazy="1" / data-skip-lazy="1" を付与)。

例:非LCP画像は lazy でOK

<img src="/path/section.webp"
loading="lazy" decoding="async"
width="800" height="450" alt="セクション画像">

4. YouTube が重い問題:軽量埋め込みで一撃

YouTube をそのまま <iframe> で複数貼ると、base.js などが初期表示で実行され、合計CPU数秒持っていかれます。
**「初期は静的、クリックされたら読み込む」**方式に変えると激的に速くなります。

4-1 最短:srcdocloading="lazy" 方式

<iframe
loading="lazy"
width="560" height="315"
title="YouTube"
src="https://www.youtube-nocookie.com/embed/VIDEO_ID?rel=0&modestbranding=1&playsinline=1"
srcdoc="
<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}
img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto;height:100%;object-fit:cover}
span{height:3em;line-height:3em;text-align:center;background:rgba(0,0,0,.5);color:#fff;font:700 1.2em sans-serif;left:0;right:0;width:40%;border-radius:.5em}
</style>
<a href='https://www.youtube-nocookie.com/embed/VIDEO_ID?autoplay=1&rel=0&modestbranding=1&playsinline=1'>
<img src='https://i.ytimg.com/vi/VIDEO_ID/hqdefault.jpg' alt='動画プレビュー' loading='lazy'>
<span>▶ 再生</span>
</a>"
>
</iframe>
  • autoplay=1 はクリック後のURLのみに付けるのがコツ。初期は実行しません。

4-2 本格:lite-youtube-embed をショートコード化

長期運用・動画が多いならこの方法が最強です。

// functions.php
add_action('wp_enqueue_scripts', function(){
wp_enqueue_style('lite-yt', 'https://unpkg.com/lite-youtube-embed@0.3.2/src/lite-yt-embed.css', [], null);
wp_enqueue_script('lite-yt', 'https://unpkg.com/lite-youtube-embed@0.3.2/src/lite-yt-embed.js', [], null, true);
});
add_shortcode('yt', function($atts){
$id = esc_attr($atts['id'] ?? '');
$title = esc_attr($atts['title'] ?? 'YouTube');
if (!$id) return '';
return '<lite-youtube videoid="'.$id.'" style="aspect-ratio:16/9" title="'.$title.'"></lite-youtube>';
});

本文では
[yt id="VIDEO_ID" title="紹介動画"] だけ。クリックまで iframe を作りません。


5. Async / Defer の基礎と安全設定

Async は「読み終えたらすぐ実行」。Defer は「HTML を最後まで読んだ後に実行(順番を守る)」です。
jQuery 依存や“順序が大事”なスクリプトがあるサイトでは、Defer の方が壊れにくいです。

5-1 壊れない基本方針

  • グローバル設定:Defer

  • jQuery:Exclude(除外)

  • 壊れては困るテーマJSも Scripts to Exclude(例:common.min.js, main.js, shop.min.js など)

Scripts to Exclude(例)

jquery.js, jquery.min.js, jquery-migrate.min.js,
common.min.js, main.js, shop.min.js

LazyLoad 系が複数なら、lazysizes.min.js / jquery.lazyloadxt.*.js のどちらかは外すか停止して1本化しましょう。

5-2 Plugin/Theme Exclusions の使い分け

  • どのファイルか分からない場合、プラグイン丸ごと/テーマ丸ごとの除外も可。

  • ただし除外し過ぎは効果が落ちるため、基本はファイル名でピンポイント除外がベター。

5-3 変更後のチェック

  • プラグイン・ページキャッシュ・ブラウザキャッシュを全削除→再読込

  • DevTools の Console にエラーが出ていないか確認

  • 重要UI(メニュー、モーダル、ページトップボタン)が動くか確認


6. 「ページ上へ」ボタンが消えた/出ない問題

アップデートや最適化でよく起きます。原因は主に4つ。

  1. HTMLをJSで生成していたが、JSが遅延/順序崩れで未実行

  2. CSSの ::before でアイコン描画していたが、CSSが読まれない/FontAwesome崩れ

  3. z-index で他の固定UIに隠れている

  4. テンプレート末尾の wp_footer() が無い(フックが走らない)

6-1 一番安全な復旧

HTMLを常に出す最小JSにする方法が安定します。

footer.php に直書き(wp_footer() の前後)

<a href="#whole" class="page-top" aria-label="ページ上部へ"></a>
<?php wp_footer(); ?>
</body>
</html>

最小JS(jQuery不要・Defer/Asyncの影響を受けにくい)

<script>
document.addEventListener('DOMContentLoaded',function(){
var btn=document.querySelector('.page-top'); if(!btn) return;
var showAt=200;
function toggle(){ (window.scrollY>showAt)?btn.style.display='flex':btn.style.display='none'; }
toggle(); window.addEventListener('scroll',toggle,{passive:true});
btn.addEventListener('click',function(e){e.preventDefault();window.scrollTo({top:0,behavior:'smooth'});});
});
</script>

このスニペット(または保存したJSファイル名)は、Async/Deferの “Scripts to Exclude” にも入れておくと盤石です。

フォントに依存しないCSS(::beforeで矢印)

.page-top{
position:fixed; right:14px; bottom:14px;
width:52px; height:52px; border-radius:9999px;
background:#ff9800; color:#fff;
display:flex; align-items:center; justify-content:center;
box-shadow:0 4px 14px rgba(0,0,0,.18);
z-index:10010;
}
.page-top::before{content:"▲";font-size:18px;line-height:1;transform:translateY(-1px);}

7. PHP8 で突然 Fatal:DOMDocument::loadHTML() 対策

PHP8以降は引数チェックが厳格化。loadHTML('') のように空文字を渡すと ValueError で Fatal になります。
空チェックエラー握りUTF-8 明示で守りましょう。

// $html に何らかのHTMLを入れる前提
$html = isset($html) ? (string)$html : '';
if (trim($html) === ) {
echo ‘<!– DOMDocument: empty HTML skipped –>’;
} else {
$dom = new DOMDocument(‘1.0’,‘UTF-8’);
libxml_use_internal_errors(true);
$ok = $dom->loadHTML(‘<?xml encoding=”UTF-8″>’ . $html,
LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
libxml_clear_errors();
echo $ok ? $dom->saveHTML() : $html;
}

“空になる”よくある原因

  • 外部取得(wp_remote_get() 等)の失敗/タイムアウト

  • 対象の説明文・本文が空

  • 条件分岐の取り違い/未定義変数


8. キャッシュ/サーバーの基本もおさえる

  • ページキャッシュ:サーバー系(LiteSpeed Cacheなど)または WP Rocket / Cloudflare APO。

  • オブジェクトキャッシュ:Redis/Memcached(クエリの再計算を抑える)。

  • WP Cron をサーバーCronにDISABLE_WP_CRONtrue にし、5-10分間隔で wp-cron.php を実行。

  • DB/一時データの掃除:不要トランジェント・オプションを定期的に削除。


9. 計測のコツ:原因と効果をハッキリさせる

  • PSI/Lighthouse はモバイル計測でチェック(LCP/TBTに注目)。

  • 変更は1つずつ→計測→効果を見る。

  • LCP 画像は見つかったか」「遅延扱いされていないか」「fetchpriority が出ているか」を監視。

  • 画像は節度ある Preload(1枚)、JSはDefer+除外で安定化。


10. コピペ用・完成テンプレ(必要箇所だけ使ってOK)

10-1 LCP画像(背景のときは Preload)

// functions.php
add_action('wp_head', function () {
if (is_front_page()) {
echo '<link rel="preload" as="image" href="'.esc_url(get_template_directory_uri().'/images/hero.webp').'" imagesizes="100vw">'."\n";
}
}, 1);

10-2 画像タグに fetchpriority を自動付与(特定ID)

// 例:画像ID 12345 をLCP扱い(トップのみ)
add_filter('wp_get_attachment_image_attributes', function($attr,$attachment){
if (is_front_page() && (int)$attachment->ID === 12345) {
$attr['fetchpriority'] = 'high';
$attr['loading'] = 'eager';
$attr['decoding'] = 'async';
$attr['data-no-lazy'] = '1';
$attr['data-skip-lazy'] = '1';
if (!empty($attr['class'])) {
$attr['class'] = str_replace(['lazy','lazyload','lazyloaded','lazy-hidden'],'', $attr['class']);
$attr['class'] = trim($attr['class']);
}
}
return $attr;
}, 10, 2);

10-3 フッターに「ページ上へ」&最小JS

<!-- footer.php -->
<a href="#whole" class="page-top" aria-label="ページ上部へ"></a>
<?php wp_footer(); ?>
</body>
</html>
<script>
document.addEventListener('DOMContentLoaded',function(){
var btn=document.querySelector('.page-top'); if(!btn) return;
var showAt=200;
function toggle(){ (scrollY>showAt)?btn.style.display='flex':btn.style.display='none'; }
toggle(); addEventListener('scroll',toggle,{passive:true});
btn.addEventListener('click',e=>{e.preventDefault();scrollTo({top:0,behavior:'smooth'});});
});
</script>
/* 追加CSS */
.page-top{position:fixed;right:14px;bottom:14px;width:52px;height:52px;border-radius:9999px;background:#ff9800;color:#fff;display:flex;align-items:center;justify-content:center;box-shadow:0 4px 14px rgba(0,0,0,.18);z-index:10010}
.page-top::before{content:"▲";font-size:18px;line-height:1;transform:translateY(-1px)}

10-4 YouTube 軽量埋め込み(srcdoc

<iframe
loading="lazy" width="560" height="315" title="YouTube"
src="https://www.youtube-nocookie.com/embed/VIDEO_ID?rel=0&modestbranding=1&playsinline=1"
srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}
img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto;height:100%;object-fit:cover}
span{height:3em;line-height:3em;text-align:center;background:rgba(0,0,0,.5);color:#fff;font:700 1.2em sans-serif;left:0;right:0;width:40%;border-radius:.5em}</style>
<a href='https://www.youtube-nocookie.com/embed/VIDEO_ID?autoplay=1&rel=0&modestbranding=1&playsinline=1'>
<img src='https://i.ytimg.com/vi/VIDEO_ID/hqdefault.jpg' alt='動画プレビュー' loading='lazy'><span>▶ 再生</span>
</a>"
>
</iframe>

10-5 Async/Defer:壊れない除外例

Scripts to Exclude(例)

jquery.js, jquery.min.js, jquery-migrate.min.js,
common.min.js, main.js, shop.min.js

(実際のファイル名に置き換え)


11. ありがちな落とし穴チェックリスト

  • preloadindex.php に書いた→ 効果が出ない。<head>

  • LCP画像に loading="lazy" を付けている→ LCPが遅れる

  • LazyLoad プラグインが 2つ動いている→ 競合・非表示

  • Async(非同期)でjQueryが後回し→ 依存スクリプトが失敗。Defer+Exclude

  • wp_footer() がないテンプレートがある→ フックが走らない

  • YouTube を そのまま複数埋め→ CPUが数秒飛ぶ。軽量化に置換


12. まとめ:最小手数で“速く・壊れない”サイトへ

  1. LCPを最優先fetchpriority="high"、背景は preload<head>

  2. YouTubeは軽量化:クリックまで本体を読ませない

  3. Async/Deferは Defer+除外:jQueryと重要JSは Scripts to Exclude

  4. LazyLoadは1本化、LCPは遅延しない

  5. 「ページ上へ」ボタンは常時出力+最小JSで安定

この流れを押さえるだけで、表示の体感がガラッと改善し、アップデート後の事故も激減します。

サポートのご案内

各サポートに関するご質問など、お気軽にお問い合わせください

03-3562-7238営業時間10:00~19:00(土日祝除く)