자바 스크립트에서 이미지를 캐시하는 방법


84

내 친구와 저는 특정 이미지를 나중에 더 빨리 표시하기 위해 캐시하려는 웹 사이트에서 작업하고 있습니다. 두 가지 주요 질문이 있습니다.

  1. 이미지를 어떻게 캐시합니까?
  2. 캐시 된 이미지를 어떻게 사용합니까? (단지 확인하기 위해 이미지가 페이지 A에 캐시 된 경우 캐시에서 호출하여 페이지 B에서 사용할 수 있습니다.)

또한 이미지의 캐시 된 버전이 만료되는 시기 를 설정할 수 있습니까?

더 자세히 설명하는 페이지에 대한 예제 및 / 또는 링크가 포함되어 있으면 매우 감사하겠습니다.

원시 Javascript 또는 jQuery 버전을 사용하는 것이 좋습니다.


12
당신은하지 않습니다. 브라우저가 그렇습니다.
Pointy

브라우저가 이미지를 자동으로 캐시합니까?
Logan Besecker 2012

8
@Logan : 예, 브라우저는 이미지를 자동으로 캐시합니다. 단, 서버가 브라우저에 캐시해도 안전하다는 것을 알리는 데 필요한 헤더를 보내면됩니다. (이 헤더는 브라우저에게 질문의 일부입니다 만료 시간을 말할 수 있습니다.)
icktoofay

내 브라우저가 필요한 헤더를 보내고 있는지 어떻게 확인할 수 있습니까?
Logan Besecker 2012

1
@LoganBesecker 브라우저 개발 도구의 네트워크 섹션에서 응답 헤더를 확인할 수 있습니다.
jlaceda

답변:


133

이미지가 어떤 방식 으로든 브라우저에로드되면 브라우저 캐시에 있으며 이미지가있는 한 현재 페이지에서 사용하든 다른 페이지에서 사용하든 다음에 사용할 때 훨씬 더 빠르게로드됩니다. 브라우저 캐시에서 만료되기 전에 사용됩니다.

따라서 이미지를 미리 캐시하려면 브라우저에 이미지를로드하기 만하면됩니다. 여러 이미지를 미리 캐시하려면 일반적으로 javascript에서 수행 할 때 페이지로드를 유지하지 않으므로 javascript를 사용하여 수행하는 것이 가장 좋습니다. 다음과 같이 할 수 있습니다.

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"]);

이 함수는 원하는만큼 호출 할 수 있으며 매번 프리 캐시에 이미지를 더 추가합니다.

이미지가 자바 스크립트를 통해 이와 같이 미리로드되면 브라우저는 해당 이미지를 캐시에 저장하고 다른 위치 (웹 페이지)의 일반 URL을 참조 할 수 있으며 브라우저는 브라우저가 아닌 캐시에서 해당 URL을 가져옵니다. 회로망.

결국 시간이 지남에 따라 브라우저 캐시가 가득 차서 한동안 사용되지 않은 가장 오래된 것을 버릴 수 있습니다. 따라서 결국 이미지는 캐시에서 플러시되지만 잠시 동안 거기에 있어야합니다 (캐시의 크기와 다른 검색이 수행 된 정도에 따라 다름). 이미지가 실제로 다시 미리로드되거나 웹 페이지에서 사용될 때마다 브라우저 캐시의 위치를 ​​자동으로 새로 고쳐서 캐시에서 플러시 될 가능성을 줄입니다.

브라우저 캐시는 크로스 페이지이므로 브라우저에로드 된 모든 페이지에서 작동합니다. 따라서 사이트의 한 위치에서 사전 캐시 할 수 있으며 브라우저 캐시는 사이트의 다른 모든 페이지에서 작동합니다.


위와 같이 미리 캐싱하면 이미지가 비동기 적으로로드되므로 페이지로드 또는 표시를 차단하지 않습니다. 그러나 페이지에 자체 이미지가 많은 경우 이러한 사전 캐시 이미지는 페이지에 표시되는 이미지와 대역폭 또는 연결을두고 경쟁 할 수 있습니다. 일반적으로 이것은 눈에 띄는 문제는 아니지만 느린 연결에서이 사전 캐싱으로 인해 기본 페이지로드 속도가 느려질 수 있습니다. 미리로드 된 이미지가 마지막으로로드되는 것이 괜찮다면 다른 모든 페이지 리소스가 이미로드 될 때까지 미리로드를 시작하기 위해 대기하는 함수 버전을 사용할 수 있습니다.

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);

이 예에서는 각 URL에 대해 새 이미지 개체를 만듭니다. 당신은 루프의 IMG 변수 외부를 설정하고 단지 SRC를 업데이트하는 경우, 동일한 효과를 가지고 자원을 줄이려고한다
cadlac

