| @ -0,0 +1,186 @@ | |||
| # Background | |||
| The concept of lazy loading is a design pattern where you only download the required scripts/content when the client needs it rather than when the page is loaded. | |||
| The most iconic example is the "infinite" feed that social media sites like Instagram use. | |||
| Rather than dump a ton of content to the client at once, Instagram dynamically loads more content once you reach the end of the page. | |||
| This allows websites to save bandwidth by only sending the client what they need when they need it. | |||
| When a youtube video is embedded into a website, it pulls a ton of scripts which are required to play the video. | |||
| However, when you embed a youtube video on a blog post, most people are not going to watch that video. | |||
| Even if the visitor wanted to watch that video, there is no reason why all the scripts should be loaded when you initially land on the page. | |||
| Rather than embed the video normally, you can instead simply have a the thumbnail of the video with a play button on it. | |||
| When the client clicks the play button, the youtube scripts are then loaded. | |||
| # Performance Without Lazy Loading | |||
|  | |||
|  | |||
| A very basic blog post with two Youtube videos is **1.5 MB** in size. | |||
| That is a rather large page for a client to download and render. | |||
| Notice that 65% of the content by size is from Youtube and 29 requests were from Google domains. | |||
| # Performance with Lazy Loading | |||
|  | |||
|  | |||
| After lazy loading Youtube videos I was able to reduce the size of this blog post by nearly 1 MB. | |||
| This also decreased the page load time by 75%. | |||
| Additional tests show's that each embedded youtube video consumes around 500 KB. | |||
| Using the lazy loading method you can slash that 500 KB to a mere 100 KB-- size of just the thumbnail. | |||
| # Code Used | |||
| ## Javascript | |||
| This is some basic JavaScript code which selects all of the "youtube" embedded videos on our page and adds a play button handler. | |||
| When the button is clicked, it updates the div to have an Iframe with the appropriate embedded youtube video. | |||
| If you are already using jQuery, you could use that but, I did not since the **goal** of this is to optimize the page load time. | |||
| The [jQuery library](https://mathiasbynens.be/demo/jquery-size) is nearly 50 KB. | |||
| ```javascript | |||
| <script> | |||
| ( function() { | |||
| var youtube = document.querySelectorAll( ".youtube" ); | |||
| for (var i = 0; i < youtube.length; i++) { | |||
| var source = "https://img.youtube.com/vi/"+ youtube[i].dataset.embed +"/sddefault.jpg"; | |||
| var image = new Image(); | |||
| image.src = source; | |||
| image.addEventListener( "load", function() { | |||
| youtube[ i ].appendChild( image ); | |||
| }( i ) ); | |||
| 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 ); | |||
| } ); | |||
| }; | |||
| } )(); | |||
| </script> | |||
| ``` | |||
| ## CSS | |||
| This CSS defines how the embedded youtube video looks before you click the play button. | |||
| ```CSS | |||
| .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; | |||
| } | |||
| ``` | |||
| ### Example | |||
| <youtube src="DoDaHmyIPvQ" /> | |||
| ## HTML | |||
| Rather than use the embed code that youtube provides, you have to use the following code to integrate with the CSS and JS written. | |||
| All you need from the youtube video is the ID which appears in the link associated with that video. | |||
| ```HTML | |||
| <div class="wrapper"> | |||
| <div class="youtube" data-embed="DoDaHmyIPvQ"> | |||
| <div class="play-button"></div> | |||
| </div> | |||
| </div> | |||
| ``` | |||
| ## Node Templating Stuff | |||
| When witting blog posts in Markdown, it is not convenient to include 5 lines of HTML to embed a video. | |||
| On my node server I wrote some code to convert a simpler "youtube tag" into the 5 lines of HTML shown above. | |||
| This is completely optional. | |||
| ```javascript | |||
| //regular expression to detect custom youtube video tag | |||
| //<youtube src="" /> | |||
| var re = /\<youtube .*?>/; | |||
| //result is a string which contains a HTML document | |||
| while (result.search(re) != -1) | |||
| { | |||
| var ytid = result.substring(result.search(re) + 14, result.search(re)+ 11 + 14); | |||
| var youtubeHTML = "<div class=\"wrapper\">\n" + | |||
| "\t<div class=\"youtube\" data-embed=\"" + | |||
| ytid + | |||
| "\" />\n" + | |||
| "\t\t<div class=\"play-button\"></div>\n" + | |||
| "\t</div>\n" + | |||
| "</div>\n"; | |||
| var original = "<youtube src=\"" + ytid + "\" />"; | |||
| result = result.split(original).join(youtubeHTML); | |||
| } | |||
| ``` | |||