Laravel6にBootstrap、jQueryを入れたはずが、動作しない。
ReferenceError: $ is not defined
という$がないっていう、jQueryファイルを読み込ませるのを忘れてたっていうやりがちな失敗時に起こるエラーです。
だがしかし、Larabelのデフォルトテンプレート(views/layouts/app.blade.php)から読まれている/js/app.jsを確認してみると確実にjQueryが読み込まれており、$is not definedなはずがねぇ!!のですが、エラーは無慈悲にも出続け・・・。
1時間くらいはまったのちに解決したので、備忘録を残しておきます。
原因:scriptタグのdefarによるもの
今回のエラーを簡易的にテストするためにbody直下に
<script>
$(function() {
alert(‘jQuery’);
});
</script>
「jQuery」という文字列をアラート表示するだけの簡単なスクリプトをおきました。
デフォルトテンプレートに記載されているjsファイル読み込みのscriptタグには、defar属性が付与されています。
<script src="{{ asset('js/app.js') }}" defer></script>
このdefar属性がついていることで、app.js内のスクリプトはDOMの解析が終了してから実行されます。
そのため、テストスクリプトのようなインラインスクリプトが実行される時点ではdefar属性が指定されたapp.jsが実行されていないためにエラーが出る、という単純な原因でした。
app.jsが実行されていない、ということは、app.jsに記載されたjQueryももちろん実行されていない。
そりゃエラー出るか。ということを1時間悩みました。
解決策 type=moduleを付与
解決策として、defarが原因ならscriptタグのdefarを削除すればいいわけで、確かに取ると、上記ソースのインラインスクリプトは正常に実行されjQueryとアラートが表示されます。
ですが、defar属性のメリットの恩恵も捨てることになるため、削除以外の解決方法を検討することに。
結果、インラインスクリプトのtype属性にmoduleを指定することで解決することにしました。
scriptのtype属性にmoduleなんて値が指定できることを知らなかった。。。
moduleってなんだろう・・・ということで参考にしたページを置いておきます。
参考
MDN web docs 「script要素」
MDN web docsのscript要素の仕様
defarやtype属性、type属性の値などが記載されているので参考になります。
https://developer.mozilla.org/ja/docs/Web/HTML/Element/Script
これを見てみると、IEは非対応のようです。
その他ブラウザでの実際の動作はまだ確認してませんが、とりあえず、下記環境では問題なし。
・win Firefox 75.0
・win Chrome 81.0.4044.113
いずれも64ビット版
・iPhone safari 13.1
type=”module”を指定した時の実行の流れ
WHATWGの読み込み概略図を見てみると、type属性にmoduleを指定した場合の実行タイミングが分かります。
外人 says
天才!