シニアWebエンジニア M.H.
2026.7.3
Webサイトは構築完了すると、数か月で閉鎖するキャンペーンサイトでもない限り、多くは3~5年、長いと10年以上作った当初の環境を大きくは変更しない状態で運用していきます。
それはつまり制作した時代によく使われていた手法・ツール・ライブラリ・フレームワークとお付き合いし続けることになります。
そんなかつてはよく使われていたフロントのライブラリの一つがjQueryです。
意外とまだ見かけることがあるjQueryが使われたサイト。そんなサイトの運用・リニューアル時に遭遇したjQueryにまつわる様々な落とし穴を紹介します。
ページ内のバナーAを削除したら、関係ない場所の別のバナーBが表示されない、という現象が起きました。
調べると、どうやらバナーAの画面位置をトリガーにバナーBを表示する、という仕組みになっていたため、トリガーとなるバナーAを削除したので表示されなくなった、というのが判明しました。
本来ならバナーAを削除したら、バナーAの要素の取得時にエラーが出て欲しいものです。
しかし、jQueryでは存在しない要素であっても空のjQueryのオブジェクトを返すため、プロパティにはアクセスできてしまうため、エラーが出てなかったのでした。
$(function() {
// #sample01はDOM上に存在しない要素
const sample01 = $('#sample01');
// 空のjQeuryオブジェクト(lengthプロパティが0で、jQueryのprototypeを持つ)
console.log('存在しない要素', sample01);
// prototypeのプロパティとしては存在するのでエラー出ない
console.log('存在しない要素のテキスト', sample01.text());
// これもエラーにならない
sample01.on('click', function() {
console.log('存在しない要素はクリックできません');
});
// 代入時にチェックすればエラーを出すようにできる
const sample01_checked = $('#sample01').length ? $('#sample01') : null;
// これはエラーになる
console.log('存在しない要素のテキスト', sample01_checked.text());
});
もしかしたら、このあたりの緩さが広く受け入れられた要因の一つなのかもしれません。
リニューアル前のサイトではjQueryが使用されていたのですが、リニューアルを機にjQueryなしで構築をしました。
現サイトのGTMの埋め込みコードを移植したところ、Chromeのデベロッパーツールのコンソールに「$ is not function」のエラーが。
GTMの埋め込みコードを消すと出なくなるため、どうやらGTMから出力されている何らかのコード(カスタムHTML もしくは カスタムJavaScript)が原因のようです。(カスタムHTML・カスタムJavaScript共にそのままのコードで記載されていないので解析はできませんでした)
サイトの方にjQueryを読み込んだところ、無事エラーは出なくなりました。
こちらではGTMを設定できない案件だったため、仕方なくGTMのためだけにjQueryを残したのでした。
一昔前は猫も杓子もjQueryだったため、解析用ツールなどサイトに自動的に読み込まれるスクリプトはjQuery前提で記載されている可能性がある、ということを念頭に置いておくと良いかもしれません。
運用中サイトに新規でキャンペーンLPを追加したいが、ヘッダー・フッター等の共通パーツは既存ページに合わせたい、というような案件がありました。
共通パーツはHTMLだけでなく、CSS・JSも読み込むことになります。長年運用されていたサイトだっため、jQueryのバージョンが1系になっていた、ということがありました。
当時はjQueryが3系の時代で、当然3系ベースで作っていたため、いざ組み込んで正常に動くのか?という懸念がありましたが、3系でしか使用できない機能を使っていなかったため、問題ありませんでした。
この時は1系だけにすることで上手くいったのですが、jQueryは複数バージョンを混在させることもできるので、この方法を取ってもよかったかもしれません。
<div id="target1">target element for jQuery 1.x</div>
<div id="target2">target element for jQuery 3.x</div>
<!-- 1系を読み込み -->
<script src="<https://code.jquery.com/jquery-1.12.4.min.js>"></script>
<script>
// 1系を退避(window.$ / window.jQuery から切り離す)
window.$jq1 = jQuery.noConflict(true);
</script>
<!-- 3系を読み込み -->
<script src="<https://code.jquery.com/jquery-3.7.1.min.js>"></script>
<script>
// 3系を退避(window.$ / window.jQuery から切り離す)
window.$jq3 = jQuery.noConflict(true);
</script>
<script>
// ここでwindow.$ / window.jQuery は未定義のはず
console.log("window.$:", window.$);
console.log("window.jQuery:", window.jQuery);
// 無名関数内にそれぞれのjQueryを渡して、$をそのまま使えるようにする
(function($) {
console.log("jq1 version:", $.fn.jquery);
$('#target1').css('background-color', 'yellow');
})($jq1);
(function($) {
console.log("jq3 version:", $.fn.jquery);
$('#target2').css('background-color', 'cyan');
})($jq3);
</script>
わざわざこのようなことはせずに、今なら追加するLPの方はjQueryなしで作るのが最適解かと思います。
様々な人が引き継いできた歴史あるJavaScriptのコードは、様々な書き方をしてあります。
下記のようなコードに、要素element3に対して何か処理を追加する場合、どちらの書き方にすべきか、というのが困るところです。
var ele1 = $('.element1');
ele1.on('click', function(){
console.log('click element1');
});
const ele2 = document.querySelector('.element2');
ele2.addEventListener('click', () => {
console.log('click element2');
});
// こうする?さすがにvarはやめとく?
var ele3_jquery = $('.element3');
// それともこっち?
const ele3_plain = document.querySelector('.element3');
その他の部分もいろいろと記載方法が混在しているので、jQueryだけの問題でもないのですが。
テストを適切に行えるなら、どちらかの記載に統一するようにAIを使って変換するのがよいかもしれません。
以上、遭遇したJQueryの落とし穴たちでした。
どれもそんなに深刻なことにはならないものですが、知らないと意外と対処に時間が取られたりします。
ブラウザの互換性問題、アニメーションやAJAXなどの機能追加のために使われてきたjQueryは、ブラウザの互換性問題の解消、素のJavaScriptやCSSの機能が充実してきたことよって役目を終えつつあります。
しかし、運用歴の長いサイトやCMSなどに組み込まれていたりと、まだまだ残っていくことにはなりそうです。(jQuery4も出たことですし)
関連する記事
この人が書いた記事