我正在使用https://gtmetrix.com来诊断我的页面速度问题。
有问题的页面有一个嵌入的 YouTube 视频,GTMetrix 说该视频的 JS 调用正在减慢页面加载速度。
这是正在拨打的电话:
<iframe width="640" height="360" src="https://www.youtube.com/embed/PgcokT0AWHo" frameborder="0" allowfullscreen></iframe>
我正在使用https://gtmetrix.com来诊断我的页面速度问题。
有问题的页面有一个嵌入的 YouTube 视频,GTMetrix 说该视频的 JS 调用正在减慢页面加载速度。
这是正在拨打的电话:
<iframe width="640" height="360" src="https://www.youtube.com/embed/PgcokT0AWHo" frameborder="0" allowfullscreen></iframe>
编辑:截至 2019 年 10 月,这不再有效(感谢@CpnCrunch 的更新)。对于不影响用户体验的情况,您显然可以在页面加载后添加 1000 毫秒超时以使其生效。
这是一个src
使用纯 JS 解决方案动态加载页面的示例。使用事件侦听器而不是window.onload
后者,因为只能设置一个事件,并且它将覆盖任何先前的window.onload
事件:
<iframe id="videoFrame" width="640" height="360" src="" frameborder="0" allowfullscreen></iframe>
<script>
function setVideoFrame(){
document.getElementById('videoFrame').src = 'http://example.com/';
}
if (window.addEventListener) // W3C DOM
window.addEventListener('load', setVideoFrame, false);
else if (window.attachEvent) { // IE DOM
window.attachEvent('onload', setVideoFrame);
}else{ //NO SUPPORT, lauching right now
setVideoFrame();
}
</script>
请注意,脚本可以在代码中的任何位置,但如果不支持事件监听器(这在当今的浏览器中极不可能),该函数会立即启动,因此它至少应该在iframe
元素之后。
我在做一个网站时遇到了同样的问题,我偶然发现了这个链接如何“延迟加载”嵌入的 youtube 视频
它本质上的作用是,在页面加载时,它会在网页上显示一个假的 youtube 播放器部分(由 css 和您的视频图像缩略图组成),当用户点击它时,它将替换那个假播放器部分Iframe 就是加载播放器的时候。
来自网站的代码
(function() {
// get's all video wrapper divs
var youtube = document.querySelectorAll(".youtube");
// iterates through all the divs
for (var i = 0; i < youtube.length; i++) {
/*
gets the video id we mentioned in the data-embed attribute
to generate image thumbnail urls, youtube has several
resolutions.
- mqdefault 320 x 180
- hqdefault 480 x 360
- sddefault - 640 x 480
- maxresdefault - 1920 x 1080
*/
var source = "https://img.youtube.com/vi/" + youtube[i].dataset.embed + "/sddefault.jpg";
/*
creates new image and sets the source attribute to the thumbnail
url we generated above and sets it to load the image on page load
*/
var image = new Image();
image.src = source;
image.addEventListener("load", function() {
youtube[i].appendChild(image);
}(i));
/*
below is where the magic happens, we attach click listeners to the
video embed divs and when clicked we create a new iframe and sets
it inside the video wrapper div and only then will the js files
associated with the embedded video be loaded
*/
youtube[i].addEventListener("click", function() {
var iframe = document.createElement("iframe");
iframe.setAttribute("frameborder", "0");
iframe.setAttribute("allowfullscreen", "");
iframe.setAttribute("src", "https://www.youtube.com/embed/" + this.dataset.embed + "?rel=0&showinfo=0&autoplay=1");
this.innerHTML = "";
this.appendChild(iframe);
});
};
})();
html {
background-color: #f3f3f3;
}
.wrapper {
max-width: 680px;
margin: 60px auto;
padding: 0 20px;
}
.youtube {
background-color: #000;
margin-bottom: 30px;
position: relative;
padding-top: 56.25%;
overflow: hidden;
cursor: pointer;
}
.youtube img {
width: 100%;
top: -16.82%;
left: 0;
opacity: 0.7;
}
.youtube .play-button {
width: 90px;
height: 60px;
background-color: #333;
box-shadow: 0 0 30px rgba( 0, 0, 0, 0.6);
z-index: 1;
opacity: 0.8;
border-radius: 6px;
}
.youtube .play-button:before {
content: "";
border-style: solid;
border-width: 15px 0 15px 26.0px;
border-color: transparent transparent transparent #fff;
}
.youtube img,
.youtube .play-button {
cursor: pointer;
}
.youtube img,
.youtube iframe,
.youtube .play-button,
.youtube .play-button:before {
position: absolute;
}
.youtube .play-button,
.youtube .play-button:before {
top: 50%;
left: 50%;
transform: translate3d( -50%, -50%, 0);
}
.youtube iframe {
height: 100%;
width: 100%;
top: 0;
left: 0;
}
<!-- (1) video wrapper, data-embed contains ID of the Youtube video-->
<div class="youtube" data-embed="AqcjdkPMPJA">
<!-- (2) the "play" button -->
<div class="play-button"></div>
</div>
只需要添加一行代码和它的延迟加载!
例如前面可能是这样的:
<iframe
width="400"
height="200"
src="https://www.youtube.com/embed/sh0EGUheef8"
frameborder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
></iframe>;
只需要改变
src 与 srcdoc
srcdoc="<style>*{padding:0;margin:0;overflow:hidden}html,body{height:100%}img,span{position:absolute;width:100%;top:0;bottom:0;margin:auto}span{height:1.5em;text-align:center;font:48px/1.5 sans-serif;color:white;text-shadow:0 0 0.5em black}</style><a href=https://www.youtube.com/embed/sh0EGUheef8/?autoplay=1><img src=https://img.youtube.com/vi/sh0EGUheef8/hqdefault.jpg alt='AltTagContent'><span>▶</span></a>"
这个技巧植根于srcdoc,这是一个可以将 HTML 文档的全部内容放在属性中的功能。这就像内联样式,但内联整个文档之类的东西。
唯一的问题是框架。用户将不得不再次单击它。由于第一次点击只是加载视频。它仍然可以保存否则会被下载的垃圾,特别是对于移动设备,那些 500KB 可能会受到伤害。
我找不到任何可行的解决方案,所以我编写了一个 javascript 库来执行此操作:
https://github.com/groupboard/ytdefer
它最初显示一个图像,当用户单击它时,它会使用 YouTube Iframe API 加载视频,然后开始播放(这样就不需要单击两次)。
根据https://stackoverflow.com/a/50411411/2046846的响应和 2000 毫秒的超时更改,我以这种方式解决了这个问题。
// Lazy Youtube.js
function setVideoFrames() {
window.setTimeout(function () {
let youtube_iframes = document.querySelectorAll('.lazy-youtube');
if (youtube_iframes !== null) {
for (let i = 0; i < youtube_iframes.length; i++) {
youtube_iframes[i].src = youtube_iframes[i].getAttribute('data-src');
}
}
}, 2000);
}
if (window.addEventListener) // W3C DOM
window.addEventListener('load', setVideoFrames, false);
else if (window.attachEvent) { // IE DOM
window.attachEvent('onload', setVideoFrames);
} else { //NO SUPPORT, lauching right now
setVideoFrames();
}
然后是带有类lazy-youtube的常规html
<iframe width="1140" height="733"
class="lazy-youtube"
data-src="https://www.youtube.com/embed/{{ video-id }}?rel=0"
frameborder="0"
allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen title="Youtube Video"></iframe>
查看使用带有 src 属性的 iframe 和带有 GTMatrix 结果的动态 src 属性的给定示例。
<html>
<head>
<title>-</title>
</head>
<body>
<iframe id="myvideo" width="640" height="360" src="https://www.youtube.com/embed/PgcokT0AWHo" frameborder="0" allowfullscreen></iframe>
</body>
</html>
这是上面代码的 GTMatrix 的结果。
现在检查动态 src 代码。
<html>
<head>
<title>-</title>
<script type="text/javascript">
function test()
{
document.getElementById('myvideo').src = 'https://www.youtube.com/embed/PgcokT0AWHo';
}
</script>
</head>
<body onload="test();">
<iframe id="myvideo" width="640" height="360" frameborder="0" allowfullscreen></iframe>
</body>
</html>
现在,查看将动态 src 应用于 iframe 后的 GTMatrix 结果。
希望这些例子能帮助你评估你的问题。
一种可能的方法是不iframe
直接使用,而是将其添加到某些事件侦听器上,例如单击。
看看我长期以来一直在我的网站上使用的这个解决方案(无耻推广 -演示)
在这里,我展示了一个带有播放按钮的预览图像。当用户单击图像时,YouTube iframe 会动态添加到页面,从而在页面加载时节省大量字节。下面的代码几乎可以用于生产,可以根据您的要求使用。
if (document.querySelector("#videoPlayer")) {
document.querySelector("#videoPlayer a").addEventListener("click", playVideo);
}
function playVideo() {
var player = document.getElementById("videoPlayer");
var id = player.getAttribute("data-id");
player.classList.add("loaded");
var src =
"https://www.youtube.com/embed/" +
id +
"?autoplay=1&autohide=1&rel=0&modestbranding=1&showinfo=0&border=0&wmode=opaque&theme=light&iv_load_policy=3";
var iframe =
"<iframe width='100%' height='100%' src='" +
src +
"' scrolling='no frameborder='0' allowfullscreen></iframe>";
player.innerHTML = iframe;
return false;
}
#videoPlayer {
background-color: #000;
max-width: 100%;
overflow: hidden;
position: relative;
cursor: pointer;
height: 380px;
width: 100%;
margin: 1em auto;
}
#videoPlayer:after {
content: attr(data-title);
position: absolute;
bottom: 0;
left: 0;
display: block;
background: rgba(0, 0, 0, 0.5);
width: 100%;
max-height: 100px;
text-align: left;
padding: 1em;
font-size: 1.2em;
color: #fff;
transition: opacity 0.7s ease-in-out;
}
#videoPlayer:hover:after {
opacity: 0;
}
#videoPlayer .thumb {
bottom: 0;
display: block;
left: 0;
margin: auto;
max-width: 100%;
position: absolute;
right: 0;
top: 0;
width: 100%;
height: auto;
opacity: 0.8;
filter: alpha(opacity=80);
transition: all 200ms ease-out;
-webkit-transition: all 200ms ease-out;
}
#videoPlayer .thumb:hover {
-webkit-transform: scale(1.2);
transform: scale(1.2);
}
#videoPlayer .play {
filter: alpha(opacity=90);
opacity: 0.9;
height: 97px;
left: 50%;
margin-left: -38px;
margin-top: -38px;
position: absolute;
top: 50%;
width: 136px;
background: url("http://i.imgur.com/TxzC70f.png");
background-repeat: no-repeat;
}
#videoPlayer.loaded:after {
display: none;
}
<div id="videoPlayer" data-title="NBA 2K18 - Get Shook Trailer" data-id="lwBqitrE3ww"> <a title="Click to play video : NBA 2K18 - Get Shook Trailer"> <img class="thumb" alt="NBA 2K18 - Get Shook Trailer" src="https://1.bp.blogspot.com/-X4naiytBpyU/WZRt5d3P1iI/AAAAAAAADq8/y4IAHBmh39kqdwu8THECuObG3r9HIfa9wCLcBGAs/s800/nba-2k18-get-shook-trailer-hoopsvilla.jpg" /><span class="play"></span></a></div>
</div>
注意:由于跨域 cookie 问题,上面的演示可能无法运行。请参阅codepen上的演示。
可能的改进:
<iframe width="640" height="360" src="" data-src="https://www.youtube.com/embed/PgcokT0AWHo" frameborder="0" allowfullscreen></iframe>
<script>
function init() {
var vidDefer = document.getElementsByTagName('iframe');
for (var i=0; i<vidDefer.length; i++) {
if(vidDefer[i].getAttribute('data-src')) {
vidDefer[i].setAttribute('src',vidDefer[i].getAttribute('data-src'));
}
}
}
window.onload = init;
</script>
你可以替换:
<iframe src="https://www.youtube.com/embed/LcIytqkbdlo" height="180" width="320"></iframe>
和
<div class="youtube" id="LcIytqkbdlo" style="width: 320px; height: 180px;"></div> <script src="https://labnol.googlecode.com/files/youtube.js"></script>
如此处所示: https ://www.mainstreethost.com/blog/light-youtube-embeds-faster-page-load/
您可以在这里找到另一篇有用的文章来解决您的问题: https ://mikeindustries.com/blog/archive/2007/06/widget-deployment-with-wedje
WEDJE 通过使用文档对象模型 (DOM) 来附加一个 div,创建一个脚本元素,然后将脚本元素附加到 div,创建一个跨平台、跨浏览器的延迟,所有这些都使用 JavaScript。该技术的一个例子如下:
<script type="text/javascript"> // create div below
(function( ){document.write('<div id="wedje_div_example">Loading widget...<\/div>');
s=document.createElement('script'); // create script element
s.type="text/javascript"; // assign script to script element
s.src="http://www.example.com/scripts/widget.js";
// assign script s to div element
setTimeout("document.getElementById('wedje_div_example').appendChild(s)",1);})( )
</script>
当这些元素以这种方式链接在一起时,浏览器似乎将附加 JavaScript 的加载和执行解耦,使小部件执行异步!这是匹配的外部 JavaScript 文件 widget.js,它抓取我们之前创建的 div 并加载图像:
document.getElementById('wedje_div_example').innerHTML+='<img src="https://www.example.com/images/example.gif" width="60" height="60" />';
iframe 从 youtube 加载 4+ js 文件(超过1MB),您可以使用这种方法克服使用Jquery的加载时间。
HTML
<div class="youtube_video_iframe">
JavaScript
$window.on('load', function () {
var youtube_video_iframe = `<iframe width="500" height="350"
src="https://www.youtube.com/embed/1gxcvLGKIRM" frameborder="0" allow="accelerometer;
autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`;
$('.youtube_video_iframe').append(youtube_video_iframe);
});