2012-04-20 23 views
48

Moi przyjaciele i ja pracujemy nad witryną, w której chcielibyśmy buforować określone obrazy, aby wyświetlać je szybciej w przyszłości. Mam dwa główne pytania:W jaki sposób buforujesz obraz w JavaScript

  1. W jaki sposób buforujesz obraz?
  2. Jak korzystać z obrazu po jego buforowaniu? (I tylko w celu sprawdzenia, czy obraz jest buforowane na stronie A, to jest możliwe, aby połączyć go z pamięci podręcznej, aby używać go na stronie B, prawda?)

Ponadto, możliwe jest ustawienie gdy wersja obrazu z pamięci podręcznej wygaśnie?

Byłoby bardzo docenione, gdyby dołączono przykład i/lub link do strony opisującej to dalej.

Używamy albo surowego kodu Javascript, albo wersji jQuery.

+10

ty nie. Przeglądarka ma. – Pointy

+0

powoduje automatyczne buforowanie obrazów przeglądarki? –

+6

@Logan: Tak, przeglądarka buforuje obrazy automatycznie, pod warunkiem, że Twój serwer wyśle ​​niezbędne nagłówki, aby poinformować przeglądarkę, że można bezpiecznie zapisać w pamięci podręcznej. (Te nagłówki mogą również informować przeglądarkę o czasie wygaśnięcia, który jest częścią twojego pytania.) – icktoofay

Odpowiedz

92

Po załadowaniu obrazu w jakikolwiek sposób do przeglądarki, będzie ono znajdować się w pamięci podręcznej przeglądarki i ładować się będzie znacznie szybciej przy następnym użyciu, niezależnie od tego, czy jest ono używane na bieżącej stronie, czy na dowolnej innej stronie. ponieważ obraz jest używany przed wygaśnięciem z pamięci podręcznej przeglądarki.

Tak więc, aby wykonać wstępne obrazy, wystarczy załadować je do przeglądarki. Jeśli chcesz wstępnie skompresować kilka obrazów, najlepiej jest zrobić to za pomocą javascript, ponieważ generalnie nie będzie on ładował strony po wykonaniu z javascript. Można to zrobić tak:

function preloadImages(array) { 
    if (!preloadImages.list) { 
     preloadImages.list = []; 
    } 
    var list = preloadImages.list; 
    for (var i = 0; i < array.length; i++) { 
     var img = new Image(); 
     img.onload = function() { 
      var index = list.indexOf(this); 
      if (index !== -1) { 
       // remove image from the array once it's loaded 
       // for memory consumption reasons 
       list.splice(index, 1); 
      } 
     } 
     list.push(img); 
     img.src = array[i]; 
    } 
} 

preloadImages(["url1.jpg", "url2.jpg", "url3.jpg"]); 

Funkcja ta może być wywołana tyle razy, ile chcesz i za każdym razem, to będzie po prostu dodać więcej zdjęć do precache.

Po wczytaniu obrazów w javascript, przeglądarka będzie je przechowywać w pamięci podręcznej i można po prostu odwoływać się do normalnych adresów URL w innych miejscach (na twoich stronach internetowych), a przeglądarka pobierze ten adres URL z pamięci podręcznej zamiast przez sieć.

Ostatecznie z upływem czasu pamięć podręczna przeglądarki może wypełniać i rzucać najstarsze rzeczy, które przez jakiś czas nie były używane. Ostatecznie obrazy zostaną wypuszczone z pamięci podręcznej, ale powinny pozostać tam przez jakiś czas (w zależności od tego, jak duża jest pamięć podręczna i jak wiele innego przeglądania jest wykonywane). Za każdym razem, gdy obrazy są w rzeczywistości ponownie ładowane lub używane na stronie internetowej, automatycznie odświeża się ich pozycja w pamięci podręcznej przeglądarki, więc jest mniej prawdopodobne, że zostaną wypuszczone z pamięci podręcznej.

Pamięć podręczna przeglądarki jest stroną między stronami, więc działa dla każdej strony załadowanej do przeglądarki. Możesz więc wstępować w jednym miejscu w swojej witrynie, a pamięć podręczna przeglądarki będzie działać na wszystkich innych stronach w Twojej witrynie.


Po wykonaniu powyższego zdjęcia obrazy są wczytywane asynchronicznie, aby nie blokować ładowania ani wyświetlania strony. Ale jeśli twoja strona ma wiele własnych obrazów, te obrazy z precache mogą konkurować o przepustowość lub połączenia z obrazami, które są wyświetlane na twojej stronie. Zwykle nie jest to zauważalny problem, ale w przypadku powolnego połączenia, ten precaching może spowolnić ładowanie strony głównej. Jeśli ładowanie obrazów wstępnych zostało załadowane jako ostatnie, można użyć wersji funkcji, która czekała na rozpoczęcie wstępnego ładowania, dopóki wszystkie inne zasoby stron nie zostaną załadowane.

