2017-04-26 3 views
5

생각에는 내가 너무 좋아하는 URL의 목록이 있습니다어떻게 이미지를 캐시에 저장 하시겠습니까?

[ '/images/1', '/images/2', ... ]

을 그리고 이미지 사이를 전환하는 빠른 있도록 사람들의 n를 프리 페치합니다. 내가 componentWillMount 지금 뭐하는 거지 것은 다음 imgNodes

componentWillMount() { 
     const { props } = this; 
     const { prefetchLimit = 1, document = dummyDocument, imgNodes } = props; 
     const { images } = document; 
     const toPrefecth = take(prefetchLimit, images); 
     const merged = zip(toPrefecth, imgNodes); 

     merged.forEach(([url, node]) => { 
     node.src = url; 
     }); 
    } 

가과 같이 정의되는 :

imgNodes: times(_ => new window.Image(), props.prefetchLimit),

times, ziptakeramda에서 오는. 에 관계없이 URL이 사용되는 경우의 EtagExpire 태그에 따라 브라우저 캐시 안타

<img src={url} />

:과 같이 반응의 내부

는 이제 해당 URL을 사용하는 경우. 또한 우리는 같은 방법으로 imgNodes을 재사용하면서 n - 1을 뷰 내부에 칠 때마다 다음 n 개의 이미지를 프리 페치 (prefetch) 할 계획입니다.

내 질문은 다음과 같습니다

  • 이도 유효한 아이디어는이 아이디어를 사용하는 100 개 이상의 구성 요소를 제공하지만 한 번에 볼 수 있습니까?

  • 이렇게하면 메모리 문제가 발생합니까? 구성 요소가 마운트 해제 될 때 imgNodes가 가비지 수집 될 것으로 가정합니다.

우리는 그래서 가게에서 이러한 이미지를 절약 할 수 redux를 사용하지만 캐싱을 처리하는 대신 브라우저의 자연 캐시를 활용하고 좋아하는 것 같다.

아이디어의 나쁜 점은 무엇입니까?

+0

너는 이것으로 어디든 갔니? 관심있어 ... –

+0

@MathieuK. 기본적으로 위에서 설명한 것과 동일한 구조/인터페이스를 사용하며 일반적인 HTTP 캐싱을 활용합니다. –

+1

그래서 브라우저/HTTP의 기본 동작을 사용 하시겠습니까? –

답변

1

모든 구성 요소에서이 작업을 수행 할 필요는 없습니다. 이미지를 다운로드하자 마자 브라우저에 의해 캐시되고 모든 구성 요소에서 액세스 할 수 있으므로 상위 구성 요소의 어딘가에 한 번만이 작업을 수행 할 수 있습니다.

이미지를 캐싱하여 만들려는 정확한 UX는 무엇인지 모르지만 코드는 이미지 다운로드 만 시작하지만 이미지 다운로드 중, 다운로드 완료 또는 실패 여부는 알 수 없습니다. 예를 들어, 이미지를 다운로드하거나 (부드럽게 만들기 위해) 이미지를 다운로드 할 때만 이미지를 변경하거나 클래스를 구성 요소에 추가하는 버튼을 표시하려면 현재 코드가 실망시킬 수 있습니다.

약속으로 해결하는 것이 좋습니다.

// create an utility function somewhere 
const checkImage = path => 
    new Promise(resolve => { 
     const img = new Image() 
     img.onload =() => resolve(path) 
     img.onerror =() => reject() 

     img.src = path 
    }) 

... 

// then in your component 
constructor(props) { 
    super(props) 
    this.state = { imagesLoaded: false } 
} 

// doesn't really matter whether you do it in componentWillMount or componentDidMount 
    componentWillMount() { 
     Promise.all(
      R.take(limit, imgUrls) 
      .map(checkImage) 
     ).then(() => this.setState({ imagesLoaded: true }), 
       () => console.error('could not load images')) 
    } 

render =() => 
    this.state.imagesLoaded 
     ? <BeautifulComponent /> 
     : <Skeleton /> 

메모리 사용량과 관련해서는 아무 것도 나빠질 것이라고 생각하지 않습니다. 브라우저는 일반적으로 병렬 xhr 요청 수를 제한하므로 사용하지 않은 이미지가 가비지 수집되므로 (브라우저 캐시에 보존되므로) 크래시가 발생하는 거대한 힙 사용량 스파이크를 만들 수 없습니다.

Redux 스토어는 앱 애셋이 아닌 앱 상태를 저장하는 곳이지만 어쨌든 거기에 실제 이미지를 저장할 수는 없습니다.

관련 문제