Skip to content

Commit 8ba8d6a

Browse files
committed
speed(homepage) offload images until in viewport
1 parent 198c534 commit 8ba8d6a

File tree

3 files changed

+81
-24
lines changed

3 files changed

+81
-24
lines changed
Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,33 @@
11
import React from 'react';
2+
import VisibilitySensor from '../VisibilitySensor/VisibilitySensor';
3+
import SmallIcon from '../../assets/icon-square-small-slack.png';
24
import './Contributors.scss';
35

4-
export default ({contributors}) => {
5-
if (!contributors.length) {
6-
return <noscript />;
7-
}
8-
9-
return (
10-
<div className="contributors">
11-
<div className="contributors__list">
12-
{
13-
contributors.map(contributor => (
14-
<a key={ contributor }
15-
className="contributor"
16-
href={ `https://github.com/${contributor}` }>
17-
<img alt={ contributor } src={ `https://github.com/${contributor}.png?size=90` } />
18-
<span className="contributor__name"> {contributor}</span>
19-
</a>
20-
))
21-
}
6+
export default class Contributors extends VisibilitySensor {
7+
render() {
8+
const { isVisible } = this.state;
9+
const { contributors } = this.props;
10+
11+
if (!contributors.length) {
12+
return <noscript />;
13+
}
14+
15+
return (
16+
<div className="contributors" ref={ this.visibilityTarget }>
17+
<div className="contributors__list">
18+
{
19+
contributors.map(contributor => (
20+
<a key={ contributor }
21+
className="contributor"
22+
href={ `https://github.com/${contributor}` }>
23+
<img alt={ contributor }
24+
src={ isVisible ? `https://github.com/${contributor}.png?size=90` : SmallIcon } />
25+
<span className="contributor__name"> {contributor}</span>
26+
</a>
27+
))
28+
}
29+
</div>
2230
</div>
23-
</div>
24-
);
25-
};
31+
);
32+
}
33+
}

src/components/Support/Support.jsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Import External Dependencies
22
import React from 'react';
3+
import VisibilitySensor from '../VisibilitySensor/VisibilitySensor';
34

45
// Import Data
56
import Backers from './_supporters.json';
@@ -61,9 +62,10 @@ function formatMoney(number) {
6162
return str;
6263
}
6364

64-
export default class Support extends React.Component {
65+
export default class Support extends VisibilitySensor {
6566
render() {
6667
let { rank } = this.props;
68+
const { isVisible } = this.state;
6769

6870
let supporters = SUPPORTERS;
6971
let minimum, maximum, maxAge, limit, random;
@@ -108,7 +110,7 @@ export default class Support extends React.Component {
108110
}
109111

110112
return (
111-
<div className="support">
113+
<div className="support" ref={ this.visibilityTarget }>
112114
<div className="support__description">
113115
{ rank === 'backer' ? (
114116
<p>
@@ -134,7 +136,7 @@ export default class Support extends React.Component {
134136
href={ supporter.website || `https://opencollective.com/${supporter.slug}` }>
135137
{<img
136138
className={ `support__${rank}-avatar` }
137-
src={ supporter.avatar || SmallIcon }
139+
src={ (isVisible && supporter.avatar) ? supporter.avatar : SmallIcon }
138140
alt={ supporter.name || supporter.slug ? `${supporter.name || supporter.slug}'s avatar` : 'avatar' }
139141
onError={ this._handleImgError } />}
140142
</a>
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import React from 'react';
2+
3+
export default class VisibilitySensor extends React.Component {
4+
state = {
5+
isVisible: false
6+
};
7+
8+
constructor(props) {
9+
super(props);
10+
this.visibilityTarget = React.createRef();
11+
}
12+
13+
componentWillUnmount() {
14+
this.stopListeningForVisibility();
15+
}
16+
17+
componentDidMount () {
18+
if (this.visibilityTarget.current) {
19+
this.startListeningForVisibility();
20+
}
21+
}
22+
23+
startListeningForVisibility = () => {
24+
if (typeof IntersectionObserver !== 'function') {
25+
// fall back to rendering images
26+
// browser doesnt support IntersectionObserver;
27+
return this.setState({ isVisible: true });
28+
}
29+
30+
this.observer = new IntersectionObserver(this.visibilityChanged, {
31+
threshold: 0.05
32+
});
33+
this.observer.observe(this.visibilityTarget.current);
34+
}
35+
36+
stopListeningForVisibility = () => {
37+
this.observer && this.observer.unobserve(this.visibilityTarget.current);
38+
delete this.observer;
39+
}
40+
41+
visibilityChanged = (entries) => {
42+
if (entries[0].isIntersecting) {
43+
this.setState({ isVisible: true });
44+
this.stopListeningForVisibility();
45+
}
46+
}
47+
}

0 commit comments

Comments
 (0)