Skip to content

Commit f59a963

Browse files
committed
feat: webp support 🚀
1 parent b1e6444 commit f59a963

File tree

3 files changed

+23
-7
lines changed

3 files changed

+23
-7
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,13 @@ $ npm install react-lite-yt-embed
3333
- Preload the YouTube thumbnail image when page loaded. [Make image load faster]
3434
- Preconnect YouTube domain when mouse hover on the component. [Save 3 round-trip-time (DNS lookup + TCP handshake + SSL negotiation) before user click play button, making iframe load faster]
3535

36+
### WebP Support
37+
'react-lite-yt-embed' support WebP image format, which is generally 25% - 35% smaller than jpg image, so the network request time will also decrease, making your web app render even faster.
38+
39+
If you use some browsers that not totally support WebP, for example, Safari, 'react-lite-yt-embed' will fallback the image to jpg automatically.
40+
41+
You can see WebP browser support [here](https://caniuse.com/?search=webp).
42+
3643
## Basic Usage
3744

3845
```javascript

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
2-
"version": "1.2.3",
2+
"version": "1.2.4",
33
"license": "MIT",
44
"main": "dist/index.js",
55
"typings": "dist/index.d.ts",

src/LiteYoutubeEmbed.tsx

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState, useEffect, useMemo, useCallback } from 'react';
1+
import React, { useState, useEffect, useMemo, useCallback, useRef } from 'react';
22

33
import styles from './styles.module.css';
44
import { qs } from './utils';
@@ -35,13 +35,15 @@ const LiteYoutubeEmbed = ({
3535
}: ILiteYouTubeEmbedProps): React.ReactElement => {
3636
const muteParam = mute || defaultPlay ? '1' : '0'; // Default play must be mute
3737
const queryString = useMemo(() => qs({ autoplay: '1', mute: muteParam, ...params }), []);
38-
const defaultPosterUrl = isMobile ? `https://i.ytimg.com/vi/${id}/${mobileResolution}.jpg` : `https://i.ytimg.com/vi/${id}/${desktopResolution}.jpg`;
38+
const defaultPosterUrl = isMobile ? `https://i.ytimg.com/vi_webp/${id}/${mobileResolution}.webp` : `https://i.ytimg.com/vi_webp/${id}/${desktopResolution}.webp`;
39+
const fallbackPosterUrl = isMobile ? `https://i.ytimg.com/vi/${id}/${mobileResolution}.jpg` : `https://i.ytimg.com/vi/${id}/${desktopResolution}.jpg`;
3940
const ytUrl = noCookie ? 'https://www.youtube-nocookie.com' : 'https://www.youtube.com';
4041
const iframeSrc = isPlaylist ? `${ytUrl}/embed/videoseries?list=${id}` : `${ytUrl}/embed/${id}?${queryString}`; // * Lo, the youtube placeholder image! (aka the thumbnail, poster image, etc)
4142

4243
const [isPreconnected, setIsPreconnected] = useState(false);
4344
const [iframeLoaded, setIframeLoaded] = useState(defaultPlay);
4445
const [posterUrl, setPosterUrl] = useState(defaultPosterUrl);
46+
const isWebpSupported = useRef(true);
4547

4648
const warmConnections = useCallback(() => {
4749
if (isPreconnected) return;
@@ -55,12 +57,19 @@ const LiteYoutubeEmbed = ({
5557

5658
// fallback to hqdefault resolution if maxresdefault is not supported.
5759
useEffect(() => {
58-
if ((isMobile && mobileResolution === 'hqdefault') || (!isMobile && desktopResolution === 'hqdefault')) return;
60+
if ((isMobile && mobileResolution === 'hqdefault') || (!isMobile && desktopResolution === 'hqdefault') && !isWebpSupported.current) return;
5961

60-
// If the image ever loaded one time, this part will use cache data, won't cause a new network request.
62+
// If the image ever loaded one time (in this case is preload link), this part will use cache data, won't cause a new network request.
6163
const img = new Image();
6264
img.onload = function() {
63-
if (img.width === 120 || img.width === 0) setPosterUrl(`https://i.ytimg.com/vi/${id}/hqdefault.jpg`);
65+
if (img.width === 120 || img.width === 0) {
66+
if (!isWebpSupported.current) setPosterUrl(`https://i.ytimg.com/vi/${id}/hqdefault.jpg`);
67+
else setPosterUrl(`https://i.ytimg.com/vi_webp/${id}/hqdefault`);
68+
}
69+
};
70+
img.onerror = function() {
71+
isWebpSupported.current = false;
72+
setPosterUrl(fallbackPosterUrl);
6473
};
6574
img.src = posterUrl;
6675
}, [id, posterUrl]);
@@ -89,7 +98,7 @@ const LiteYoutubeEmbed = ({
8998
onPointerOver={warmConnections}
9099
className={`${styles['yt-lite']} ${iframeLoaded && styles['lyt-activated']}`}
91100
>
92-
<img
101+
<img
93102
src={posterUrl}
94103
className={`${styles['yt-lite-thumbnail']}`}
95104
loading={lazyImage ? 'lazy' : undefined}/>

0 commit comments

Comments
 (0)