Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
The Art of Lazy Loading
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Houssein Djirdeh
October 03, 2018
Technology
570
0
Share
The Art of Lazy Loading
The magic of lazy loading images and splitting bundles ✨
Houssein Djirdeh
October 03, 2018
More Decks by Houssein Djirdeh
See All by Houssein Djirdeh
Performance Empathy
housseindjirdeh
0
210
GitPoint - Lunch and Learn
housseindjirdeh
0
120
Progressive Web Apps - fullStackTO/FITC Web Unleashed
housseindjirdeh
0
220
Once you go PRPL - FullStackFest
housseindjirdeh
0
42
Once you go PRPL: SeattleJS
housseindjirdeh
0
190
Other Decks in Technology
See All in Technology
JSTQB Expert Levelシラバス「テストマネジメント」日本語版のご紹介
ymty
0
120
15年メンテしてきたdotfilesから開発トレンドを振り返る 2011 - 2026
giginet
PRO
2
270
Oracle Cloud Infrastructure(OCI):Onboarding Session(はじめてのOCI/Oracle Supportご利⽤ガイド)
oracle4engineer
PRO
2
17k
LLMに何を任せ、何を任せないか
cap120
11
6.9k
OpenClawでPM業務を自動化
knishioka
2
370
ThetaOS - A Mythical Machine comes Alive
aslander
0
240
トイルを超えたCREは何屋になるのか
bengo4com
0
120
OCI技術資料 : 証明書サービス概要
ocise
1
7.2k
Oracle AI Database@AWS:サービス概要のご紹介
oracle4engineer
PRO
3
2.1k
TUNA Camp 2026 京都Stage ヒューリスティックアルゴリズム入門
terryu16
0
670
Babylon.js を使って試した色々な内容 / Various things I tried using Babylon.js / Babylon.js 勉強会 vol.5
you
PRO
0
210
Embeddings : Symfony AI en pratique
lyrixx
0
450
Featured
See All Featured
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
660
Chasing Engaging Ingredients in Design
codingconduct
0
160
技術選定の審美眼(2025年版) / Understanding the Spiral of Technologies 2025 edition
twada
PRO
118
110k
Building Applications with DynamoDB
mza
96
7k
How to build a perfect <img>
jonoalderson
1
5.3k
We Have a Design System, Now What?
morganepeng
55
8.1k
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
490
AI Search: Where Are We & What Can We Do About It?
aleyda
0
7.2k
Have SEOs Ruined the Internet? - User Awareness of SEO in 2025
akashhashmi
0
310
Making Projects Easy
brettharned
120
6.6k
Building the Perfect Custom Keyboard
takai
2
720
Typedesign – Prime Four
hannesfritz
42
3k
Transcript
the art of lazy loading lazy loading @hdjirdeh
lazy defer until the user needs it
loading fetch + render
what?
images!
None
highest high medium low low high highest medium low
highest high medium low low high highest medium low
low highest high medium low low high highest medium
highest high medium low low high highest medium medium low
> 40% of data fetched = images
scroll event listeners
<img class="lazy" data-src="kittens.png"> class="lazy" data-src="kittens.png"
let image = document.querySelector("img.lazy"); const lazyLoad = () "=> {
setTimeout(() "=> { if ( image.getBoundingClientRect().top "<= window.innerHeight "&& image.getBoundingClientRect().bottom ">= 0 ) { image.src = image.dataset.src; } }, 200); }; document.addEventListener("scroll", lazyLoad); let image = document.querySelector("img.lazy"); const lazyLoad = () "=> { setTimeout(() "=> { if ( image.getBoundingClientRect().top "<= window.innerHeight "&& image.getBoundingClientRect().bottom ">= 0 ) { image.src = image.dataset.src; } }, 200); } document.addEventListener("scroll", lazyLoad); };
intersection observer
let image = document.querySelector("img.lazy"); let lazyObserver = new IntersectionObserver(entry "=>
{ if (entry.isIntersecting) { const image = entry.target; image.src = lazyImage.dataset.src; lazyObserver.unobserve(image); } }); lazyObserver.observe(image); let image = document.querySelector("img.lazy"); let lazyObserver = new IntersectionObserver(entry "=> { if (entry.isIntersecting) { const image = entry.target; image.src = lazyImage.dataset.src; lazyObserver.unobserve(image); } }); lazyObserver.observe(image);
bit.ly/inter-obs
native browser feature?
<img lazyload=“on”> lazyload=“on”
None
what else?
code!
None
1 KB of Image 1 KB of JavaScript ≠
split, split, split ✂
import('lodash.sortby') .then(module "=> module.default) .then(doSomethingCool) import('lodash.sortby') .then(module "=> module.default) .then(doSomethingCool)
dynamic import
what should I do?
audit
None
None
None
audit fix ✂
None
Use a library lozad.js lazysizes yall.js
Use IO + polyfill Use a library Use placeholders/ load
early
Use placeholders/ load early pinterest pinterest.com
Use placeholders/ load early lqip-loader github.com/zouhir/lqip-loader
Use placeholders/ load early Primitive primitive.lol
Use placeholders/ load early sqip github.com/technopagan/sqip SQIP LQIP Image
None
export const routes: Routes = [ { path: 'main', component:
'MainComponent', }, { path: 'details', loadChildren: 'details/details.module#DetailsModule' } ]; angular router
const DetailsComponent = () "=> import(‘./details.vue'); export const router =
new VueRouter({ routes: [ { path: '/details', component: DetailsComponent }, ] }) const DetailsComponent = () "=> import(‘./details.vue'); export const router = new VueRouter({ routes: [ { path: '/details', component: DetailsComponent }, ] }) const DetailsComponent = () "=> import(‘./details.vue'); export const router = new VueRouter({ routes: [ { path: '/details', component: DetailsComponent }, ] }) export const router = new VueRouter({ routes: [ { path: '/details', component: DetailsComponent }, ] }) vue router
import { Router } from 'preact-router'; import Home from '"../routes/home';
import Details from 'async!./details'; export const App = () "=> ( <Router> <Home path="/" "/> <Details path="/details/" "/> "</Router> ); import { Router } from 'preact-router'; import Home from '"../routes/home'; import Details from 'async!./details'; export const App = () "=> ( <Router> <Home path="/" "/> <Details path="/details/" "/> "</Router> ); preact cli import { Router } from 'preact-router'; import Home from '"../routes/home'; import Details from 'async!./details'; export const App = () "=> ( <Router> <Home path="/" "/> <Details path="/details/" "/> "</Router> );
const loadPage = (page) "=> (dispatch) "=> { switch(page) {
case 'view1': import('"../my-view1.js').then((module) "=> { "// ""... }); break; "//""... } dispatch(updatePage(page)); }; const loadPage = (page) "=> (dispatch) "=> { switch(page) { case 'view1': import('"../my-view1.js').then((module) "=> { "// ""... }); break; "//""... } dispatch(updatePage(page)); }; const loadPage = (page) "=> (dispatch) "=> { switch(page) { case 'view1': import('"../my-view1.js').then((module) "=> { "// ""... }); break; "//""... } dispatch(updatePage(page)); }; polymer pwa-starter-kit
import Loadable from 'react-loadable'; const DetailsComponent = Loadable({ loader: ()
"=> import('./details.component'), loading: () "=> <div>Loading""..."</div>, }); import Loadable from 'react-loadable'; const DetailsComponent = Loadable({ loader: () "=> import('./details.component'), loading: () "=> <div>Loading""..."</div>, }); import Loadable from 'react-loadable'; const DetailsComponent = Loadable({ loader: () "=> import('./details.component'), loading: () "=> <div>Loading""..."</div>, }); jamiebuilds / react-loadable
import loadable from 'loadable-components'; const DetailsComponent = loadable(() "=> import('./details.component'),
{ LoadingComponent: () "=> <div>Loading""..."</div> }); import loadable from 'loadable-components'; const DetailsComponent = loadable(() "=> import('./details.component'), { LoadingComponent: () "=> <div>Loading""..."</div> }); import loadable from 'loadable-components'; const DetailsComponent = loadable(() "=> import('./details.component'), { LoadingComponent: () "=> <div>Loading""..."</div> }); smooth-code / loadable-components
import LoadableVisibility from ‘react-loadable-visibility/react-loadable' const DetailsComponent = LoadableVisibility({ loader: ()
"=> import('./details.component'), loading: () "=> <div>Loading""..."</div>, }) import LoadableVisibility from ‘react-loadable-visibility/react-loadable' const DetailsComponent = LoadableVisibility({ loader: () "=> import('./details.component'), loading: () "=> <div>Loading""..."</div>, }) import LoadableVisibility from ‘react-loadable-visibility/react-loadable' const DetailsComponent = LoadableVisibility({ loader: () "=> import('./details.component'), loading: () "=> <div>Loading""..."</div>, }) stratiformltd / react-loadable-visibility
None
const DetailsComponent = Loadable({ loader: () "=> import('./details.component'), loading: ()
"=> <div>Loading""..."</div>, delay: 300, }); jamiebuilds / react-loadable const DetailsComponent = Loadable({ loader: () "=> import('./details.component'), loading: () "=> <div>Loading""..."</div>, delay: 300, });
suspense
bit.ly/lazy-metro metro (react native)
None
audit fix ✂ observe
webpack-bundle-analyzer
size-plugin
progressivetooling.com
responsive images with srcset preload critical chunks convert gifs to
.mp4 pre-cache assets using a service worker compress assets remove unused packages module / nomodule
/ Dx Ux
@hdjirdeh