2017
Reading time: (~ mins)
Everyone knows webpage sizes have ballooned and continue to in recent times. Even articles reporting on it are part of the problem. Most sites serve everything and the kitchen sink to a user even if they never end up interacting with bloated javascript modules. I have a simple solution, don't give users junk unless they are actively seeking it! One step shy of walling off all content behind a series of confirmation buttons, we can make pretty good progress just by smartly loading-in features.
Using a metric of how many DOOM executables of space(2.39MB) we can save, I'll tackle 3 common use cases:
Feature | Effort | DOOMs saved |
---|---|---|
Disqus Comments | Copy/Paste | ~0.50(1.20MB) |
Youtube Player | Copy/Paste | ~0.68(1.62MB) |
Google Maps | A little leg work | ~0.96(2.30MB) |
<div id="disqus_thread"></div> <noscript> Please enable JavaScript to view the <a href="https://disqus.com/?ref_noscript">comments powered by Disqus.</a> </noscript>JAVSCRIPT:
( function() { //Modified from: //christianfei.com/posts/how-to-lazy-load-disqus-comments/ var comments = document.getElementById('disqus_thread'), disqusLoaded = false; function loadDisqus() { (function() { var d = document, s = d.createElement('script'); s.src = '//REPLACE_SHORTNAME.disqus.com/embed.js'; // REPLACE HERE s.setAttribute('data-timestamp', +new Date()); (d.head || d.body).appendChild(s); })(); disqusLoaded = true; } function findTop(obj) { var curtop = 0; if (obj.offsetParent) { do { curtop += obj.offsetTop; } while (obj = obj.offsetParent); return curtop; } } // Throttle scroll event: //codepen.io/SitePoint/pen/RRLVAL function throttle(fn, wait) { var time = Date.now(); return function() { if ((time + wait - Date.now()) < 0) { fn(); time = Date.now(); } } } if(comments) { var commentsOffset = findTop(comments); window.addEventListener('scroll', throttle(function() { if(!disqusLoaded && window.pageYOffset > commentsOffset - 1000) { // CUSTOMIZE: distance to check loadDisqus(); } }, 100)); // CUSTOMIZE: throttle frequency } } )();CUSTOMIZE:
JAVSCRIPT: REPLACE_SHORTNAME with the one given to your website, found in
Disqus>Admin>Settings>General-Shortname
Optional: distance to start loading, throttle frequency
Every time the user scrolls (throttled to 100ms periods), check if we are within 1000px to the top of the Disqus DIV. If we are, run the code that Disqus provides to bring in their comment module.
EXAMPLE:Used on this page, check the bottom!
<div class="youtube" data-embed="REPLACE_VIDEO_ID"> <!-- REPLACE HERE --> <div class="play-button"></div> </div>CSS:
.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:.7}.youtube .play-button{width:90px;height:60px;background-color:red;box-shadow:0 0 30px rgba(0,0,0,0.6);z-index:1;opacity:.8;border-radius:6px}.youtube .play-button:before{content:"";border-style:solid;border-width:15px 0 15px 26px;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}JAVASCRIPT:
( function() { var youtube = document.getElementsByClassName( "youtube" ); for (var i = 0; i < youtube.length; i++) { var source = "https://img.youtube.com/vi/"+ youtube[i].dataset.embed +"/hqdefault.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 ); } ); }; } )();CUSTOMIZE:
HTML: REPLACE_VIDEO_ID with the id of the video you want.
Ex: https://www.youtube.com/watch?v=jNQXAC9IVRw id would be the v query param value of 'jNQXAC9IVRw'
Optional:
CSS styling can be adjusted as needed.
Automatically grabs a still image from the video using the youtube api. Mock out the video player with the image and a fake button. If a user clicks, load in the actual embedded video and autoplay.
EXAMPLE:
<img src="REPLACE_IMG_SRC" <!-- REPLACE HERE --> alt="Static map image" title="Click here to activate map" class="g-map-static" style="max-width: 600px; max-height: 480px; opacity: 1;" i-frame-src="https://www.google.com/maps/d/u/0/embed?mid=REPLACE_GMAP_ID"/> <!-- REPLACE HERE -->CSS:
iframe.g-map-static{width: 600px;height:480px;}JAVSCRIPT:
( function() { var gmaps = document.getElementsByClassName('g-map-static'); for (var i = 0; i < gmaps.length; i++) { gmaps[i].addEventListener( "click", iframeSetup, false); }; function iframeSetup(e) { e.preventDefault(); this.removeEventListener('click', iframeSetup, false); var ifrm = document.createElement("iframe"); ifrm.setAttribute('class', 'g-map-static'); ifrm.style.background = 'url('+this.src+')'; ifrm.style.setProperty('background-size', 'contain'); ifrm.style.setProperty('background-repeat', 'no-repeat'); this.insertAdjacentElement('afterend', ifrm); this.remove(); ifrm.setAttribute('src', this.getAttribute('i-frame-src')); return false; } } )();CUSTOMIZE:
HTML:
- Manually take a screenshot of the loaded GMaps module. Save the file somewhere the webpage can access (on your server, image hosting site, etc.).
- REPLACE_IMG_SRC will reference the aforementioned image file.
- REPLACE_GMAP_ID with google map id, which can be found by opening up the embedded map and looking at the mid query param.
Ex. 'https://www.google.com/maps/d/u/0/viewer?mid=1jNUEdgWxPGBvh72IurIhcND3SZ0' id is "1jNUEdgWxPGBvh72IurIhcND3SZ0".
Show a placeholder image of what google maps would render. If a user clicks, call for the iframe and replace the image.
EXAMPLE:
Pretty easy right? I'm sure every vistor to your site will thank you for taking a stand and not throwing every bit of js at them that you can muster.
P.S. The irony that Google's run_prettify.js is larger than all the written content on this page is not lost on me. At least that is only a loss of 0.007 DOOMs.