【解決】Lightningテーマでモバイルメニューボタンが機能しない問題

おしらせ

この記事は、Claudeによって執筆されました。

WordPressのLightningテーマで、スマホ表示の「MENU」ボタン(ハンバーガーメニュー)をタップしても何も反応しない——。

この記事では、その原因と直し方を実際の調査に基づいてまとめます。結論から言うと、テーマのバグではなくCloudflareの「Rocket Loader」が犯人でした。

症状

  • スマホ幅(モバイルビュー)で左上の MENU ボタンをタップしても、ナビゲーションが開かない
  • ボタン自体は表示されていて、押した感触もあるが、メニューがスライドインしてこない
  • PC表示のメニューやページ内リンクは正常
  • ブラウザのコンソールにエラーは出ない(ここが厄介なポイント)

該当するボタンのHTMLはこれです。

<div id="vk-mobile-nav-menu-btn" class="vk-mobile-nav-menu-btn">MENU</div>

原因を一発で見抜くチェック

ページのソースを表示し、Lightningの main.js<script> タグを探してください。**正常なら type は付かない(または text/javascript)**ですが、壊れている環境ではこうなっています。

<script id="lightning-js-js"
        src="/wp-content/themes/lightning/_g3/assets/js/main.js"
        type="9b4721faa21ebd07019f6273-text/javascript"></script>

type="ランダムなハッシュ-text/javascript" ——これは Cloudflare Rocket Loader が付ける署名です。この形が見えたら、ほぼ確定です。レスポンスヘッダーに server: cloudflare / cf-ray: があるかも併せて確認しておくと確実です。

なぜ「ボタンだけ」効かないのか

Lightningの main.js は、モバイルメニューの初期化をこう書いています(要点を抜粋)。

window.addEventListener('DOMContentLoaded', function () {
  var menuBtn = document.getElementById('vk-mobile-nav-menu-btn');
  var menu    = document.getElementById('vk-mobile-nav');
  if (!menuBtn || !menu) { return; }
  menuBtn.addEventListener('click', function () {
    // menu-open / vk-mobile-nav-open クラスを付け外しして開閉
  });
});

DOMContentLoaded を待ってからボタンにクリック処理を登録する、ごく標準的な書き方です。

ところが Rocket Loader は、スクリプトを本来の読み込みタイミングから外し、DOMContentLoaded が発火した後に非同期で実行します。すると上のコードは、もう終わってしまったイベントを待ち続けることになり、コールバックが永遠に呼ばれません。結果、ボタンにクリック処理が付かず「押しても無反応」になります。

エラーが出ないのは、例外が起きているのではなく「リスナーが手遅れで登録され、ただ発火しないだけ」だからです。

ちなみに同じ main.js 内でも、ヘッダーのスクロール処理は正常に動きます。そちらは次のような「もう読み込み済みなら即実行する」フォールバックが入っているためです。

'loading' !== document.readyState
  ? init()
  : window.addEventListener('DOMContentLoaded', init);

モバイルメニューとアコーディオン(サブメニューの▼)にはこの保険が無いので、そこだけ壊れる、というわけです。

直し方

案1:Rocket Loader を無効化する(最も確実・おすすめ)

Cloudflareダッシュボード → 対象ドメイン → Speed → 設定 → コンテンツの最適化(タブ) → Rocket Loaderオフ にします。

このページの下の方にあります

Rocket Loader は DOMContentLoaded 依存のスクリプトを壊しやすく、Cloudflare公式も注意喚起している機能です。体感速度への寄与も限定的なので、思い切って切ってしまうのが手っ取り早い解決策です。

案2:main.js だけ Rocket Loader の対象外にする

「他のスクリプトの遅延は残したい」場合は、data-cfasync="false" を付けたスクリプトだけ Rocket Loader が無視する仕様を使います。子テーマの functions.php に以下を追加してください。

add_filter('script_loader_tag', function ($tag, $handle) {
    if ($handle === 'lightning-js') {          // main.js のハンドル
        $tag = str_replace('<script ', '<script data-cfasync="false" ', $tag);
    }
    return $tag;
}, 10, 2);

案3:Configuration Rule で特定URLだけ無効化

ダッシュボードの全体設定を触りたくない場合は

Cloudflareダッシュボード → 対象ドメイン → ルール → ページ ルール

で「ページルールを作成」から対象URLの Rocket Loader だけ Off にする方法もあります。

確認方法

修正後、ページのソースで main.jstype からハッシュが消え、普通の text/javascript(または type 無し)になっていればOKです。あとはブラウザのデバイスモード(狭い画面幅)で MENU をタップし、メニューがスライドインすれば解決です。

補足:LiteSpeed Cache を使っている場合

同様の「JS遅延実行」機能は LiteSpeed Cache の "Delay JS" にもあります。今回の原因は Rocket Loader でしたが、将来 LiteSpeed 側で Delay JS を有効にすると同じ理由で再現するかもしれません。

その場合は LiteSpeed の除外設定にも main.js を追加してください。

まとめ

  • 症状:スマホの MENU ボタンが無反応、コンソールにエラーは出ない
  • 見分け方:main.jstype="ハッシュ-text/javascript" を探す
  • 原因:Cloudflare Rocket Loadermain.jsDOMContentLoaded 後に実行し、メニュー初期化が発火しない
  • 対処:Rocket Loader を切る/data-cfasync="false" で main.js を除外する

「テーマが壊れた」と思っても、実際はCDN/キャッシュ系の最適化機能とJSの実行タイミングの相性が原因、というのはよくあるパターンです。エラーが出ないタイプの不具合こそ、type 属性のような“署名”から犯人を絞り込むのが近道です。

コメントを残す