javascript 자바스크립트 - 자바 스크립트로 어떻게 이미지를 캐시합니까?




넣기 배열 (8)

친구들과 저는 미래에 더 빨리 이미지를 표시하기 위해 특정 이미지를 캐시하고 싶은 웹 사이트에서 작업하고 있습니다. 두 가지 주요 질문이 있습니다.

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

또한 캐시 된 버전의 이미지가 만료 될 설정할 수 있습니까?

예제 및 / 또는이를 더 설명하는 페이지에 대한 링크가 포함 된 경우 많은 도움이 될 것입니다.

원시 자바 스크립트 또는 jQuery 버전을 사용하여 문제가 없습니다.


Answers

나는 항상 Konva JS : 이미지 이벤트 에서 언급 한 예제를 사용하여 이미지 를로드하는 것을 선호한다.

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


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

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

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

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

따라서 이미지를 미리 캐시하려면 브라우저에 이미지를로드해야합니다. 당신이 이미지의 무리를 precach하고 싶다면, 아마 자바 스크립트에서 할 때 일반적으로 페이지로드를 견디지 ​​않을 것이므로 자바 스크립트로 그것을하는 것이 가장 좋습니다. 당신은 이렇게 할 수 있습니다 :

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

이 함수는 원하는만큼 여러 번 호출 할 수 있으며 매번 precache에 더 많은 이미지를 추가합니다.

자바 스크립트를 통해 이미지를 미리로드하면 브라우저에서 해당 이미지를 캐쉬에 넣고 웹 페이지의 다른 위치에있는 일반 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);

JS를 통해 비동기 미리로드 이미지에 대한 비슷한 대답 이 있습니다. 동적으로로드하는 것은로드하는 것과 동일합니다. 캐시됩니다.

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


lazyload 이미지에 비슷한 기술을 사용하지만 Javascript가 첫 번째 로딩 할 때 브라우저 캐시에 액세스하지 않음을 알 수는 없습니다.

내 예 :

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

이러한 이미지에는 수정할 때마다 고유 한 URL이 있으므로 브라우저에 1 년 동안 캐시되는 캐싱 헤더가 생성됩니다.

max-age: 31536000, public

이제 Chrome Devtools를 열고 '캐시 사용 안함'옵션이 활성화되어 있지 않고 캐시를 지운 후 처음으로 페이지를로드하면 모든 이미지가 가져오고 200 개의 상태가됩니다. 배너의 모든 이미지가 한주기 씩 지나면 네트워크 요청이 중지되고 캐시 된 이미지가 사용됩니다.

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

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

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

이것이 Chrome Devtools의 버그 인 경우 아직 아무도 눈치 채지 못했습니다. ;)

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

내가 틀렸다면 나를 바로 잡아주세요. :)


다음과 같은 몇 가지 사항을 살펴볼 수 있습니다.

이미지 미리로드
.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 요청이 대역폭을 떨어 뜨리고 다른 사람들은 "인지 된"로드가 더 좋다고 말합니다. 나는 이것을 공중에 남겨 둘 것이다.


귀하의 질문에 "javascript를 사용하여"라고하더라도, 링크 태그의 prefetch 속성을 사용하여 자산을 미리로드 할 수 있습니다. 이 글을 쓰는 시점에서 (2016 년 8 월 10 일) Safari에서는 지원되지 않지만 다른 모든 곳에서는 사용할 수 있습니다.

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

지원에 대한 자세한 정보는 http://caniuse.com/#search=prefetch 하십시오.

Microsoft가 지원을 중단했기 때문에 IE 9,10은 사용 caniuse 매트릭스에 포함되어 있지 않습니다.

그래서 당신이 정말 자바 스크립트를 사용하여 붙어 있다면, 당신은 동적으로 이러한 요소를 귀하의 페이지에 추가하려면 jquery를 사용할 수 있습니다 ;-)


JavaScript에서 속성 제거

대부분의 옵션이 잘못되었거나 답변이 중복되어 있기 때문에가 아닌 여러 가지 옵션이이 페이지에 나와 있습니다. 적절한 기술은 현재 상황이나 당신이나 당신의 목표에 달려 있기 때문입니다. 팀이 성취하려고 노력하고있다. 질문에 대한 답을 명확히하기 위해 알아야 할 사항은 다음과 같습니다.

  1. 타겟팅하는 ECMAScript 버전
  2. 속성을 제거하려는 객체 유형의 범위와 생략 할 수 있어야하는 속성 이름의 유형 (문자열 만? 기호? 임의의 객체에서 매핑 된 약한 참조? 이들은 모두 JavaScript에서 몇 년 동안 속성 포인터 유형이었습니다 )
  3. 귀하와 귀하의 팀이 사용하는 프로그래밍 정신 / 패턴. 당신은 기능적 접근법을 선호하고 당신의 팀에서 돌연변이가 일어나거나 야생형 돌연변이 객체 지향 기술을 사용합니까?
  4. 순수한 자바 스크립트에서 이것을 달성하고 싶습니까? 아니면 타사 라이브러리를 사용할 의향이 있습니까?

