次のHTMLコードがあります。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.jsdelivr.net/blazy/1.8.2/blazy.min.js" defer></script>
<script src="https://code.jquery.com/jquery-2.1.4.min.js" integrity="sha256-8WqyJLuWKRBVhxXIL1jBDD7SDxU936oZkCnxQbWwJVw=" crossorigin="anonymous" defer></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lightbox2/2.9.0/js/lightbox.min.js" defer></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous" defer></script>
<!-- 26 dec flexslider js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/flexslider/2.6.3/jquery.flexslider.min.js" defer></script>
<script defer>
(function($) {
$(document).ready(function() {
//do something with b-lazy plugin, lightbox plugin and then with flexslider
});
})(jQuery);
</script>
</head>
<body>
</body>
</html>
JQueryが定義されていないというエラーが表示されます。インラインJSコードからdeferを削除しても、jQueryは未定義です。何らかの理由で、jQueryプラグインを頭に入れて、JSコードをインラインにしておく必要があります。私の質問は:
defer
属性が存在する場合、インラインJavascriptコードが遅延しないのはなぜですか?
インラインJavascriptコードの遅延動作を模倣する方法はありますか?必要に応じて、bodyタグの最後に配置できます。
defer
属性を持つスクリプトは指定された順序でロードされますが、前ではなくドキュメント自体がロードされました。 defer
は、script
属性も持たない限り、src
タグに影響を与えないため、最初に実行されるスクリプトはインラインスクリプトです。そのため、その時点ではjQueryはまだロードされていません。
これは少なくとも2つの方法で解決できます。
インラインスクリプトを.js
ファイルに配置し、src
属性(既にあるdefer
属性に加えて)を使用して参照するか、または
ドキュメントと遅延スクリプトがロードされるまで、インラインスクリプトを待機させます。 DOMContentLoaded
イベントは、それが発生すると起動します:
<script>
window.addEventListener('DOMContentLoaded', function() {
(function($) {
//do something with b-lazy plugin, lightbox plugin and then with flexslider
})(jQuery);
});
</script>
注意:後者の場合、$(document).ready(function()
はもう含まれないことに注意してください。これは同じイベント(DOMContentLoaded
)を待つためです。 couldは元のコードと同じようにそれを含めますが、jQueryはコールバックを実行するだけですimmediatelyで、実際の違いはありません。
スクリプトからBase64 URLを作成し、srcに配置できます!
<script src="data:text/javascript;base64,YWxlcnQoJ0hlbGxvIHdvcmxkIScpOw=="
defer>
</script>
動作を確認する簡単なテストを作成しました。 defer
が機能している場合は、Hello world!
lastのアラートが表示されます。
<script defer>
alert('Why no defer?!?');
</script>
<!-- alert('Hello world!'); -->
<script src="data:text/javascript;base64,YWxlcnQoJ0hlbGxvIHdvcmxkIScpOw=="
defer></script>
<script>
alert('Buh-bye world!');
</script>
手動で行うのは少し面倒ですので、HTMLを何らかの方法(ハンドルバー、Angularなど)でコンパイルする余裕がある場合は、非常に役立ちます。
私は現在使用しています:
<script src="data:text/javascript;base64,{{base64 "alert('Hello world!');"}}"
defer>
</script>
MDNドキュメントから:
遅延
このブール属性は、ドキュメントが解析された後、DOMContentLoaded
を起動する前にスクリプトが実行されることをブラウザに示すために設定されます。 defer属性は外部スクリプトでのみ使用する必要があります。
これはIIFE(Immediately Invoked Function Expression)と呼ばれ、DOMが利用可能になる前に実行されます。したがって、その場合、jQuery
はDOMにないため未定義です。
#noLib #vanillaJS
クロスブラウザPRODuctionで使用しないことを推奨
mS IEが消滅し、MS EdgeがChromiumオープンソースを採用するまで;)
spec script#attr-defer(MDN web docs) :「src属性が存在しない場合(インラインスクリプトの場合)、この場合は使用しないでください。この場合、効果はありません。」
spec Data_URI
正しいtype "text/javascript"を使用する必要はありませんbase64まったく...;)
プレーンテキストを使用するので、シンプルを使用できます:
<script defer src="data:text/javascript,
//do something with b-lazy plugin, lightbox plugin and then with flexslider
lightbox.option({
resizeDuration: 200,
wrapAround: true
})
">
はい、それは少し奇妙なハックですが、<script type="module">
はデフォルトで延期され、正確な順序でmixする他のオプションはありません:
<script src=".." async defer>
を使用(またはJSから行う場合はsrc
を割り当てる前にscript.async = true
を設定)および/またはページの一番下にスクリプトを配置する必要があるという一般的な知識があります。 、可能な限り高速にページがロードされ、ユーザーにレンダリングされるようにします。
defer.js (注:私はこのスクリプトの著者です)プレーンJavaScriptで記述されており、遅延読み込みを他のコンテンツはより高速でパフォーマンスが向上します。インラインスクリプトブロックと同様に、javascriptファイルを効率的に延期できます。
ページがJavaScriptで強化されたHTMLページである場合は、<script async>
だけで十分です。ブラウザがこれらのスクリプトを解析して実行するのに時間がかかります。UIを変更するたびにレイアウトがリフローし、ロード速度が遅くなります。ユーザーは短気で、すぐに離れます。
さまざまなケースで、async
またはdefer
を使用しても、 defer.js よりも速いページ速度は得られません。