2
@cadlac-그러나 브라우저가 실제로 각 이미지를 다운로드하고 캐시하도록하려면 새 .src 속성을 설정하기 전에 하나의 이미지 다운로드가 완료 될 때까지 기다려야합니다. 그렇지 않으면 브라우저가 이전 다운로드를 중지하고 성공적으로 캐시하지 못할 수 있습니다.
jfriend00 2014-07-11

기다릴 필요없이 최신 버전의 브라우저에서 작동하는 것 같지만 좋은 지적입니다. 나는 그것의 호환성 :보고 일부 오래된 브라우저에서 그것을 밖으로 시도해야합니다
cadlac

@cadlac-필요 없습니다. Image()이미지로드가 완료되면 목록 에서 요소 를 제거하도록 코드를 업데이트했습니다 . 이미지로드가 완료 될 때까지 기다리는 것이 더 안전합니다.
jfriend00 2014-07-14

1
다른 문서 리소스가로드 될 때까지 기다리는 다른 버전의 스크립트를 추가하여 이미지 미리로드가 가시적 인 페이지 리소스로드와 대역폭 경쟁을하지 않도록했습니다.
jfriend00 2015-07-30

13

@Pointy가 자바 스크립트로 이미지를 캐시하지 않는다고 말했듯이 브라우저가 그렇게합니다. 그래서 이것은 당신이 요구하는 것일 수도 있고 아닐 수도 있습니다 ...하지만 자바 스크립트를 사용하여 이미지를 미리로드 할 수 있습니다. 사전로드하려는 모든 이미지를 배열에 넣고 해당 배열의 모든 이미지를 숨겨진 img 요소에 넣으면 이미지를 효과적으로 사전로드 (또는 캐시) 할 수 있습니다.

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

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

2
한 페이지에 이미지를 미리로드하고 (표시하지 않고) 다음 페이지에 표시 할 수 있습니까?
Logan Besecker

2
내가 아는 한 한 페이지에 이미지를 미리로드하면 브라우저 캐시에 입력 된 다음 다른 페이지에 더 빨리 표시됩니다. 이것이 틀렸다면 누군가 나를 바로 잡으십시오.
Trav McKinney

4

질문에 "자바 스크립트 사용"이라고되어 ​​있지만 prefetch링크 태그 의 속성을 사용하여 자산을 미리로드 할 수 있습니다 . 이 글을 쓰는 현재 (2016 년 8 월 10 일) Safari에서는 지원되지 않지만 거의 모든 곳에서 지원됩니다.

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

지원에 대한 추가 정보 : http://caniuse.com/#search=prefetch

IE 9,10은 caniuseMicrosoft에서 지원을 중단했기 때문에 매트릭스에 나열되지 않았습니다 .

따라서 실제로 자바 스크립트를 사용하는 데 어려움을 겪고 있다면 jquery를 사용하여 이러한 요소를 페이지에 동적으로 추가 할 수도 있습니다 ;-)


1
좋은 좋은 좋은 좋은!
Bhargav Nanekalva

3

다음과 같은 몇 가지 사항을 확인할 수 있습니다.

이미지 미리로드
.htaccess 파일에서 캐시 시간 설정 이미지의
파일 크기 및 base64 인코딩.

미리로드 : http://perishablepress.com/3-ways-preload-images-css-javascript-ajax/

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

base64 인코딩에 대한 몇 가지 다른 생각이 있습니다. 일부는 http 요청이 대역폭을 저하 시킨다고 말하는 반면 다른 사람들은 "인식 된"로딩이 더 좋다고 말합니다. 나는 이것을 공중에 남겨 둘 것이다.


3

답변의 완성도를위한 추가 : HTML로 미리로드

<link rel="preload" href="bg-image-wide.png" as="image">

다른 사전로드 기능이 있지만 다음과 같이 목적에 적합한 것은 없습니다 <link rel="preload">.

  • <link rel="prefetch">오랫동안 브라우저에서 지원되었지만 다음 탐색 / 페이지로드 (예 : 다음 페이지로 이동할 때)에 사용될 리소스를 미리 가져 오기위한 것입니다. 이것은 괜찮지 만 현재 페이지에는 유용하지 않습니다! 또한 브라우저는 미리로드 된 리소스보다 프리 페치 리소스에 낮은 우선 순위를 부여합니다. 현재 페이지가 다음 페이지보다 더 중요합니다. 자세한 내용은 링크 프리 페치 FAQ 를 참조하세요.
  • <link rel="prerender">백그라운드에서 지정된 웹 페이지를 렌더링하여 사용자가 탐색 할 경우로드 속도를 높입니다. 사용자 대역폭을 낭비 할 가능성이 있기 때문에 Chrome은 대신 프리 렌더를 NoState 프리 페치로 취급합니다.
  • <link rel="subresource"> 얼마 전에 Chrome에서 지원되었으며 사전로드와 동일한 문제를 해결하기위한 것이었지만 문제가있었습니다. 항목에 대한 우선 순위를 결정할 방법이 없었기 때문에 (당시에는 존재하지 않았던) 상당히 낮은 우선 순위로 가져 왔습니다.

