Defer.js ドキュメント (日本語訳)
Defer.js は、Shin さんが作成したインラインでも わずか1.81KByteの「遅延ロード」JavaScriptライブラリの決定版‼️
個人用の資料として Version: 3.6.0 の 英語ドキュメント を翻訳しましたので、ついでに公開。(2023/03/22 commit版を翻訳)
なお、このドキュメントの著作権は Shin さんのもので、サンプルコードはオリジナルのまま転載させて頂きます。
機械翻訳された文章を手直ししていますが、不可解な場合は オリジナルの英語ドキュメントを参照してください。
defer(遅延ロード)機能に加え、 Version: 3.2.0 以降 Defer.all() メソッドに リソース(プリロード)ヒント 機能が追加されました❗️
現在のWeb技術では、「遅延ロード」と「リソース(プリロード)ヒント」の組み合わせが最も効果的な選択肢らしいです。
また、Shin さんは WordPress用の「遅延ロードプラグイン」や「遅延ロードPHPライブラリ」なども公開中。
「 Defer.js 使い方(利用方法)」の記事も、当サイトにて 2023/03/03 公開 しました。
(注)オレンジ色のコメントは、翻訳者が追加したもの
Package @shinsenter/defer.js
🥇 Defer.js は、JavaScriptのマイクロライブラリで、(ほとんど)あらゆるものを遅延ロードさせることができます。
Defer.js は依存性ゼロ、超効率的、そして Webバイタル に貢献します‼️
はじめに
大きなCSSファイル、遅いJavaScript、重いメディアリソースの遅延は、ウェブサイトの Webバイタル の問題を引き起こし、遅くてイライラするユーザーエクスペリエンスにつながります。
しかし、これらのリソースを完全に遅延させ、ウェブサイトの読み込み速度を向上させることができるとしたらどうでしょう?
Defer.js を利用することで、これらの問題を解決できます!
遅延ロード機能、依存性のないデザイン、高速なパフォーマンス、そして蓄積された実績を持つ Defer.js は、あなたのウェブサイトのWebバイタルを最適化するための完璧なソリューションです。
Defer.js を利用することで、モダン・ブラウザでもレガシー・ブラウザでも、高速なロード時間により、ウェブサイトのユーザーエクスペリエンスを向上させることができます。
英語以外のドキュメント
【手助けが必要です】一緒に、ドキュメントやサンプルを より良いものにしましょう‼️
日本語
日本人の方は、以下の記事を参考にしていただければ幸いです。
- この日本語訳記事
- あトんさんの記事
- りもさんの記事
謝辞
アタルさん、あトんさん、りもさん、日本語記事の執筆 ありがとうございます!
ライブラリの概略
Defer.js選択のメリット
- 🧩 ほとんど何でも簡単に、遅延ロードできる
- 🚀 軽量で高速、依存性がない
- 🤝 お気に入りのフレームワークに、楽々と統合できる
- 🔰 初心者の方でも簡単に使える
- ⚡️ 超小型( minzip サイズなら、約1KByte )
- 🦾 最新の「Webバイタル」標準に準拠
- 📱 スマートフォンでの利用に最適化
- ✅ Internet Explorer 9 などのレガシー・ブラウザをサポート
※ Internet Explorer 9 などのレガシー・ブラウザの場合、 IntersectionObserver polyfill ライブラリ が必要です。
サポートするブラウザ
Defer.jsは、以下のすべてのモダン・ブラウザに対応しています。
- 🖥 IE 9以上 / Edge
- 🖥 Firefox 4以上
- 🖥 Safari 3以上
- 🖥 Chrome
- 🖥 Opera
- 📱 Android 4以上
- 📱 iOS 3.2以上
判明している問題点
Discussion #122:iOS の Safari で、 waitForUserAction 引数 true 状態で Defer.all() メソッドを実行し、遅延したスクリプトの1つが DOM 変更を行った場合、最初の click イベントが動作しない場合があります。
ライブラリの使い方
Defer.js は、ローディング時間を短縮することで、ウェブサイトのパフォーマンスを向上させることができる使い勝手の良いライブラリです。
ここでは、その使い方を説明します。
CDNを利用して「JSライブラリ・ファイルをロードする方法」が簡単ですが、慣れている方は「インライン化」がオススメです!
CDN ( jsdelivr )
Defer.jsライブラリをあなた方のサイトに追加するには、<head> 要素内の最初の方で、 <script> 要素(以下6行め)を 挿入します。
<head>
<meta charset="UTF-8" />
<title>My Awesome Page</title>
<!-- Add Defer.js here -->
<script src="https://cdn.jsdelivr.net/npm/@shinsenter/defer.js@3.6.0/dist/defer.min.js"></script>
<!-- ... -->
</head>
ライブラリのインライン化
HTTPリクエストを節約するために、defer.min.js から全テキストをコピーして、以下6行めの「script要素内のコメント( /* 〜 */ )」と置き換えることで、Defer.jsライブラリ全体をインライン化することも可能です。
(とてもコンパクトなファイルサイズ 1.81KByte に最適化済み)
<head>
<meta charset="UTF-8" />
<title>My Awesome Page</title>
<!-- Add the Inlined Defer.js here -->
<script>/* Defer.js content goes here */</script>
<!-- ... -->
</head>
旧バージョンとの互換性
古いバージョンの Defer.js を使用している場合、defer.min.js の代わりに defer_plus.min.js が利用可能です。
<head>
<meta charset="UTF-8" />
<title>My Awesome Page</title>
<!-- Put defer_plus.min.js here -->
<script src="https://cdn.jsdelivr.net/npm/@shinsenter/defer.js@3.6.0/dist/defer_plus.min.js"></script>
<!-- ... -->
</head>
古いブラウザ(IE9など)の場合
IntersectionObserver 機能をサポートしていないレガシー・ブラウザのパフォーマンスを向上させるには、defer.min.js スクリプト要素の後で 「IntersectionObserver polyfill」ライブラリをロードしてください。(以下4行め)
<script>/* Defer.js content */</script>
<!-- Add the IntersectionObserver Polyfill for legacy browsers -->
<script>'IntersectionObserver'in window||document.write('<script src="https://cdn.jsdelivr.net/npm/@shinsenter/defer.js@3.6.0/dist/polyfill.min.js"><\/script>');</script>
(注)モダン・ブラウザは IntersectionObserver 機能をサポートしているので、IE9のようなレガシー・ブラウザを考慮しなければ、polyfill の追加は必要無いでしょう。
IntersectionObserver 機能をサポートしているブラウザの場合、document.write() 以降のコードは実行されません。
当ライブラリをインライン化した場合は、一組の <script>タグと </script>タグの間に Defer.js コードと IntersectionObserver polyfill library コードを入れても 問題ありません。
関数の一覧
[param] カギカッコ付きの パラメータ(引数)は、省略可能
後の方のパラメータのみを指定する場合、指定しない途中のパラメータには「初期値(初期値が無い場合は null )」をセット
- Defer(func, [delay], [waitForUserAction]) ⇒ void
- .lazy : boolean
- .all([selector], [delay], [waitForUserAction]) ⇒ void
- .dom([selector], [delay], [unveiledClass], [resolver], [observeOptions]) ⇒ void
- .css(fileUrl, [id], [delay], [onload], [waitForUserAction]) ⇒ void
- .js(fileUrl, [id], [delay], [onload], [waitForUserAction]) ⇒ void
- .reveal(node, [unveiledClass]) ⇒ void
defer(func, [delay])deferimg([selector], [delay], [unveiledClass], [resolver], [observeOptions])deferiframe([selector], [delay], [unveiledClass], [resolver], [observeOptions])deferstyle(src, [id], [delay], [onload])deferscript(src, [id], [delay], [onload])
取り消し線 付きのメソッドは、廃止されました。
( defer() メソッドは、メソッド名を Defer() に変更 )
型の定義
Defer(func, [delay], [waitForUserAction]) ⇒ void
DOM を大量に操作すると、実際のシナリオではレンダリングブロックの問題が発生することがあります。
Defer() メソッドでスクリプトをラップすることで、レンダリングブロックの問題を回避できるかもしれません。
種類: global function
適用: Version 2.0〜
パラ は、「パラメータ」の略です
パラ | 型 | 初期値 | 説明 |
---|---|---|---|
func | 関数 | ページが完全にロードされた後に実行される関数 | |
[delay] | 数値 | 0 | 関数実行まで待機する時間(ミリ秒) |
[waitForUserAction] | 真偽 | false | ユーザーとの対話があるまで、Defer()メソッドが実行を待つかどうか? |
例A JS関数1
jQuery を利用した、幾つかの DOM 操作を実行する例です。
このサンプルは、ページの読み込みが終わるとすぐに、<pre><code></code></pre> ブロックをドキュメントに添付します。
<script>
function generate_code_blocks () {
$('.demo').each(function() {
var code = $('<pre><code class="language-html"></code></pre>');
var demo = $(this);
var html = demo.html().trim().replace(/ {4}/g, ' ');
code.children().text(html);
demo.append(code);
});
}
Defer(generate_code_blocks, 0);
</script>
Defer() メソッドを利用すれば、ファイルだけではなく 関数の実行も遅延可能です。
ページが完全にロードされるまで保留後、さらに「指定ミリ秒」経過してから、指定した関数が実行されます。
6行め:demoクラスを付けた要素のテキストを加工(前後の空白を削除後、途中の4つの空白を 2つの空白で置換)
8行め:4行めの <pre><code></code></pre> ブロック内に、6行めの加工したテキストを挿入
9行め:demoクラスを付けた要素に、8行めの <pre><code></code></pre> ブロックを追加
例B JS関数2
時には、ユーザーがアクションを起こさない限り、コードを実行させないようにしたいこともあるでしょう。
3番目の引数は、ユーザがページの操作を始めるまで、Defer() に指定した関数の実行を遅らせるよう 指示します。
<style>
body.moving {
background: linear-gradient(270deg, #ffffff, #e8f0c3, #ccf0c3);
background-size: 600% 600%;
animation: moving_bg 30s ease infinite;
}
</style>
<script>
function make_background_animate() {
// jQuery is used in this example to attach a class to the <body> tag.
// You won't see the animated background until you start interacting.
$('body').addClass('moving');
}
Defer(make_background_animate, 0, true);
</script>
jQuery 利用例です。
スクロールなど ユーザーがアクションを起こすと、(「指定ミリ秒」経過後に)<body> 要素に「moving」CSSクラスが追加されるため、body.moving に記述したCSS効果が反映されます。
Defer.lazy : boolean
Defer.lazy 変数は、Version 3.0 から追加されました。
Defer.lazy=true を設定すると、ページロードイベントに関係なく、ユーザがページとの対話を開始するまで、遅延スクリプトの実行を遅らせるよう、ライブラリに指示します。
これは、Defer() メソッドの 、waitForUserAction 引数のデフォルトの動作をオーバーライドします。
この変数を true に変更すると、以下3メソッドの動作にも影響を与えます。
つまり、waitForUserAction 引数の初期値が false から true に変更されます。
種類: Defer の 静的プロパティ(インスタンスを生成しなくてもオブジェクトから直接呼び出せるプロパティ)
初期値: 未設定
アクセス: Public
適用: Version 3.0〜
例C Defer.lazy変数
Defer() メソッドのデフォルトの動作をオーバーライドするため
<!-- You can put this right below the script tag containing defer.min.js -->
<script>Defer.lazy = true;</script>
defer.min.js を組み込んだ script要素の直後に、記述すること!
Defer.all([selector], [delay], [waitForUserAction]) ⇒ void
遅いスクリプト(サードパーティのライブラリ、アドオン、ウィジェットなど)は、実際のシナリオで Webバイタル の問題を引き起こす可能性があります。
<script> 要素を完全に遅延させることで、あなたのサイト上で Webバイタルの問題を回避できます。
<script> 要素の type 属性を "deferjs" に設定することで、対象の <script> 要素すべてを 完全に遅延させることができます。
この仕掛けは、src 属性を持つ <script> 要素でも完全に機能します。
(注1)Defer.all() メソッドで <script> 要素の実行を遅延させる場合、予期しない挙動を避けるため、正規( type 属性指定無し、あるいは type="text/javascript" )の <script> 要素内で Defer.all() メソッドを、呼び出ししてください。
(注2)Defer.lazy=true または waitForUserAction=true を設定した場合、Version 3.0から遅延ロードの挙動が変更されました。
type="deferjs" 指定の <script> 要素は、ユーザーがページの操作を開始しない限り実行されません。
(注3)Version 3.2以降、「 Taming the Waterfall 」問題の解決方法として推奨されている「 リソース(プリロード)ヒント 」機能が、追加されています‼️
この機能の詳細は、Discussion #112 で説明しています。
(注4)判明している問題点:iOS の Safari で、 waitForUserAction 引数 true 状態で Defer.all() メソッドを実行し、遅延したスクリプトの1つが DOM 変更を行った場合、最初の click イベントが動作しない場合があります。
詳しくは、「Discussion #122」をご覧ください。
ブラウザはユーザーがクリックするつもりなのか、ダブルタップしているのかを瞬時に把握することができません。 そのため、iOS(iPadOS)の Safari では、ユーザーがもう一度タップするかどうかを確認するために、タップ操作に300ミリ秒の遅延を加えています。
そのため、次のように Defer.all() 関数で 300ミリ秒以上 遅延 すれば解決できるそうです。
Defer.all('script[type="myscript"]', 500, true);
(上記リソース(プリロード)ヒントのリンク通り)ファイル単位のプリロードは <head> 要素内に記述するだけで利用可能なため、(ファイルサイズが大きめの JS / CSSファイルなどを)手動で追加も簡単です。
なお、PageSpeed Insights 数値が低下しない事も確認済みです!
type 属性を指定した <script> 要素内で、別の type 属性を指定した Defer.all() メソッドの呼び出しは(期待通りの順序で実行されない可能性があるため)オススメできません!
Defer.js() と Defer.css() は非同期(実行順序が不明)で対象スクリプトが実行されますが、Defer.all() では 同期実行 されます。
type="deferjs" 属性を指定した <script> 要素のグループと、type="your-group" 属性を指定した <script> 要素のグループ、つまり複数の type 属性を指定した <script> 要素のグループが存在する場合を考えてみましょう。
<script> 要素のグループは、独立して実行されます!
各グループの <script> 要素は、他のグループの <script> 要素に依存することなく、グループ内の順序で実行されます。
種類: Defer の 静的メソッド(Global)
適用: Version 2.0〜
パラ | 型 | 初期値 | 説明 |
---|---|---|---|
[selector] | 文字列 | '[type="deferjs"]' | 遅延ロード対象の <script> 要素を指定する、 CSSセレクタ 初期値は「type属性が"deferjs"で完全一致」 |
[delay] | 数値 | 0 | 対象 <script> 要素が実行されるまでの、待ち時間(ミリ秒単位) |
[waitForUserAction] | 真偽 | false | ユーザーとの対話があるまで、Defer.all() メソッドが 対象 <script> 要素の実行を待つかどうか? |
CSSセレクタ チートシート(図解で解りやすいですが、部分一致と前方一致の2箇所のコードが間違ったままですね)
例D type="deferjs"
<script> 要素で type="deferjs" 属性を利用するだけで、遅延実行が可能です‼️
適用前:
<script type="text/javascript">
// your JavaScript is here
console.log('This script is a normal script tag.');
</script>
(HTML5以降、type属性指定を省略して)<script> のみでも、JavaScript と認識されます。
適用後:
<script type="deferjs">
// your JavaScript will still be here,
// but it will not run unless the user starts interacting with your page.
console.info('This script is lazy loaded with type="deferjs" attribute.');
</script>
(複数の)type="deferjs" 属性の <script> 要素のみが遅延対象の場合、Defer.all() メソッドを記述する必要はありません。
例E インラインJS
type="my-magic" のように、type 属性に お好きな文字列も利用可能。
type="deferjs" 属性を使うのが嫌な場合、Defer.all() メソッドを記述して遅延対象の<script>要素を指定できます。
(注)Defer.all() メソッドで <script> 要素の実行を遅延させる場合、予期しない挙動を避けるため、正規( type 属性指定無し、あるいは type="text/javascript" )の <script> 要素内で Defer.all() メソッドを、呼び出ししてください!
<script type="my-magic">
// your JavaScript will still be here,
// but it will not run unless the user starts interacting with your page.
console.log(
'This script is lazy loaded with type="my-magic" attribute ' +
'5 seconds after the user started interacting with your page.'
);
</script>
<!-- Place the below line after all other script tags -->
<!-- The 2nd argument means those script tags will be delayed 5000ms -->
<script>
Defer.all('script[type="my-magic"]', 5000);
</script>
12行め:「正規の JavaScript <script> 記述」推奨のため、(簡単な方法として)type属性を省略
13行め:CSSセレクタ type属性が"my-magic"と完全一致のscript要素を指定
例F JSファイル
src 属性を持つ<script>要素を、Defer.all() メソッドにて利用する例:
以下サンプルのように、インライン<script>と src属性を持つ<script>要素を混在させても、あなたのスクリプトは完璧に動作します!
waitForUserAction 引数(第3引数)を true に設定すると、ユーザーが対話を始めるまで「tippy.jsライブラリ」と「tippy関数の実行」を遅延ロードし、ユーザーがボタン上にマウスを移動すると、ツールチップが表示されます。
(注)Defer.all() メソッドで <script> 要素の実行を遅延させる場合、予期しない挙動を避けるため、正規( type 属性指定無し、あるいは type="text/javascript" )の <script> 要素内で Defer.all() メソッドを、呼び出ししてください!
<button id="tooltip-button">My button</button>
<script type="myscript" src="https://unpkg.com/@popperjs/core@2"></script>
<script type="myscript" src="https://unpkg.com/tippy.js@6"></script>
<script type="myscript">
tippy('#tooltip-button', { content: 'Hello from Defer.js!' });
</script>
<script>
Defer.all('script[type="myscript"]', 500, true);
</script>
Tippy.js (v6) 利用方法 の通り、CSSの content プロパティに任意の文字列を設定するだけで、ツールチップがマウスオーバー(デフォルト)時に表示されます!
10行め:「正規の JavaScript <script> 記述」推奨のため、(簡単な方法として)type属性を省略
11行め:type="myscript" を持つ <script> 要素が、同期実行(順番通り実行)されます。
Defer.dom([selector], [delay], [unveiledClass], [resolver], [observeOptions]) ⇒ void
Defer.dom() メソッドは、以下のような利用例で役立ちます!
- 画像、メディア、iframe要素などを、あなた方のWebサイトで遅延ロードする
- サードパーティのライブラリやアドオンを、必要な時だけダウンロードする
- 要素のブロックがビューポート領域に入ったときに、AJAXで更新を処理するようなスクロール公開機能を提供
- Defer.dom() によって遅延された要素は、ページの読み込みが終了するのと同時に、アンベールされます
Defer.dom() メソッドによって遅延された要素は、その要素がブラウザのビューポート領域に入ったとき(入る直前も指定可能)にアンベールされます。
また、Defer.dom() メソッドは、要素の data-* 属性を 非データ属性に変換します。
(例)data-src を src に変換
詳しくは、以降のサンプルを参照してください!
アンベール:日本語では「ベールを脱ぐ」「ベールを剥がす」と訳され、覆い隠していた正体や真相を明かす(真相が明かされる)時に利用されます。
遅延ロードによって仮の画像やテキストなど(あるいは空白)が表示されていた箇所が、遅延後に意図した表示や動画再生が行われることを、「アンベール」と表現しているようです。
種類: Defer の 静的メソッド(Global)
適用: Version 2.0〜
パラ | 型 | 初期値 | 説明 |
---|---|---|---|
[selector] | 文字列 | "[data-src]" | 後(のち)にアンベールされる対象の HTML要素 を指定する、 CSSセレクタ 初期値は「"data-src"属性を持つ全要素」 |
[delay] | 数値 | 0 | 遅延ロードが対象の要素に適用されるまで、待機する時間 (ミリ秒単位) |
[unveiledClass] | 文字列 | アンベールされた対象の要素に、追加されるCSSクラス名 | |
[resolver] | NodeHandler | NodeHandler は Node をチェックして、対象の要素がアンベールされるかどうかを判断する。 resolverコールバック関数 が false を返した場合、このNodeはアンベールされない。 |
|
[observeOptions] | object | Intersection observer(交差オブザーバー API)オプション |
CSSセレクタ チートシート(図解で解りやすいですが、部分一致と前方一致の2箇所のコードが間違ったままですね)
resolver 引数は、シンタックスハイライト用の「Prism.js」ライブラリを例に取ると解りやすいと思います。
(複数の <pre> 要素の子孫要素の <code> 要素に、「language-*」CSSクラスを追加してから利用するケースが多いため)
通常、対象の全要素に指定CSSクラスを追加してから、最後にライブラリの指定JSを実行すると、「要素毎に実行される関数」をループ処理します。
この「一つの DOM Node オブジェクトを引数とする関数」を、resolver として指定するようです。
resolver Prism.js
var origin = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0';
Defer.css(origin + '/themes/prism-tomorrow.min.css', 'prism-css');
Defer.js(origin + '/prism.min.js', 'prism-js', 0, function () {
Defer.dom('pre code', 100, 'ide-loaded', Prism.highlightElement, {rootMargin: "120%"});
});
上記コードは、以下のように書き換えることもできるそうです
var origin = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0';
Defer.css(origin + '/themes/prism-tomorrow.min.css', 'prism-css');
Defer.js(origin + '/prism.min.js', 'prism-js', 0, function () {
Defer.dom('pre code', 100, 'ide-loaded', function(element) {
Prism.highlightElement(element);
}, {rootMargin: "120%"});
});
{rootMargin: "120%"} :第5引数の Intersection observer(交差オブザーバー API)オプション
ビューポート領域が 100% のため "100%" だと上下左右 画面1個分(高さor幅) margin が付き、その分手前から レンダリングが開始されます。
margin のように rootMargin は "800px 0px" や "100% 0%" とかも指定可能です。
この options の説明は難しいので、図解で解りやすい 以下の記事を見つけました!
resolver highlight.js
var base = 'https://cdn.jsdelivr.net/npm/highlightjs@9.12.0';
Defer.css(base + '/styles/rainbow.css', 'hljs-css');
Defer.js(base + '/highlight.pack.min.js', 'hljs-js', 0, function () {
Defer.dom('pre code', 100, 'ide-loaded', hljs.highlightBlock, {rootMargin: "120%"});
});
05行め:「highlight.js」ライブラリの新しいバージョンでは、hljs.highlightBlock は非推奨になりました!
代わりに、hljs.highlightElement を利用してください。
例G img data-src
data-src 属性を使用して、画像要素を遅延ロードします!
ブラウザ画像ダウンロードのトリガーは、<img> 要素 の src 属性です!
HTML内の最初の画像か 1,000番めの画像かは関係ありません。
ブラウザーが src 属性を取得すれば、現在のビューの 中にあるか外にあるかに関係なく、画像をダウンロードするトリガーとなるのです。
遅延ロードするためには、画像のURLを src 以外の属性に記述します。
画像のURLは、<img> 要素の data-src 属性に指定します。
src 属性は、実画像がダウンロードされる前に、非常に小さなサイズのプレースホルダー画像(領域確保のための仮画像)をダウンロードするために利用されることもあります。
また、プレースホルダー画像データを「Base64エンコード」すれば、(ダウンロード不要の)画像埋め込みも可能です。
(例)src='data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw=='
<div id="demo-basic">
<img alt="A lazy image" width="200" height="300" loading="lazy"
data-src="https://picsum.photos/id/1003/200/300">
<img alt="A lazy image with a low-resolution placeholder"
width="200" height="300" loading="lazy"
src="https://picsum.photos/id/1002/20/30?blur"
data-src="https://picsum.photos/id/1002/200/300">
</div>
<script>
Defer.dom('#demo-basic img');
</script>
12行め:CSSセレクタ "demo-basic" idを付けた要素の子孫要素の <img> 要素を指定
「同じid名は、1ページ中に1度しか使えない」ため、クラス指定で利用するほうが多いかもしれません。
01行め: <div class="demo-basic">
12行め: Defer.dom('.demo-basic img');
に書き換えるだけで、"demo-basic" 指定を何度も利用可能です。
例H img data-srcset
data-srcset 属性と data-sizes 属性でレスポンシブ画像を遅延ロードする!
srcset 属性を使用することで、レスポンシブ画像 のサイズ設定がより簡単になりました。
同じ画像の異なるサイズのリストを定義し、それぞれのサイズに関する情報を提供することができます。
あとは、クライアント(ブラウザ)が判断することになります。
また、(前回と同様に)画像のURLを src 以外の属性に記述すれば遅延ロードできるため、<img> 要素の data-srcset 属性と data-sizes 属性を利用して、画像のURLセットを指定するだけです。
<div id="demo-srcset">
<img alt="A lazy image with srcset attribute"
width="200" height="300" loading="lazy"
data-sizes="200w"
src="https://picsum.photos/id/204/20/30?blur"
data-src="https://picsum.photos/id/204/200/300"
data-srcset="https://picsum.photos/id/204/400/600 2x, https://picsum.photos/id/204/600/900 3x">
</div>
<script>
Defer.dom('#demo-srcset img');
</script>
07行め:Retinaディスプレイ採用の iPhone や iPad 、高精細ディスプレイ採用の Android など、「論理ピクセルを2倍(x2)や3倍(x3)の物理ピクセルで表示するデバイス」に対応する画像も、遅延ロード可能です。
画像の幅を指定する sizes 属性は重要で、ビューポート(ブラウザ幅)に対する割合を示す単位 vw vh vmin vmax での指定や、ビューポート幅別の複数指定も利用できます。
なお、CSS の( %や vwなどの )width・height 指定の方が優先されるので、注意が必要です!
srcset sizes 属性と <picture> 要素に関する詳細は、こちら が解りやすいですね。
例I WebP対応
フレキシブルに画像フォーマットを選択して、レスポンシブ画像を遅延ロードする!
ブラウザによってサポートする画像フォーマットは異なります。
WebP などの新しい画像形式を表示できるブラウザではWebP画像を表示し、表示できないブラウザでは信頼できる古い画像形式のJPEGに切り替えて表示可能です。
<picture>要素 内の <source>要素 でも上記の例と同じように、 data-src data-srcset data-sizes 属性を利用して遅延ロード可能です。
(注)HTML の <picture> 画像要素は、0 個以上の(複数の) <source> 要素と、1 個の <img> 要素を含めることが可能です。
<div id="demo-picture">
<picture>
<source type="image/webp"
data-sizes="200w"
data-src="https://picsum.photos/id/1054/200/300.webp"
data-srcset="https://picsum.photos/id/1054/400/600.webp 2x, https://picsum.photos/id/1054/600/900.webp 3x">
<img alt="A lazy image with srcset attribute"
width="200" height="300" loading="lazy"
data-sizes="200w"
src="https://picsum.photos/id/1054/20/30?blur"
data-src="https://picsum.photos/id/1054/200/300"
data-srcset="https://picsum.photos/id/1054/400/600 2x, https://picsum.photos/id/1054/600/900 3x">
</picture>
</div>
<script>
Defer.dom('#demo-picture picture');
</script>
03行め:<source> 要素の type 属性に記述した「MIMEタイプ」指定のファイル形式にブラウザが対応している場合、<source> 要素内で指定したファイルが優先でダウンロードされます。
Internet Explorerブラウザ は2022年の6月16日でサポートが終了し、アクセスするとEdgeブラウザが表示されるようになりました。
モダンなブラウザの最新バージョンでは「WebP」画像を表示できるようになり、2023年から翻訳者も「WebP」画像のみで記事を書いていますが、問題は無いようです。
srcset sizes 属性と <picture> 要素に関する詳細は、こちら が解りやすいですね。
例J CSSクラスの追加
CSSクラス を追加する、基本的な使い方!
Defer.dom() メソッドでは、要素がアンベールされたときにCSSクラス名を追加することも可能です。
この例では、<img> 要素を動かすために(複数の)CSSクラス名を追加します。
<div id="demo-basic2">
<img alt="A lazy image with animation when loaded"
width="200" height="300" loading="lazy"
src="https://picsum.photos/id/1024/20/30?blur"
data-src="https://picsum.photos/id/1024/200/300">
</div>
<script>
// this example is using animate.css library
// see: https://animate.style
Defer.dom('#demo-basic2 img', 0, 'animate__animated animate__backInLeft');
</script>
例K 背景画像 インラインCSS
「インラインCSS」で、背景画像を遅延ロードする!
<img> や <picture> 以外のHTML要素の背景画像も、遅延可能です。
<style>
#demo-inline .image {
display: inline-block;
height: 300px;
width: 200px;
background: transparent 0 0 / cover no-repeat;
border-radius: 150px;
}
</style>
<div id="demo-inline">
<div class="image" data-style="background-image:url(https://picsum.photos/id/1068/400/600)"></div>
<div class="image" data-style="background-image:url(https://picsum.photos/id/1069/400/600)"></div>
<div class="image" data-style="background-image:url(https://picsum.photos/id/1070/400/600)"></div>
</div>
<script>
Defer.dom('#demo-inline .image');
</script>
12行め:一般的に、背景画像を表示させるには CSS属性の background-image を利用します。
属性値にURLが含まれるため、style ではなく、先頭に data- を付けた data-style を利用しないといけません。
例L 背景画像 CSS
CSSによる、背景画像の遅延ロード!
HTML要素の背景画像を遅延ロードする別の例ですが、インライン style 属性の代わりに CSSクラス名を利用することもできます。
<style>
#demo-css .image {
display: inline-block;
height: 300px;
width: 200px;
background: transparent 0 0 / cover no-repeat;
border-radius: 150px;
}
#pic1.shown {
background-image: url(https://picsum.photos/id/106/400/600);
}
#pic2.shown {
background-image: url(https://picsum.photos/id/206/400/600);
}
#pic3.shown {
background-image: url(https://picsum.photos/id/306/400/600);
}
</style>
<div id="demo-css">
<div id="pic1" class="image"></div>
<div id="pic2" class="image"></div>
<div id="pic3" class="image"></div>
</div>
<script>
Defer.dom('#demo-css .image', 0, 'shown');
</script>
27行め:pic1 pic2 pic3 のidを付けた 各<div>要素がアンベールされたときに shown クラスが追加されるため、#pic1.shown #pic2.shown #pic3.shown のCSSセレクタが適用され、各背景画像が遅延ロードされます。
例M 動画(video要素)
動画を遅延ロードする!
Defer.dom() メソッドを使うと、<video> 要素など さまざまなメディア要素の遅延ロードが簡単にできます。
<div id="demo-video">
<video autoplay="true" controls="true" muted="true"
width="480" height="270"
data-poster="https://storage.googleapis.com/gtv-videos-bucket/sample/images/ForBiggerFun.jpg">
<source type="video/mp4" data-src="https://storage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4">
<!-- <source type="video/ogg" data-src="https://storage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.ogg"> -->
<!-- <source type="video/avi" data-src="https://storage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.avi"> -->
</video>
</div>
<script>
Defer.dom('#demo-video video', 0, 'shown');
</script>
02行め:<picture> 要素と同じように、<video> 要素は複数の <source> 要素を持てます。
( src から、data-src 属性への書き換えを忘れずに)
<video> 要素内の poster 属性には「動画のダウンロード中に表示される画像のURL」を指定するため、先頭に data- を付けた data-poster を利用します。
例N iframe要素
<iframe> 要素を遅延ロードする!
Defer.dom() メソッドを使うと、<iframe> 要素の遅延ロードが簡単にできます。
<div id="demo-iframe">
<iframe title="An iframe example"
width="480" height="270" frameborder="0"
src="about:blank"
data-src="https://shinsenter.github.io/defer.js/">
</iframe>
</div>
<script>
Defer.dom('#demo-iframe iframe', 0, 'iframe-loaded');
</script>
04行め:遅延ロード完了まで、about:blank を表示。
05行め:src から、data-src 属性への書き換えを忘れずに!
例O YouTube
YouTube の動画を遅延ロードする!
この例では Defer.dom() メソッドを使用して、YouTube <iframe> 要素を遅延ロードします。
<div id="demo-youtube">
<iframe title="The new MacBook Air"
width="480" height="270" frameborder="0" allowfullscreen=""
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
src="about:blank"
data-src="https://www.youtube.com/embed/jwmS1gc9S5A"
data-style="background: transparent url(https://img.youtube.com/vi/jwmS1gc9S5A/hqdefault.jpg) 50% 50% / cover no-repeat;">
</iframe>
</div>
<script>
Defer.dom('#demo-youtube iframe', 0, 'youtube-loaded');
</script>
05行め:遅延ロード完了まで、about:blank を表示。
06,07行め:属性値にURLが含まれるため、data- を付けた data-src data-style を利用しないといけません。
例P Facebook投稿
Facebook の投稿を遅延ロードする!
この例では Defer.dom() メソッドを使用して、Facebook <iframe> 要素を遅延ロードします。
<div id="demo-facebook">
<iframe title="An example of Facebook post"
width="480" height="270" frameborder="0"
scrolling="no" allowtransparency="true" allow="encrypted-media"
src="about:blank"
data-src="https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2Fappseeds%2Fposts%2F1502937099839267&width=480&show_text=true&height=200">
</iframe>
</div>
<script>
Defer.dom('#demo-facebook iframe', 0, 'facebook-loaded');
</script>
05行め:遅延ロード完了まで、about:blank を表示。
06行め:属性値にURLが含まれるため、data- を付けた data-src を利用しないといけません。
例Q Discordウィジェット
Discord のウィジェットを遅延ロードする!
この例では Defer.dom() メソッドを使用して、Discord チャットボックス を遅延ロードします。
<iframe id="discord-widget" title="Discord"
width="480" height="270" frameborder="0"
allowtransparency="true" sandbox="allow-popups allow-popups-to-escape-sandbox allow-same-origin allow-scripts"
src="about:blank"
data-src="https://discord.com/widget?id=962919929307357234&theme=dark">
</iframe>
<script>
Defer.dom('#discord-widget', 0, 'discord-loaded');
</script>
04行め:遅延ロード完了まで、about:blank を表示。
05行め:属性値にURLが含まれるため、data- を付けた data-src を利用しないといけません。
09行め:"discord-widget" id を付けた要素(iframe)が、遅延ロード対象です。
例R resolver インライン関数
スクロールして、公開する!
Defer.dom() メソッドは、要素が公開されたときに(インライン)関数を呼び出して アクションを実行するのにも役立ちます。(関数に変数を割り当てない場合、正式にはインライン関数ではなく、無名関数と呼ぶそうです)
この例では、ユーザーがページの一番下までスクロールして id="surprise-me" を付けた要素が表示されてから1秒後に、「OKボタンのみのアラートダイアログ」が表示され、"seen" のCSSクラスが追加されます。
<script>
Defer.dom('#surprise-me', 1000, 'seen', function(node) {
alert('Yay!\nYou have seen all examples. Have fun with Defer.js!');
});
</script>
JS関数内で「return文」を使用しない場合、undefined が関数の戻り値です。
Defer.dom() メソッドは、型も含めた (関数の戻り値)=== false 成立の場合のみ アンベールを取り消す仕様です。(作者が教えてくれました)
つまり、型も含めた (関数の戻り値)!== false 成立の場合、アンベールされます。
「OK と キャンセル、2つのボタンを持つ確認ダイアログ」を表示するには、
alert() ではなく confirm() を利用します。
以下に、「関数の戻り値」として false と false以外 を返して、動的に「アンベール+CSSクラス追加」有無を切り替えるテストコードを掲載します。
( 例L の26行め以降を置換)
対象の <div> 要素ごとに resolver パラメータで指定した(インライン)関数が呼び出されるため、確認ダイアログが 3回 表示されます!
<script>
Defer.dom('#demo-css .image', 1000, 'shown', function(node) {
if (confirm(' [OK]=>Unveil or [Cancel]=>Not Unveil ')) {
return true;
} else {
return false;
}
});
</script>
Defer.css(fileUrl, [id], [delay], [onload], [waitForUserAction]) ⇒ void
Defer.css() メソッドを使用すれば、ページのレンダリングをブロックすることなく、外部CSSファイルの読み込みを遅延ロードできます。
(注)Defer.lazy=true または waitForUserAction=true を設定した場合、Version 3.0から遅延ロードの挙動が変更されました。
ユーザーがページの操作を開始しない限り、fileUrl パラメータ
指定のファイルは取得されません。
種類: Defer の 静的メソッド(Global)
適用: Version 2.0〜
パラ | 型 | 初期値 | 説明 |
---|---|---|---|
fileUrl | 文字列 | 遅延ロード対象のCSSファイルをURLで指定 | |
[id] | 文字列 | ファイルの重複ダウンロードを防ぐため、指定するid | |
[delay] | 数値 | 0 | CSSファイルを取得するまで、待機する時間(ミリ秒) |
[onload] | 関数 | CSSファイルの読み込み成功後に実行される、コールバック関数を指定 | |
[waitForUserAction] | 真偽 | false | ユーザーとの対話があるまで、Defer.css() メソッドがCSSファイルのダウンロードを待つかどうか? |
例S CSSファイル FontAwesome
Defer.css() メソッドを利用して、FontAwesome(CSSと一部のフォントファイル)を遅延ロードします!
<style>
#demo-fontawesome .far {
font-size: 3em;
color: green;
}
</style>
<div id="demo-fontawesome">
<i class="far fa-thumbs-up"></i>
<code>@shinsenter/defer.js</code>
</div>
<script>
var fileUrl = 'https://pro.fontawesome.com/releases/v5.14.0/css/all.css';
Defer.css(fileUrl, 'fa5-css', 0, function() {
console.info('FontAwesome is loaded.'); // debug
});
</script>
例T Defer.domをコールバック関数 animate.css
animate.css を遅延ロードします!
CSSファイルの読み込み成功後、Defer.dom() メソッドを実行します。
<script>
var origin = 'https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.1';
// This script will lazy load animate.css library.
Defer.css(origin + '/animate.min.css', 'animate-css', 0, function () {
console.info('Animate.css is loaded.'); // debug
// adds animation classes to demo blocks.
Defer.dom('.demo', 100, 'animate__animated animate__fadeIn');
}, true);
</script>
10行め:ユーザーとの対話後、CSSファイルを読み込み、( Defer.dom() を含む)06〜09行めのコールバック関数を実行します。
Defer.js(fileUrl, [id], [delay], [onload], [waitForUserAction]) ⇒ void
Defer.js() メソッドを使用すれば、ページのレンダリングをブロックすることなく、サードパーティのJavaScriptライブラリ、ウィジェット、アドオンなど、JSファイルを遅延ロードできます。
(注1) Defer.js() メソッドによるファイルのダウンロードは非同期のため、 Defer.js() メソッドでサードパーティ製ライブラリを遅延ロードする際の依存性エラーを防ぐため、onload コールバック関数を利用して、「必要なライブラリが完全に定義済みかどうか」確認するよう強く推奨します。
非同期とは、複数のファイルをDefer.js() メソッド利用で遅延ロード対象とした場合、「呼び出し順に、そのライブラリが利用できるとは限らない」ということを意味します。
複数のJSファイルを同期して遅延ロードさせたい場合は、 Defer.all() メソッドを利用しましょう!
preload が自動追加されるのは Defer.all() メソッドのみのため、JSのファイルサイズが大きい場合は <head>要素内への 手動 preload 追加 を推奨します。
(注2)Defer.lazy=true または waitForUserAction=true を設定した場合、Version 3.0から遅延ロードの挙動が変更されました。
ユーザーがページの操作を開始しない限り、fileUrl パラメータ
指定のファイルは取得されません。
種類: Defer の 静的メソッド(Global)
適用: Version 2.0〜
パラ | 型 | 初期値 | 説明 |
---|---|---|---|
fileUrl | 文字列 | 遅延ロード対象のJSファイルをURLで指定 | |
[id] | 文字列 | ファイルの重複ダウンロードを防ぐため、指定するid | |
[delay] | 数値 | 0 | JSファイルを取得するまで、待機する時間(ミリ秒) |
[onload] | 関数 | JSファイルの読み込み成功後に実行される、コールバック関数を指定 | |
[waitForUserAction] | 真偽 | false | ユーザーとの対話があるまで、Defer.js() メソッドがJSファイルのダウンロードを待つかどうか? |
例U Google Analytics
Googleタグマネージャー(GTM)を利用して、Google Analytics を遅延ロードする方法です!
Defer.js() メソッドを使用して、Googleタグマネージャーのライブラリとその外部スクリプトを遅延ロードさせます。
この例では、ページが読み込まれたらすぐに GTM を実行させたいので、waitForUserAction 引数(第5引数)を false に設定しています。
<script>
var GTM_ID = 'UA-XXXXXXX-Y';
window.dataLayer = window.dataLayer || [];
dataLayer.push(['js', new Date()]);
dataLayer.push(['config', GTM_ID]);
Defer.js('https://www.googletagmanager.com/gtag/js?id=' + GTM_ID, 'google-tag', 0, function() {
console.info('Google Tag Manager is loaded.'); // debug
}, false);
</script>
UA ではなく GA4 プロパティを利用する場合は、 G-xxxxxxxxxx ( "G-" 以降は、10文字の英数字)を GTM_ID にセットしてください。
例V AddThis
AddThisアドオンを遅延ロードする!
Defer.js() メソッドを使用して、AddThis Share Buttons とその外部リソースを遅延ロードしています。
waitForUserAction 引数(第5引数)を true に設定しているため、AddThisアドオンはユーザーがページとの対話を開始するまでロードされません。
<div class="demo-addthis"></div>
<script>
var ADDTHIS_ID = 'ra-5c68e61cf456f1cb';
var fileUrl = 'https://s7.addthis.com/js/300/addthis_widget.js#pubid=' + ADDTHIS_ID;
var loaded = false;
Defer.js(fileUrl, 'addthis-js', 0, function() {
console.info('AddThis add-on is loaded.'); // debug
}, true);
</script>
例W Prism.js マニュアルモード
Prism.jsライブラリを遅延ロードする!
Defer.js から Defer.dom を呼び出し、Prism.js ライブラリとその適用箇所を遅延ロードします。
「Prism.js マニュアルモード」利用のため、ページ上の <code> ブロックは、ユーザーが任意の <code> ブロックの位置までスクロールするまでレンダリングされません。
<style>
pre {
background-color: honeydew;
}
</style>
<script>
// turns on manual mode
window.Prism = window.Prism || {};
Prism.manual = true;
// this script will lazy load Prism.js library and its dark theme.
// when loading is done, it will apply code formatting to every <code> tag.
var origin = 'https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0';
Defer.css(origin + '/themes/prism-tomorrow.min.css', 'prism-css');
Defer.js(origin + '/prism.min.js', 'prism-js', 0, function () {
// enables code highlighting for code tags using Defer.dom()
Defer.dom('pre code', 100, 'ide-loaded', Prism.highlightElement, {rootMargin: "120%"});
console.info('Prism.js is loaded.'); // debug
});
</script>
09行め:window.Prism オブジェクトを初期化
( window.xxx:グローバル変数 ➡️ 10行めは window.Prism.manual = true; の省略記述 )
v = v || {}; は JSイディオム で、v が undefined の時など(型変換後、条件式でfalse)に、デフォルト値として「空のオブジェクト」を設定
"" 0 undefined null false 5種類の値は、条件式で false と評価
{} "hoge" 1 -1 [] true 6種類の値は、条件式で true と評価
10行め:Prism.js をマニュアル表示モードに切り替え
15行め:Prism.js 表示用CSSを遅延ロード
16行め:JSファイルの遅延ロード完了後、( Defer.dom() を含む)17〜20行めのコールバック関数を実行します。
18行め: {rootMargin: "120%"} 第5引数の Intersection observer(交差オブザーバー API)オプション
ビューポート領域が 100% のため "100%" だと上下左右 画面1個分(高さor幅) margin が付き、その分手前から レンダリングが開始されます。
margin のように rootMargin は "800px 0px" や "100% 0%" とかも指定可能です。
また、<pre> 要素の子孫要素の <code> 要素を、CSSセレクタで指定しています。
CSSセレクタ チートシート(図解で解りやすいですが、部分一致と前方一致の2箇所のコードが間違ったままですね)
例X Twitter
Twitter の「ツイート」と「タイムライン」を遅延ロードします。
この例では、 Defer.js() と Defer.dom() メソッドを組み合わせて、Twitter の「ツイート」と「タイムライン」を 遅延させています。
ページ上の .lazy-timeline または .lazy-tweet ブロックは、ユーザーがその位置にスクロールするまでは レンダリングされません。
以下コードの利用方法を 別記事に わかりやすく まとめましたので、以下記事を ご覧ください。
( 親要素の追加と CSSクラス名の変更を、JSコードで行う方法を追加 )
Defer.js() は非同期で実行されるため、依存関係がある Defer.dom() は必ず (インライン)コールバック関数内に記述 しなければいけません。
指定JS実行時に 一括レンダリングされないようにするため、埋め込みコード内に付与された オリジナルのCSSクラス名を 一時的に変更しています。
21, 31行め:node.parentNode(親要素)を引数として関数を実行するため、「埋め込みコードを、div 要素で囲む」必要があります‼️
以下コードでは、「id="demo-twitter"」を持つ(id名は任意) div 要素を利用。
複数箇所 埋め込む場合は、「class="embed-twitter"」を持つ(クラス名は任意) div 要素で囲むか、それぞれ ユニークな id を持つ div 要素で囲みます。
node.parentNode(親要素)が「記事本文」など広範囲になってしまっては、要素が現れるたびにレンダリングできません❗️
<div id="demo-twitter">
<a class="lazy-timeline" <!-- the original is class="twitter-timeline" -->
href="https://twitter.com/TwitterDev"
data-chrome="nofooter noborders"
data-height="400" data-dnt="true" data-theme="dark">
Tweets by @TwitterDev
</a>
<blockquote class="lazy-tweet" <!-- the original is class="twitter-tweet" -->>
<!-- content is truncated -->
</blockquote>
</div>
<script>
Defer.js('https://platform.twitter.com/widgets.js', 'twitter-sdk', 0, function() {
Defer.dom('.lazy-timeline', 0, 'twitter-loaded', function(node) {
// adds the correct class name for tweet element
node.className = 'twitter-timeline';
// For better performance,
// we only search within the parent DOM tree for uninitialized widgets
twttr.widgets.load(node.parentNode);
console.info('Twitter timeline is loaded.'); // debug
}, {rootMargin: "200%"});
Defer.dom('.lazy-tweet', 0, 'twitter-loaded', function(node) {
// adds the correct class name for timeline element
node.className = 'twitter-tweet';
// For better performance,
// we only search within the parent DOM tree for uninitialized widgets
twttr.widgets.load(node.parentNode);
console.info('Twitter post is loaded.'); // debug
}, {rootMargin: "200%"});
});
</script>
(注)指定時間経過後に すべての「ツイート+タイムライン」を一括レンダリングするなら、以下のコードとなります。
Defer.js() の最終引数 を true に変更すると、(マウス操作など)ユーザーがアクションを起こすまで、指定したJSの実行が保留されます。
<script>
const tw_EmbedTW = document.getElementsByClassName('twitter-tweet'); // TWeet
const tw_EmbedTL = document.getElementsByClassName('twitter-timeline'); // TimeLine
if (tw_EmbedTW.length !== 0 || tw_EmbedTL.length !== 0) {
Defer.js('https://platform.twitter.com/widgets.js', 'twitter-js', 1000, null, true);
}
</script>
例Y Instagram
Instagram の「投稿」を遅延ロードします。
この例では、 Defer.js() と Defer.dom() メソッドを組み合わせて、Instagram の「投稿」を 遅延させています。
ページ上の .lazy-instagram ブロックは、ユーザーがその位置にスクロールするまでは レンダリングされません。
以下コードの利用方法を 別記事に わかりやすく まとめましたので、以下記事を ご覧ください。
( 親要素の追加と CSSクラス名の変更を、JSコードで行う方法を追加 )
Defer.js() は非同期で実行されるため、依存関係がある Defer.dom() は必ず (インライン)コールバック関数内に記述 しなければいけません。
指定JS実行時に 一括レンダリングされないようにするため、埋め込みコード内に付与された オリジナルのCSSクラス名を 一時的に変更しています。
16行め:node.parentNode(親要素)を引数として関数を実行するため、「埋め込みコードを、div 要素で囲む」必要があります‼️
以下コードでは、「id="demo-instagram"」を持つ(id名は任意) div 要素を利用。
複数箇所 埋め込む場合は、「class="embed-insta"」を持つ(クラス名は任意) div 要素で囲むか、それぞれ ユニークな id を持つ div 要素で囲みます。
node.parentNode(親要素)が「記事本文」など広範囲になってしまっては、要素が現れるたびにレンダリングできません❗️
<div id="demo-instagram">
<blockquote class="lazy-instagram" <!-- the original is class="instagram-media" -->
data-instgrm-captioned=""
data-instgrm-permalink="<!-- the URL is omitted -->">
<!-- content is truncated -->
</blockquote>
</div>
<script>
Defer.js('https://www.instagram.com/embed.js', 'instagram-sdk', 0, function() {
Defer.dom('.lazy-instagram', 0, 'instagram-loaded', function(node) {
// adds the correct class name for instagram post
node.className = 'instagram-media';
// For better performance,
// we only search within the parent DOM tree for uninitialized widgets
instgrm.Embeds.process(node.parentNode);
console.info('Instagram post is loaded.'); // debug
}, {rootMargin: "200%"});
});
</script>
(注)指定時間経過後に すべてのInstagram「投稿」を一括レンダリングするなら、以下のコードとなります。
Defer.js() の最終引数 を true に変更すると、(マウス操作など)ユーザーがアクションを起こすまで、指定したJSの実行が保留されます。
<script>
const instaEmbed = document.getElementsByClassName('instagram-media'); // Instagram
if (instaEmbed.length !== 0) {
Defer.js('https://www.instagram.com/embed.js', 'insta-js', 1000, null, true);
}
</script>
Defer.reveal(node, [unveiledClass]) ⇒ void
「Defer.js ライブラリ」によって遅延ロードされた Node をプログラムコードで、即時公開 する!
種類: Defer の 静的メソッド(Global)
適用: Version 2.1〜
パラ | 型 | 説明 |
---|---|---|
node | Node | アンベールされる、HTMLノード |
[unveiledClass] | 文字列 | アンベールされた対象の要素に、追加されるCSSクラス名 |
例Z Defer.reveal() 4事例
// reveals a single element
var node = document.getElementById('my-video');
Defer.reveal(node);
// reveals multiple elements
document.querySelectorAll('.multi-lazy')
.forEach(function(node) {
Defer.reveal(node);
});
// a short-hand for the above code
document.querySelectorAll('.multi-lazy').forEach(Defer.reveal);
// adds 'unveiled' classname when an element unveiled
document.querySelectorAll('.multi-lazy')
.forEach(function(node) {
Defer.reveal(node, 'unveiled');
});
02行め:同一id名を付加できる要素はページ内に一つだけのため、一つだけ要素(Node)が返されます(存在しない場合、null)。
getElementById() メソッドなどが動作しない場合、メソッド名の大文字と小文字が正しいか、確認してください!
クラス名からHTML要素を取得する場合は getElementsByClassName() メソッドを利用しますが、HTML(要素)コレクションが返されるため、forEach メソッドは直接は利用できません。
querySelectorAll() メソッドは Nodeリスト が返されるため、forEachメソッドを利用したループ処理が可能で、(インライン)コールバック関数やアロー関数が利用できます。
最初の 要素(Node)が返される querySelector() メソッドも利用可能です。
querySelector() と querySelectorAll() メソッドの引数は CSSセレクタ のため、部分一致・前方一致・後方一致などを利用して Node を抽出可能です。
getElementsByClassName() は querySelectorAll() で通常 代用可能なため、上記例には無いようです。
CSSセレクタ チートシート(図解で解りやすいですが、部分一致と前方一致の2箇所のコードが間違ったままですね)
Node
他の多くの DOM API オブジェクトのベースとなる抽象的な基底クラス。
種類: global typedef
参照: https://developer.mozilla.org/docs/Web/API/Node
Function
呼び出すことができるコードスニペット、またはその関数を参照する変数。
種類: global typedef
参照: https://developer.mozilla.org/docs/Glossary/Function
NodeHandler ⇐ Function
引数として 一つの DOM Node オブジェクトを受け取る、Function
種類: global typedef
拡張: Function
パラ | 型 | 説明 |
---|---|---|
node | Node | 一つの Node オブジェクト |
コミュニティ
オープンソース貢献者の活気あるコミュニティに参加して、プロジェクトにあなたの足跡を残しませんか?
私たちは、あらゆる形の貢献とサポートを歓迎します。
標準的な GitHubプルリクエストプロセス を使用していて、私たちのレビュアーが喜んで お手伝いさせていただきます。
コードを提供する自信がないですか?
問題ありません。
ドキュメントの改善、問題の報告、議論の開始 などは すべて貴重な貢献であり、私たちはそれを高く評価しています。
【手助けが必要です】一緒に、ドキュメントとサンプルを より良いものにしましょう❗️
このプロジェクトのサポート
このプロジェクトが気に入って頂けたら、GitHubで Stargazerになったり 、Gitterコミュニティに参加したり、このプロジェクトのスポンサーになることで 支援を表明してください。
あなた方の支援も お待ちしております。
開発者にコーヒーをおごったり、スポンサーになるなど、今後の開発資金の支援も検討してください。
みなさまの ご支援を心より お待ちしております。
ベトナムから 🇻🇳 愛を込めて‼️
日本語訳 修正履歴など
お疲れ様です。ドキュメントは以上です
( 2023/03/22 commit版 を翻訳 )
このドキュメントの著作権は Shin さんのもので、サンプルコードはオリジナルのまま転載させて頂きました。
日本語訳は機械翻訳された文章を手直ししていますが、不可解な場合は オリジナルの英語ドキュメントを参照してください。
(注)オレンジ色のコメントは、翻訳者が追加したもの
修正履歴
v3.4.0 版
2023/02/19 全文の翻訳
2023/02/26 highlight.js hljs.highlightBlock → hljs.highlightElement
2023/03/06 window.Prism = window.Prism || {};
- 「初期化」の説明が適切でなかったため、修正
2023/03/10 Intersection Observer API の options の説明記事を追加
2023/05/23 Defer.dom() の rootMargin 指定にて Chromeブラウザの場合、"150% 0" または "800px 0" のようにZERO指定すると不具合を起こす場合があるため、以下のように修正。
"150% 0%" または "800px 0px"
v3.5.0 版
2023/02/26 Version: 3.5.0 変更分のみ修正
- defer.min.js 1.85KByte → 1.76KByte
- 一部ドキュメントの修正(サンプルコードを含む)
v3.6.0 版
2023/05/03 Version: 3.6.0 変更分のみ修正
- defer.min.js 1.76KByte → 1.81KByte
- 「判明している問題点(Discussion #122)」を追加
- Twitter または Instagram 埋め込み時、スクロールして該当要素が現れるたびにレンダリングするサンプルコードを追加
最後まで読んでいただき、ありがとうございます。 また、お越しくださいませ。
// アタル