Delay | User Reaction |
---|---|
0 - 100ms | Instant |
100 - 300ms | Small perceptible delay |
300 - 1000ms | Machine is working |
1s+ | Mental context switch |
10s+ | I'll come back later... |
Source :- @igrigorik
BROWSER
NETWORK
DOM
CSSOM
HTML
CSS
JS
RENDER TREE Â +
LAYOUT
+
PAINT
BROWSER
NETWORK
DNS Â LOOKUP
TCP
SSLÂ
REQUEST
 1. dns - prefetch
<link rel='dns-prefetch' href='http://example.com'>
 2. preconnect
<link rel='preconnect' href='http://example.com'>
Support :- http://caniuse.com/#feat=link-rel-preconnect
There are couples of things also like prerender, prefetch & preload
                             - @aerotwist
PRECONNECT
START Â STREAMING Â /HTML
START Â BUILDING Â DOM
GET /CSS
START Â BUILDING Â CSSOM
JAVASCRIPT
CSSOM COMPLETE
EXECUTE Â JAVASCRIPT
CONTINUE BUILDING DOM
RENDER PAGE
- @addyosmani
Progressively enhanced rest of it.
<head>
<script>
function loadCSS(src) {
'use strict';
const ref = document.getElementsByTagName('script')[0];
const link = document.createElement('link');
link.rel = 'stylesheet'; // this line is important
link.href = src;
ref.parentNode.insertBefore(link, ref);
}
</script>
<style>
.critical {
//styles
}
.non-critical {
display: none;
}
</style>
<script>
loadCSS('/non-critical.css);
</script>
</head>
<body>
</body>
How to load CSS progressively ?
- Script injected <link rel = 'stylesheet'>
//Based on https://jakearchibald.com/2016/link-in-body/
function isScriptInjectedStyleBlocking(browser) {
if(browser == Chrome || broswer == Safari) {
return true;
} else {
//Even if it's Chrome Canary, so it might land in Chrome too in future
return false;
}
}
We have a better way
'use strict';
const ref = document.getElementsByTagName('script')[0];
const link = document.createElement('link');
//below two lines are important
link.rel = 'stylesheet';
link.media = 'only whatever';
link.href = 'http://example.com/style.css';
ref.parentNode.insertBefore(link, ref);
setTimeout(_ => {
link.media = 'all';
},0);
- Script injected <link rel = 'stylesheet'> with media attr.
function isEnhancementPossible() {
if( timeMachine === 'Present' && browser !== 'IE/Edge') {
return false;
} else {
//Yes!!! Apparently IE/Edge provided the solution.
//And it worked for firefox as a hack.
return true;
}
}
What's  the  enhancement?
So much of text but where's code..?
 How a page would look like in reality?
<!-- Taken from https://jakearchibald.com/2016/link-in-body/ <3 -->
<head>
</head>
<body>
<link rel="stylesheet" href="/site-header.css">
<header>..</header>
<link rel="stylesheet" href="/article.css">
<main>..</main>
<link rel="stylesheet" href="/comment.css">
<section class='comments'>..</section>
<link rel="stylesheet" href="/about-me.css">
<section class='about-me'>..</section>
<link rel="stylesheet" href="/footer.css">
<footer>..</footer>
</body>
 -  Include  scripts  before end of <body>
<body>
..rest of markup
<script src="//my-awesome-library.js"></script>
<script src="analytics.js"></script>
</body>
 -  'defer'  attribute  on  <script/>
<script src="//my-awesome-library.js" defer></script>
<script src="analytics.js" defer></script>
 -  'aysnc'  attribute  on  <script/>
<script src="//my-awesome-library.js" async></script>
<script src="analytics.js" async></script>
Continued ...
 -  Script injected <script/>
'use strict';
[
'//my-awesome-library.js',
'analytics.js'
].forEach(link => {
const script = document.createElement('script');
script.src = src;
document.head.appendChild(script);
});
 -  Script injected <script/> with async = false
'use strict';
[
'//my-awesome-library.js',
'analytics.js'
].forEach(link => {
const script = document.createElement('script');
script.src = src;
script.async = false;
document.head.appendChild(script);
});
Developer: What is this dude!! I have done all optimizations told by that conference guy and still my website is not loading in 1000ms.
I am feeling cheated.
On twitter/Insta :- #feelingCheated #conferenceGuy #whatToDo
But  the  problem  actually  is....
Custom  FONTS
P.S. :- Fonts are great tool.
Relation  between  Fonts  and  RenderingÂ
Solutions :-
<head>
<link rel="stylesheet" href="main.css">
<link rel="stylesheet" href="font.css" media="none"
onload="if(media!='all')media='all'">
<style>
body {
font-family: MyFancyFont, "Times New Roman", ...;
}
</style>
</head>
<body>
</body>
/* Content of fonts.css*/
@font-face {
font-family: MyFancyFont;
font-style: normal;
font-weight: 400;
src: local('MyFancyFont'),
url('data:application/x-font-woff;charset=utf-8;base64,...')
}
3. Use font-loading API (https://drafts.csswg.org/css-font-loading/)
//Source :-
//https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization
var font = new FontFace("myAwesomeFont", "url(/fonts/MyAwesomeFonts.woff2)", {
style: 'normal', weight: '400'
});
font.load(); // don't wait for render tree, initiate immediate fetch!
font.ready().then(function() {
// apply the font (which may re-render text and cause a page re-flow)
// once the font has finished downloading
document.fonts.add(font);
document.body.style.fontFamily = "Awesome Font, serif";
// OR... by default content is hidden, and rendered once font is available
var content = document.getElementById("content");
content.style.visibility = "visible";
// OR... apply own render strategy here...
});
Support :- http://caniuse.com/#feat=font-loading
Can't  we  really  load  all  non-critical  resources  through  a unique method or API ?
function bestResourceLoadingMethod() {
return new Promise(resolve,reject) {
if(isConditionalLoading()) {
return resolve();
} else {
return reject();
}
}
}
bestResourceLoadingMethod()
.then(_ => console.log('Yes :3'))
.catch(_ => console.log('Future beholds something for you :D'));
Cautions :-
- Spec is still in draft mode.
- Currently, supported in Chrome only
<head>
<!-- preload this resource as stylesheet -->
<link rel="preload" href="/script/my-awesome-library.js" as="script">
</head>
<body>
<script>
if( needMyAwesomeLibrary ) {
const lib = document.createElement('script);
//Now, browser should automatically get from cache if preloaded
lib.src = "/script/my-awesome-library.js";
document.head.appendChild(lib);
}
</script>
</body>
Supported value of 'as' are :-
 media     Â
 script     Â
 style
 font
 image
 object
 document
 worker
 embed
#1 Reduce Number of HTTP Requests.
#3 Gzip everything.
#2 Don't abuse #1
#4 Never use CSS @imports
#5 Keep JavaScript that will progressively load non-critical things at top before <link rel = "stylesheet">
#6 window.onload is not a right metric to stop showing loading spinner.
#7 Try to cache fonts if you can.
#8 Use rAf for animation.
#9 Use requestIdleCallback() for non-essential stuff.
#10 Use Streams if you can (https://jakearchibald.com/2016/streams-ftw/)
/aboutme
/name
TARUN GARG
/age
Approaching 21
/github
@tarungarg546
@Tarun_Garg2
@tarungarg546
/experience
Fresher
@addyosmani      @aerotwist     @paulirish    @igrogorik
Â
@daviswalsh        @getifyJS       @souders    @grigs
Â
@scottjehl          @chromiumdev  @yoavweiss and lot more......