이 네 개의 쿼리가 응답되면, 목표를 달성하기 위해 JavaScript에서 "속성 제거"의 네 가지 카테고리가 기본적으로 선택됩니다. 그들은:

변이 형 개체 속성 삭제, 안전하지 않음

이 범주는 원래 참조를 유지 / 계속 사용하고 코드에서 상태 비 저장 기능 원리를 사용하지 않을 때 객체 리터럴 또는 객체 인스턴스에서 작동하기위한 범주입니다. 이 카테고리의 구문 예는 다음과 같습니다.

'use strict'
const iLikeMutatingStuffDontI = { myNameIs: 'KIDDDDD!', [Symbol.for('amICool')]: true }
delete iLikeMutatingStuffDontI[Symbol.for('amICool')] // true
Object.defineProperty({ myNameIs: 'KIDDDDD!', 'amICool', { value: true, configurable: false })
delete iLikeMutatingStuffDontI['amICool'] // throws

이 카테고리는 가장 오래되고 가장 간단하며 가장 널리 지원되는 부동산 제거 카테고리입니다. Symbol첫 번째 버전을 제외한 모든 버전의 JavaScript에서 작동하며 문자열 외에도 인덱스를 지원합니다 . 그러나 일부 프로그래밍 원칙을 위반하고 성능에 영향을 미치는 것은 돌연변이입니다. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… 사용될 때 캐치되지 않는 예외가 발생할 수도 있습니다 .

나머지 기반 문자열 속성 누락

이 카테고리는 비 변형 접근법이 필요하고 기호 키를 고려할 필요가 없을 때 새로운 ECMAScript 형식의 일반 객체 또는 배열 인스턴스에서 작동하기위한 것입니다.

const foo = { name: 'KIDDDDD!', [Symbol.for('isCool')]: true }
const { name, ...coolio } = foo // coolio doesn't have "name"
const { isCool, ...coolio2 } = foo // coolio2 has everything from `foo` because `isCool` doesn't account for Symbols :(

변경 객체 속성 삭제, 안전

이 범주는 구성 할 수없는 속성에서 throw되는 예외를 방지하면서 원래 참조를 유지 / 계속 사용하려는 경우 개체 리터럴 또는 개체 인스턴스에서 작동합니다.

'use strict'
const iLikeMutatingStuffDontI = { myNameIs: 'KIDDDDD!', [Symbol.for('amICool')]: true }
Reflect.deleteProperty(iLikeMutatingStuffDontI, Symbol.for('amICool')) // true
Object.defineProperty({ myNameIs: 'KIDDDDD!', 'amICool', { value: true, configurable: false })
Reflect.deleteProperty(iLikeMutatingStuffDontI, 'amICool') // false

또한 개체를 제자리에서 돌연변이시키는 것은 stateless가 아니지만 함수의 성격을 사용하여 명령문에서 Reflect.deleteProperty불가능한 부분 적용 및 기타 기능적 기술을 수행 할 수 있습니다 delete.

구문 기반 문자열 속성 누락

이 카테고리는 비 변형 접근법이 필요하고 기호 키를 고려할 필요가 없을 때 새로운 ECMAScript 형식의 일반 객체 또는 배열 인스턴스에서 작동하기위한 것입니다.

const foo = { name: 'KIDDDDD!', [Symbol.for('isCool')]: true }
const { name, ...coolio } = foo // coolio doesn't have "name"
const { isCool, ...coolio2 } = foo // coolio2 has everything from `foo` because `isCool` doesn't account for Symbols :(

라이브러리 기반 속성 생략

이 카테고리는 일반적으로 Symbol에 대한 회계 및 하나의 명세서에서 둘 이상의 속성을 생략하는 것을 포함하여 더 큰 기능적 유연성을 허용합니다.

const o = require("lodash.omit")
const foo = { [Symbol.for('a')]: 'abc', b: 'b', c: 'c' }
const bar = o(foo, 'a') // "'a' undefined"
const baz = o(foo, [ Symbol.for('a'), 'b' ]) // Symbol supported, more than one prop at a time, "Symbol.for('a') undefined"






javascript jquery image caching browser-cache