【问题标题】:How to prevent YouTube js calls from slowing down page load如何防止 YouTube js 调用减慢页面加载速度
【发布时间】:2018-10-28 20:47:11
【问题描述】:

我正在使用https://gtmetrix.com 来诊断我的页面速度问题。

page in question 有一个嵌入的 YouTube 视频,GTMetrix 表示该视频的 JS 调用正在减慢页面加载速度。

这是正在拨打的电话:

<iframe width="640" height="360" src="https://www.youtube.com/embed/PgcokT0AWHo" frameborder="0" allowfullscreen></iframe>

【问题讨论】:

  • 您是否尝试通过在window.onload 或jQuery 的ready 中动态设置src 来延迟iframe 加载?
  • @Kaddath 我没有使用 jQuery。但我很好奇如何使用window.onload。有没有这样的例子?这是标题中发生的事情吗?

标签: javascript youtube pageload page-load-time gtmetrix


【解决方案1】:

编辑:截至 2019 年 10 月,这不再有效(感谢 @CpnCrunch 的更新)。对于不影响用户体验的情况,您显然可以添加 1000 毫秒超时页面加载后生效。

这是一个使用纯 JS 解决方案在页面加载时动态添加 src 的示例。使用事件侦听器而不是 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>

请注意,脚本可以在代码中的任何位置,但如果不支持事件监听器(现在的浏览器不太可能),该函数会立即启动,因此至少应该在 @987654328 之后@元素。

【讨论】:

  • 这似乎并没有使原来的问题消失:(
  • 是的,将src 替换为您自己的网址。它应该可以工作,也许您的网站上有一个缓存系统需要清空?
  • 这只是一点点帮助。我的脚本仍然存在这些问题:youtube.com/yts/jsbin/player_ias-vfl3_buxB/en_US/base.js (817.3KiB) youtube.com/yts/jsbin/www-embed-player-vflHvHVeu/… (84.6KiB) youtube.com/embed/PgcokT0AWHo (3.3KiB of inline JavaScript)
  • 不幸的是,这不再适用(2019 年 10 月)以提高谷歌页面速度。如果您检查 pagespeed 洞察力,您会发现它没有任何区别。为了让它产生效果,我发现你需要在设置 src 属性之前在窗口加载后延迟 1000 毫秒,但这显然会造成糟糕的用户体验。
【解决方案2】:

我在做一个网站时遇到了同样的问题,我偶然发现了这个链接How to "Lazy Load" embedded youtube videos

它的本质是,在页面加载时,它会在网页上显示一个假的 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>

【讨论】:

  • 似乎需要点击两次,这并不理想。此外,狙击手似乎不再工作了。
  • @CpnCrunch 嵌入式播放器由于其运行的沙盒环境而引发错误。未捕获的 DOMException:无法从“文档”读取“cookie”属性:文档已被沙盒化,并且缺少“允许同源标志。
【解决方案3】:

只需要添加一行代码并延迟加载!

例如前面可能是这样的:

  <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 可能会受到伤害。

【讨论】:

    【解决方案4】:

    我找不到任何可行的解决方案,所以我编写了一个 javascript 库来执行此操作:

    https://github.com/groupboard/ytdefer

    它最初会显示一张图片,当用户点击它时,它会使用 YouTube Iframe API 加载视频,然后开始播放(这样就不需要点击两次)。

    【讨论】:

    • 绝对喜欢这种热情和想法!但是...实现对我来说太大了。闻起来需要太多的代码维护来保持这个工作随着时间的推移......而且,实现诸如使其响应的东西可能会更难......尽管它可能有助于我并行寻求使其离线或在普瓦。无论如何,感谢所有的灵感! ?
    【解决方案5】:

    一种可能的方法是不直接使用iframe,而是将它添加到一些事件监听器上,比如点击。

    看看我在我的网站上使用了很长时间的这个解决方案(无耻推广 - Demo

    这里我展示了一个带有播放按钮的预览图像。当用户单击图像时,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 上查看演示。

    可能的改进:

    1. 支持同一页面上的多个视频。它目前只允许一个视频。使用基于类的选择器可以轻松完成。

    【讨论】:

      【解决方案6】:

      查看使用带有 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 的结果。

      现在检查动态源代码。

      <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 结果。

      希望这些示例能帮助您评估您的问题。

      【讨论】:

      • 不幸的是,这不再适用(2019 年 10 月)以提高谷歌页面速度。如果您检查 pagespeed 洞察力,您会发现它没有任何区别。为了让它产生效果,我发现你需要在设置 src 属性之前在窗口加载后延迟 1000 毫秒,但这显然会造成糟糕的用户体验。
      【解决方案7】:

      根据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();
      }
      

      然后是带有惰性 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>
      

      【讨论】:

        【解决方案8】:

        你可以替换:

        <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" />';
        

        【讨论】:

        • googlecode 链接不再起作用,而且该解决方案似乎需要用户点击两次,这并不理想。
        【解决方案9】:
        <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> 
        

        【讨论】:

        • 不幸的是,这不再适用(2019 年 10 月)以提高谷歌页面速度。如果您检查 pagespeed 洞察力,您会发现它没有任何区别。为了让它产生效果,我发现你需要在设置 src 属性之前在窗口加载后延迟 1000 毫秒,但这显然会造成糟糕的用户体验。
        【解决方案10】:

        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);
        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-05-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-01-13
          • 2019-05-07
          相关资源
          最近更新 更多