function preloadImages(array, waitForOtherResources, timeout) { 
    var loaded = false, list = preloadImages.list, imgs = array.slice(0), t = timeout || 15*1000, timer; 
    if (!preloadImages.list) { 
     preloadImages.list = []; 
    } 
    if (!waitForOtherResources || document.readyState === 'complete') { 
     loadNow(); 
    } else { 
     window.addEventListener("load", function() { 
      clearTimeout(timer); 
      loadNow(); 
     }); 
     // in case window.addEventListener doesn't get called (sometimes some resource gets stuck) 
     // then preload the images anyway after some timeout time 
     timer = setTimeout(loadNow, t); 
    } 

    function loadNow() { 
     if (!loaded) { 
      loaded = true; 
      for (var i = 0; i < imgs.length; i++) { 
       var img = new Image(); 
       img.onload = img.onerror = img.onabort = function() { 
        var index = list.indexOf(this); 
        if (index !== -1) { 
         // remove image from the array once it's loaded 
         // for memory consumption reasons 
         list.splice(index, 1); 
        } 
       } 
       list.push(img); 
       img.src = imgs[i]; 
      } 
     } 
    } 
} 

preloadImages(["url1.jpg", "url2.jpg", "url3.jpg"], true); 
preloadImages(["url99.jpg", "url98.jpg"], true); 
+0

W tym przykładzie tworzysz nowy obiekt obrazu dla każdego adresu URL. Jeśli ustawisz zmienną img poza pętlą i po prostu zaktualizujesz src, powinno to mieć ten sam efekt i zmniejszyć zasoby – cadlac

+0

@ cadlac - Ale żeby mieć pewność, że przeglądarka rzeczywiście pobierze i zapisze w pamięci każdy obraz, będziesz musiał poczekaj, aż zakończy się pobieranie jednego obrazu przed ustawieniem nowej właściwości .src. W przeciwnym razie przeglądarka mogłaby po prostu zatrzymać wcześniejsze pobieranie i nigdy pomyślnie go nie buforować. – jfriend00

+0

Wygląda na to, że działa on w nowszych wersjach przeglądarek bez czekania, ale dobrze trafiłeś. Będę musiał wypróbować to na starszych przeglądarkach, aby zobaczyć kompatybilność :) – cadlac

10

jako @Pointy powiedział, że nie buforuje obrazów z javascript, przeglądarka to robi. więc może to być tym, o co prosisz i może nie być, ale możesz wstępnie załadować obrazy za pomocą javascript. Umieszczając wszystkie obrazy, które chcesz wczytać do tablicy i umieszczając wszystkie obrazy w tej tablicy w ukrytych elementach img, skutecznie wczytujesz (lub buforujesz) obrazy.

var images = [ 
'/path/to/image1.png', 
'/path/to/image2.png' 
]; 

$(images).each(function() { 
var image = $('<img />').attr('src', this); 
}); 
+2

Czy można wstępnie załadować obraz na jednej stronie (bez wyświetlania go), a następnie wyświetlić na następnej stronie? –

+1

według mojej wiedzy, jeśli wstępnie załadujesz obraz na jednej stronie, zostanie on wprowadzony do pamięci podręcznej przeglądarki, a następnie wyświetlony szybciej na każdej innej stronie. jeśli to jest złe, proszę, popraw mnie. –

2

Istnieje kilka rzeczy, które można spojrzeć na:

Wstępne ładowanie obrazów
Ustawianie czasu cache w pliku .htaccess
rozmiar plików obrazów i kodujące je base64.

Wgrywanie: http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/

buforowanie: http://www.askapache.com/htaccess/speed-up-sites-with-htaccess-caching.html

Istnieje kilka różnych myśli do kodowania base64, niektórzy mówią, że żądania HTTP bog dół pasma, podczas gdy inni twierdzą, że „postrzegana” ładowanie jest lepszy. Zostawię to w powietrzu.

0

Tak, przeglądarka automatycznie buforuje obrazy automatycznie.

Można jednak ustawić pamięć podręczną obrazu, aby wygasła. Sprawdź Ten stos pytań przelewowe i odpowiedzieć:

Cache Expiration On Static Images

1

mam similar answer dla asynchronicznego wstępne ładowanie obrazów poprzez JS. Ładowanie ich dynamicznie przebiega tak samo, jak ładowanie ich w normalny sposób. będą buforować.

