-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Fixes JS Render Blocking (#34)
* loading js script dynamically to avoid render blocking behavior * adding checks for widget/player instances before trying to load the script, adding dev mode warnings
- Loading branch information
1 parent
5d6fa5a
commit eb3a8ff
Showing
3 changed files
with
236 additions
and
153 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,7 +7,7 @@ import type { CloudinaryVideoPlayerOptions, CloudinaryVideoPlayerOptionsLogo } f | |
import type { GetCldImageUrlOptions } from "../helpers/getCldImageUrl"; | ||
import type { GetCldVideoUrlOptions } from "../helpers/getCldVideoUrl"; | ||
const PLAYER_VERSION = '2.0.5'; | ||
const PLAYER_VERSION = '2.1.0'; | ||
export interface CldVideoPlayerProps extends Omit<CloudinaryVideoPlayerOptions, "autoplayMode" | "cloud_name" | "controlBar" | "height" | "logoImageUrl" | "logoOnclickUrl" | "posterOptions" | "publicId" | "secure" | "showLogo" | "width"> { | ||
class?: string; | ||
|
@@ -73,82 +73,101 @@ if ( className ) { | |
/> | ||
</div> | ||
|
||
<script is:inline src={`https://unpkg.com/cloudinary-video-player@${PLAYER_VERSION}/dist/cld-video-player.min.js`}></script> | ||
|
||
<script> | ||
import type { CloudinaryVideoPlayer } from '@cloudinary-util/types'; | ||
|
||
interface Cloudinary { | ||
videoPlayer: (video: HTMLVideoElement, options: {}) => CloudinaryVideoPlayer; | ||
import type { CloudinaryVideoPlayer } from '@cloudinary-util/types'; | ||
import { loadScript } from '../lib/util'; | ||
|
||
interface Cloudinary { | ||
videoPlayer: (video: HTMLVideoElement, options: {}) => CloudinaryVideoPlayer; | ||
} | ||
|
||
window.addEventListener('load', async () => { | ||
const videos = document.querySelectorAll('.astro-cloudinary-cldvideoplayer') as NodeListOf<HTMLVideoElement>; | ||
|
||
if ( videos.length === 0 ) return; | ||
|
||
// Verify that the script already hasn't been loaded before trying to load it again | ||
|
||
if ( !('cloudinary' in window) || typeof (window.cloudinary as Cloudinary).videoPlayer !== 'function' ) { | ||
await loadScript('https://unpkg.com/[email protected]/dist/cld-video-player.min.js'); | ||
} | ||
|
||
window.addEventListener('load', () => { | ||
if ( 'cloudinary' in window ) { | ||
const cloudinary = window.cloudinary as Cloudinary; | ||
const videos = document.querySelectorAll('.astro-cloudinary-cldvideoplayer') as NodeListOf<HTMLVideoElement>; | ||
|
||
if ( import.meta.env.MODE === 'development' ) { | ||
const playerIds = Array.from(videos).map(video => video.dataset.cldvideoplayerId); | ||
if ( new Set(playerIds).size !== playerIds.length ) { | ||
console.warn('[CldVideoPlayer] Multiple instances of the same video detected on the page which may cause unexpected results. Try adding a unique id to each player.'); | ||
} | ||
} | ||
|
||
videos.forEach(video => { | ||
const playerOptions = video.dataset.cldvideoplayerOptions && JSON.parse(video.dataset.cldvideoplayerOptions); | ||
const player = cloudinary.videoPlayer(video, playerOptions); | ||
|
||
if ( !player ) return; | ||
|
||
// Loop through all avialable player events and create custom event callbacks | ||
|
||
const events = [ | ||
'loadstart', | ||
'suspend', | ||
'abort', | ||
'error', | ||
'emptied', | ||
'stalled', | ||
'loadedmetadata', | ||
'loadeddata', | ||
'canplay', | ||
'canplaythrough', | ||
'playing', | ||
'waiting', | ||
'seeking', | ||
'seeked', | ||
'ended', | ||
'durationchange', | ||
'timeupdate', | ||
'progress', | ||
'play', | ||
'pause', | ||
'ratechange', | ||
'volumechange', | ||
'fullscreenchange', | ||
'posterchange', | ||
'mute', | ||
'unmute', | ||
'percentsplayed', | ||
'timeplayed', | ||
'seek', | ||
'sourcechanged', | ||
'qualitychanged', | ||
]; | ||
|
||
events.forEach(event => { | ||
player.on(event, (e: { Player: CloudinaryVideoPlayer; type: string; }) => { | ||
const customEvent = new CustomEvent(`cldvideoplayer:${event}`, { | ||
detail: { | ||
Player: e.Player, | ||
type: e.type, | ||
Video: video | ||
}, | ||
}); | ||
video.closest(`#${video.dataset.cldvideoplayerId}`)?.dispatchEvent(customEvent); | ||
}); | ||
}); | ||
}) | ||
if ( !('cloudinary' in window) ) { | ||
if ( import.meta.env.MODE === 'development' ) { | ||
throw new Error('Unable to find cloudinary when loading the CldVideoPlayer.') | ||
} | ||
}); | ||
// Silently exit if it can' tbe found, we don't want to break people's page in production just | ||
// because the player wouldn't load | ||
return; | ||
} | ||
|
||
const cloudinary = window.cloudinary as Cloudinary; | ||
|
||
// Check to see if there are any duplicate player IDs | ||
// This should be rare but if there are duplicates it can create conflicts | ||
// in how the player loads with the given settings | ||
|
||
if ( import.meta.env.MODE === 'development' ) { | ||
const playerIds = Array.from(videos).map(video => video.dataset.cldvideoplayerId); | ||
if ( new Set(playerIds).size !== playerIds.length ) { | ||
console.warn('[CldVideoPlayer] Multiple instances of the same video detected on the page which may cause unexpected results. Try adding a unique id to each player.'); | ||
} | ||
} | ||
|
||
videos.forEach(video => { | ||
const playerOptions = video.dataset.cldvideoplayerOptions && JSON.parse(video.dataset.cldvideoplayerOptions); | ||
const player = cloudinary.videoPlayer(video, playerOptions); | ||
|
||
if ( !player ) return; | ||
|
||
// Loop through all avialable player events and create custom event callbacks | ||
|
||
const events = [ | ||
'loadstart', | ||
'suspend', | ||
'abort', | ||
'error', | ||
'emptied', | ||
'stalled', | ||
'loadedmetadata', | ||
'loadeddata', | ||
'canplay', | ||
'canplaythrough', | ||
'playing', | ||
'waiting', | ||
'seeking', | ||
'seeked', | ||
'ended', | ||
'durationchange', | ||
'timeupdate', | ||
'progress', | ||
'play', | ||
'pause', | ||
'ratechange', | ||
'volumechange', | ||
'fullscreenchange', | ||
'posterchange', | ||
'mute', | ||
'unmute', | ||
'percentsplayed', | ||
'timeplayed', | ||
'seek', | ||
'sourcechanged', | ||
'qualitychanged', | ||
]; | ||
|
||
events.forEach(event => { | ||
player.on(event, (e: { Player: CloudinaryVideoPlayer; type: string; }) => { | ||
const customEvent = new CustomEvent(`cldvideoplayer:${event}`, { | ||
detail: { | ||
Player: e.Player, | ||
type: e.type, | ||
Video: video | ||
}, | ||
}); | ||
video.closest(`#${video.dataset.cldvideoplayerId}`)?.dispatchEvent(customEvent); | ||
}); | ||
}); | ||
}) | ||
}); | ||
</script> |
Oops, something went wrong.