index.html
index.html
style.css
script.js
<link rel="preload" as="font" crossorigin="anonymous"
type="font/woff2" href="..." />
<link rel="preload" as="image"
type="image/png" href="..." />
<link rel="prefetch" href="next.html" />
<link rel="dns-prefetch" href="//example.com" />
<link rel="preconnect" href="https://example.com" />
<link rel="prerender" href="https://example.com" />
Cache-Control: public, max-age=31536000
// for immutable content
Cache-Control: no-cache
// for mutable content
self.addEventListener('fetch', event => {
event.respondWith(
caches.match(event.request)
.then(response => response || fetch(event.request))
);
});
index.html
styles.css
nasty_ads.js
index.html
styles.css
nasty_ads.js
?
index.html
styles.css
nasty_ads.js
index.html
styles.css
nasty_ads.js
?
index.html
styles.css
nasty_ads.js
!
index.html
styles.css
nasty_ads.js
?
index.html
styles.css
nasty_ads.js
!
index.html
styles.css
nasty_ads.js
<script src="nasty_ads.js" async></script>
index.html
styles.css
nasty_ads.js
index.html
styles.css
nasty_ads.js
<script src="nasty_ads.js" defer></script>
load
parse
compile
execute
<img src="small.jpg" srcset="medium.jpg 1000w, large.jpg 2000w">
style
layout
paint
composite
HTML/JS
.moving-element {
will-change: transform;
}
style
layout
paint
composite
JavaScript
document.addEventListener(
'touchstart', handler, {passive: true});
function animationStep() {
// animate
requestAnimationFrame(animationStep);
}
requestAnimationFrame(animationStep);
function heavyComputation() { /* ... */ }
requestIdleCallback(heavyComputation);