많은 스크립트 기반 리소스 로더가 있지만 브라우저의 가져 오기 우선 순위 지정 대기열에 대한 권한이 없으며 거의 ​​동일한 성능 문제가 발생합니다.

출처 : https://developer.mozilla.org/en-US/docs/Web/HTML/Preloading_content


1

나는이 비슷한 대답 JS를 통해 비동기 사전로드 된 이미지를. 동적으로로드하는 것은 정상적으로로드하는 것과 같습니다. 그들은 캐시합니다.

캐싱은 브라우저를 제어 할 수 없지만 서버를 통해 설정할 수 있습니다. 요청시 정말 새로운 리소스를로드해야하는 경우 캐시 버스터 기술 을 사용하여 새로운 리소스를 강제로로드 할 수 있습니다 .


1

비슷한 기술을 사용하여 이미지를 지연로드하지만 Javascript가 처음로드 할 때 브라우저 캐시에 액세스하지 않는다는 것을 알 수는 없습니다.

내 예 :

내 홈페이지에 4 개의 이미지가있는 회전 배너가 있습니다. 슬라이더는 2 초를 기다립니다. 자바 스크립트가 다음 이미지를로드하고 2 초를 기다립니다.

이러한 이미지에는 수정할 때마다 변경되는 고유 한 URL이 있으므로 브라우저에서 1 년 동안 캐시 할 캐시 헤더를 얻습니다.

max-age: 31536000, public

이제 Chrome Devtools를 열고 '캐시 사용 안함'옵션이 활성화되어 있지 않은지 확인하고 처음으로 페이지를로드하면 (캐시를 지운 후) 모든 이미지가 가져 와서 200 상태가됩니다. 배너에있는 모든 이미지의 전체주기 후 네트워크 요청이 중지되고 캐시 된 이미지가 사용됩니다.

이제 정기적으로 새로 고치거나 하위 페이지로 이동하여 다시 클릭하면 캐시에있는 이미지가 무시되는 것 같습니다. Chrome devtools의 네트워크 탭에 "디스크 캐시에서"라는 회색 메시지가 표시 될 것으로 예상됩니다. 대신 요청이 회색 대신 녹색 상태 원으로 2 초마다 전달되는 것을보고 데이터가 전송되는 것을 확인하므로 캐시가 자바 스크립트에서 전혀 액세스되지 않는다는 인상을받습니다. 페이지가로드 될 때마다 이미지를 가져옵니다.

따라서 홈페이지에 대한 각 요청은 이미지의 캐싱 정책에 관계없이 4 개의 요청을 트리거합니다.

위의 내용과 대부분의 웹 서버 및 브라우저가 현재 지원하는 새로운 http2 표준을 고려할 때 http2는 거의 동시에 모든 이미지를로드하므로 지연로드 사용을 중지하는 것이 좋습니다.

이것이 Chrome Devtools의 버그라면 아무도 이것을 아직 눈치 채지 못한 것이 정말 놀랍습니다. ;)

이것이 사실이라면 지연 로딩을 사용하면 대역폭 사용량 만 증가합니다.

내가 틀렸다면 나를 고쳐주세요. :)


1

요즘에는 이미지 렌더링 프로세스를 캐시하고 개선하기 위해 Google 에서 제안한 새로운 기술이 있습니다.

  1. JavaScript Lazysizes 파일 포함 : lazysizes.js
  2. 사용하려는 html 파일에 파일을 추가하십시오. <script src="lazysizes.min.js" async></script>
  3. lazyload이미지에 클래스를 추가합니다 . <img data-src="images/flower3.png" class="lazyload" alt="">

0

예, 브라우저는 자동으로 이미지를 캐시합니다.

그러나 이미지 캐시가 만료되도록 설정할 수 있습니다. 이 Stack Overflow 질문과 답변을 확인하십시오.

정적 이미지의 캐시 만료


0

저는 항상 Konva JS : Image Events 에 언급 된 예제를 사용하여 이미지 를로드 하는 것을 선호합니다 .

  1. 이미지 URL 목록이 객체 또는 배열로 있어야합니다. 예를 들면 다음과 같습니다.

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

  2. 이미지 URL 목록과 인수 목록에서 콜백 함수를 수신하는 함수 정의를 정의하여 이미지로드가 완료되면 웹 페이지에서 실행을 시작할 수 있습니다.

    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. 마지막으로 함수를 호출해야합니다. 예를 들어 jQueryDocument Ready 에서 호출 할 수 있습니다.

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.