javascript 如何防止 YouTube js 调用减慢页面加载速度
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/50410828/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to prevent YouTube js calls from slowing down page load
提问by Genadinik
I am using https://gtmetrix.comto diagnose issues with my page speed.
我正在使用https://gtmetrix.com来诊断我的页面速度问题。
The page in questionhas one embedded YouTube video and GTMetrix is saying that this video's JS calls are slowing down page load speed.
有问题的页面有一个嵌入的 YouTube 视频,GTMetrix 表示该视频的 JS 调用减慢了页面加载速度。
This is the call being made:
这是正在拨打的电话:
<iframe width="640" height="360" src="https://www.youtube.com/embed/PgcokT0AWHo" frameborder="0" allowfullscreen></iframe>
回答by Kaddath
EDIT: as of October 2019, this is not working anymore (Thanks to @CpnCrunch for the update).For the cases where it's not impacting the user experience, you can apparently add a 1000ms timeout after the page load for it to take effect.
编辑:截至 2019 年 10 月,这不再有效(感谢 @CpnCrunch 的更新)。对于不影响用户体验的情况,您显然可以在页面加载后添加 1000 毫秒超时以使其生效。
This is an example of attibuting the srcdynamically on page load, using a pure JS solution. Using event listeners instead of window.onloadbecause with the latter, only one event can be set and it would override any precedent window.onloadevent:
这是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>
Note that the script can be anywhere in the code, but in case of no support for event listeners (which is highly unlikely with nowadays browsers), the function is launched right away, so it should be at least after the iframeelement.
请注意,脚本可以位于代码中的任何位置,但如果不支持事件侦听器(现在的浏览器不太可能),则该函数会立即启动,因此它至少应该在iframe元素之后。
回答by Ajmal Hassan
I was having the same problem for a website I was doing and I stumbled upon this link How to "Lazy Load" embedded youtube videos
我在做的一个网站上遇到了同样的问题,我偶然发现了这个链接如何“延迟加载”嵌入的 youtube 视频
What it essentially does is, upon page load, it'll show a fake youtube player section (made out of css and your video image thumbnail) on the webpage and when the user clicks on it, it'll replace that fake player section with the Iframe and that's when the player will be loaded.
它本质上的作用是,在页面加载时,它会在网页上显示一个假的 youtube 播放器部分(由 css 和您的视频图像缩略图组成),当用户点击它时,它将替换那个假的播放器部分Iframe,然后播放器将被加载。
Code from the website
来自网站的代码
(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>
回答by Manish Nayak
Look at given examples of using an iframe with src attribute and with dynamic src attribute with GTMatrix results.
查看使用带有 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>
Here is the result of GTMatrix for above code.
这是上述代码的 GTMatrix 结果。
Now check dynamic src code.
现在检查动态源代码。
<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>
Now, look at the GTMatrix result after applying dynamic src to the iframe.
现在,查看将动态 src 应用于 iframe 后的 GTMatrix 结果。
Hope these examples will help you to evaluate your problem.
希望这些例子能帮助你评估你的问题。
回答by Sid Vishnoi
One possible approach is to not use the iframedirectly but add it on some event listener, like click.
一种可能的方法是不iframe直接使用而是将其添加到某些事件侦听器上,例如单击。
Have a look at this solution which I've been using on my website since long time (shameless promotion - Demo)
看看这个解决方案,我长期以来一直在我的网站上使用(无耻的促销 -演示)
Here I show a preview image with a play button. When user clicks the image, the YouTube iframe is dynamically added to page, saving tons on bytes on page load. The code below is almost production ready and can be used as per your requirements.
在这里,我展示了一个带有播放按钮的预览图像。当用户单击图像时,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>
Note:The demo above may not work due to cross-origin cookie issues. Please see the demo on codepen.
注意:由于跨域 cookie 问题,上面的演示可能无法运行。请参阅codepen上的演示。
Possible improvements:
可能的改进:
- Support multiple videos on same page. It currently allows only one video. It can be done easily with class based selectors.
- 支持同一页面上的多个视频。它目前只允许一个视频。使用基于类的选择器可以轻松完成。
回答by Vasile Florin Vilsan
You could replace:
你可以替换:
<iframe src="https://www.youtube.com/embed/LcIytqkbdlo" height="180" width="320"></iframe>
with
和
<div class="youtube" id="LcIytqkbdlo" style="width: 320px; height: 180px;"></div> <script src="https://labnol.googlecode.com/files/youtube.js"></script>
as exemplified here: https://www.mainstreethost.com/blog/light-youtube-embeds-faster-page-load/
如此处所示:https: //www.mainstreethost.com/blog/light-youtube-embeds-faster-page-load/
You could find another useful article which addresses your problem over here: https://mikeindustries.com/blog/archive/2007/06/widget-deployment-with-wedje
您可以在此处找到另一篇有用的文章来解决您的问题:https: //mikeindustries.com/blog/archive/2007/06/widget-deployment-with-wedje
WEDJE creates a cross-platform, cross-browser defer by using the document object model (DOM) to append a div, create a script element, and then append the script element to the div, all with JavaScript. An example of the technique follows:
WEDJE 通过使用文档对象模型 (DOM) 附加一个 div,创建一个脚本元素,然后将脚本元素附加到 div 中,创建一个跨平台、跨浏览器的 defer,全部使用 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>
When these elements are linked together in this way, browsers appear to decouple the loading and execution of the attached JavaScript, making widget execution asynchronous! Here is the matching external JavaScript file, widget.js, which grabs the div we created earlier and loads an image:
当这些元素以这种方式链接在一起时,浏览器似乎将附加 JavaScript 的加载和执行分离,从而使小部件执行异步!这是匹配的外部 JavaScript 文件 widget.js,它抓取我们之前创建的 div 并加载图像:
document.getElementById('wedje_div_example').innerHTML+='<img src="https://www.example.com/images/example.gif" width="60" height="60" />';
回答by Nanhe Kumar
<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>
回答by CpnCrunch
I couldn't find any workable solutions, so I wrote a javascript library to do this:
我找不到任何可行的解决方案,所以我写了一个 javascript 库来做到这一点:
https://github.com/groupboard/ytdefer
https://github.com/groupboard/ytdefer
It initially displays an image, and when the user clicks on it it then uses the YouTube Iframe API to load the video, and then start playing it (so that two clicks aren't required).
它最初显示一个图像,当用户点击它时,它然后使用 YouTube Iframe API 加载视频,然后开始播放它(因此不需要两次点击)。
回答by felipep
Based on the response of https://stackoverflow.com/a/50411411/2046846and with the 2000ms timeout changes I solved the issue in this way.
基于https://stackoverflow.com/a/50411411/2046846的响应和 2000ms 超时更改,我以这种方式解决了这个问题。
// 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();
}
Then the regular html with the class lazy-youtube
然后是带有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>


