2016-07-20 10 views
1

我々は怠惰な負荷の画像に使用している現在のアプローチは、次のとおりです。大きなページに画像をレイジーに読み込む方法は?

サーバ側テンプレートはなど、すべての画像要素をレンダリング:

<img 
    src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" 
    data-src="http://static.com/img.jpg" 
    style="display: none;" 
/> 

DOMContentLoadedイベントは、解雇されたJavaScriptがある<img />要素を検出したときビューポートでsrc属性値をdata-srcの値に置き換えます。

問題:全体のDOMがロードされるまで、フロントページ上の

画像が表示されません。これは非常に大きなページ(HTML 2MB)なので、DOMContentLoadedイベントが発生するまでに3〜5秒かかります。

私が探しているのは、DOMでの操作が可能になるとすぐに、最初の100枚の画像をロードできるJavaScriptソリューションです。私が探しています何

+0

それはあなたのコメントから聞こえる:「JavaScriptがビューポート内にある要素を検出し、データ-SRCの値でsrc属性値を置き換えます」あなたはすでにこのページの画像を扱っているJavaScriptをいくつか持っています。なぜ最初に最初の100枚の画像を読み込むための制限を加えないのですか? –

+0

最初の100枚の画像に遅延読み込みをしたくないのはなぜですか?最初の100枚の画像でsrc-dataと同じsrcを使用するようにサーバーサイドコードを変更しないのはなぜですか? –

答えて

0

は、すぐに彼らはDOMに 操作に利用可能になると 負荷に最初の100枚の画像を、私を可能にするJavaScriptのソリューションです。

私が実装した解決策は本質的にこれです。

私は、ページ上の既存のイメージの再インデックスを可能にするために、遅延ローディングスクリプトを抽象化する必要がありました。私は、ドキュメント内の他のものの前にこのスクリプトを同期的に読み込むことから始めます。 JavaScriptが機能できる瞬間から、スクリプトはDOM内のすべての画像要素を見つけてそれらがビューポート内にあるかどうかを調べるために間隔を空けます。要素がビューポート内にあるとみなされると、画像要素(data-srcsrc)を変更しようとします。この間隔は、DOMContentLoadedが発砲されるまで続きます。コードの面では

、それは次のようになります。

const LazyImageLoader = require('./LazyImageLoader'); 
const domReady = require('domready'); 

/** 
* The reason for using setTimeout instead of setInterval 
* is to not re-run revalidate more often than the body 
* of the function can be evaluated. 
*/ 
const createIntervalIterator = (callback, interval) => { 
    let currentTimeout; 

    const control = {}; 

    const iterator =() => { 
    const startTime = new Date().getTime(); 

    callback(); 

    const evaluationTime = new Date().getTime() - startTime; 

    const delayNextIteration = interval - evaluationTime; 

    currentTimeout = setTimeout(iterator, delayNextIteration); 
    }; 

    iterator(); 

    return() => { 
    clearTimeout(currentTimeout); 
    }; 
}; 

const iterationIntervalTime = 100; 

const lazyImageLoader = new LazyImageLoader({ 
    offset: 100, 
    selector: 'img[data-src]', 
}); 

/** 
* Revalidation ensures that all images are in LazyImageLoader index. 
*/ 
const revalidate =() => { 
    lazyImageLoader.revalidate(); 
}; 

const cancelInterval = createIntervalIterator(() => { 
    revalidate(); 
}, iterationIntervalTime); 

domReady(() => { 
    if (cancelInterval) { 
    cancelInterval(); 
    } 

    // Revalidate after domReady in case any images have been added 
    // to the DOM after the last `revalidate` invocation. 
    revalidate(); 
});