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
Houssein Djirdeh
October 03, 2018
Technology
0
500
The Art of Lazy Loading
The magic of lazy loading images and splitting bundles ✨
Houssein Djirdeh
October 03, 2018
Tweet
Share
More Decks by Houssein Djirdeh
See All by Houssein Djirdeh
Performance Empathy
housseindjirdeh
0
190
GitPoint - Lunch and Learn
housseindjirdeh
0
110
Progressive Web Apps - fullStackTO/FITC Web Unleashed
housseindjirdeh
0
210
Once you go PRPL - FullStackFest
housseindjirdeh
0
30
Once you go PRPL: SeattleJS
housseindjirdeh
0
180
Other Decks in Technology
See All in Technology
REST API Design Pitfalls
victorrentea
1
500
XP matsuri 2024 - 銀河英雄伝説に学ぶ
kawaguti
PRO
3
450
Oracle GoldenGate 23ai 導入Tips
oracle4engineer
PRO
1
200
エンジニアは伝え方が9割/90% of what engineers need is communication skills
ykanoh
2
140
位置情報とオープンソースがやりたくてMIERUNEに転職した話 〜経歴、事例紹介、GISへのいざない〜 / MIERUNE JCT - Tokyo 2024
mierune
PRO
0
390
MLOpsの「あるある」課題の解決と、そのためのライブラリgokart
mski_iksm
1
150
映像・音声伝送システム
jtes
0
190
VS CodeでF1〜12キーつかってますか? / Do you use the F1-12 keys in VS Code?
74th
1
250
Authenticator のエミュレーションによる パスキーのログインテスト/nikkei-tech-talk-25
nikkei_engineer_recruiting
0
140
Sansanにおける全社横断データ分析基盤の挑戦と未来 / Challenges and Future of Cross-Organizational Data Analytics Platform at Sansan
sansan_randd
2
300
Understanding and Optimising INP
akshayysharma
0
150
PREEMPT_RT over the years
ennael
PRO
0
280
Featured
See All Featured
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
90
16k
Designing for Performance
lara
604
68k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
Fashionably flexible responsive web design (full day workshop)
malarkey
402
65k
The Art of Programming - Codeland 2020
erikaheidi
49
13k
Art, The Web, and Tiny UX
lynnandtonic
294
20k
[RailsConf 2023] Rails as a piece of cake
palkan
49
4.7k
Pencils Down: Stop Designing & Start Developing
hursman
119
11k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
25
640
Dealing with People You Can't Stand - Big Design 2015
cassininazir
363
22k
Writing Fast Ruby
sferik
624
60k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
1
230
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