co do buforowania, nie można sterować przeglądarką, ale można ustawić ją za pośrednictwem serwera. Jeśli potrzebujesz załadować naprawdę świeży zasób na żądanie, możesz użyć cache buster technique, aby wymusić załadowanie nowego zasobu.

1

Nawet jeśli pytanie mówi „przy użyciu javascript”, można użyć atrybutu znacznika łącza prefetch wstępnego ładowania żadnych aktywów. W chwili pisania tego (10 sierpnia 2016) nie jest obsługiwany w przeglądarce Safari, ale jest prawie wszędzie:

<link rel="prefetch" href="(url)">

Więcej informacji na temat wsparcia tutaj: http://caniuse.com/#search=prefetch

Zauważ, że IE 9 , 10 nie są wymienione w macierzy caniuse, ponieważ Microsoft przerwał dla nich obsługę.

Więc jeśli naprawdę zatrzymany na użyciu javascript, można użyć jQuery dynamicznie dodać te elementy do swojej strony, jak również ;-)

+0

Fajnie miło miło! –

1

używam podobną technikę LazyLoad obrazów, ale nie może pomóc, ale zauważ, że JavaScript nie uzyskuje dostępu do pamięci podręcznej przeglądarki przy pierwszym ładowaniu.

Mój przykład:

Mam obrotowy banner na mojej stronie z 4 obrazów suwak czekać 2 sekundy, niż javascript ładuje następny obraz, czeka 2 sekundy, etc.

Obrazy te mają unikalne adresy URL, które zmieniają się po ich zmodyfikowaniu, dzięki czemu przechwytują nagłówki, które będą przechowywane w pamięci podręcznej przeglądarki przez rok.

max-age: 31536000, public 

Teraz gdy otwieram Chrome DevTools i upewnij de opcja „Wyłącz cache” nie jest aktywna i załadować stronę po raz pierwszy (po wyczyszczeniu pamięci podręcznej) wszystkie zdjęcia się pobrać i mieć status 200. Po pełnym cyklu wszystkich obrazów w banerze sieć żąda zatrzymania i używane są obrazy z pamięci podręcznej.

Teraz, gdy robię zwykłe odświeżanie lub przechodzę do podstrony i klikam z powrotem, obrazy znajdujące się w pamięci podręcznej wydają się ignorowane. Spodziewam się zobaczyć szary komunikat "z pamięci podręcznej dysku" na karcie Sieć w devtools w Chrome. Zamiast tego widzę, że żądania mijają się co dwie sekundy z zielonym kółkiem statusu zamiast szarym, widzę przesyłane dane, więc mam wrażenie, że cache nie jest dostępny w ogóle z javascript. Po prostu pobiera obraz za każdym razem, gdy strona zostanie załadowana.

Każde żądanie na stronę domową wyzwala 4 żądania niezależnie od zasady buforowania obrazu.

Biorąc pod uwagę powyższe razem i nowy standard http2, większość serwerów i przeglądarek obsługuje teraz, myślę, że lepiej przestać używać lazyloading, ponieważ http2 załaduje wszystkie obrazy prawie jednocześnie.

Jeśli jest to błąd w Chrome Devtools, to naprawdę zaskakuje, że nikt tego jeszcze nie zauważył. ;)

Jeśli jest to prawdą, użycie lazyloading tylko zwiększa wykorzystanie pasma.

Proszę mnie poprawić, jeśli się mylę. :)

0

Zawsze wolę używać przykładu wspomnianego w Konva JS: Image Events, aby załadować obrazy.

  1. Trzeba mieć listę adresów URL obrazu jako przedmiotu lub tablicy, na przykład:

    var sources = { lion: '/assets/lion.png', monkey: '/assets/monkey.png' };

  2. Definiowanie definicji funkcji, gdzie odbiera lista adresów URL obrazu i funkcję oddzwonienia na liście argumentów, więc kiedy zakończy ładowanie obrazu można rozpocząć excution na swojej stronie internetowej:

function loadImages(sources, callback) { 
 
       var images = {}; 
 
       var loadedImages = 0; 
 
       var numImages = 0; 
 
       for (var src in sources) { 
 
        numImages++; 
 
       } 
 
       for (var src in sources) { 
 
        images[src] = new Image(); 
 
        images[src].onload = function() { 
 
         if (++loadedImages >= numImages) { 
 
          callback(images); 
 
         } 
 
        }; 
 
        images[src].src = sources[src]; 
 
       } 
 
      }

  1. Wreszcie, trzeba wywołać funkcję. Można to nazwać na przykład z jQuery „s Dokument Gotowe

$(document).ready(function(){ loadImages(sources, buildStage); });

Powiązane problemy