How Modern Web Technology Works - The Foundation for a Faster Web
What you might get out of this
P.S. Maybe we can clear up some myths too.
Why do we need to know how a browser does things
„About 25 years ago Jakob Nielsen wrote a book called Usability Engineering and he offered some advice about response times which had already been in place for at least 25 years before he wrote the book.“
https://www.nngroup.com/articles/response-times-3-important-limits/
https://developers.google.com/web/fundamentals/performance/why-performance-matters/
Data vs. Feelings
First | Repeated | |
---|---|---|
TTFB | 0.8s | 0.8s |
First Paint | 2.2s | 1.9s |
DOMContentLoaded | 3.3s | 2.4s |
Load | 6.6s | 4.9s |
Finished | 9.2s | 6.7s |
Visual Complete | 9.0s | 7.4s |
Bytes Transferred | 3,100kB | 187kB |
Request Count | 268/268 | 69/268 |
0s
1s
2s
3s
4s
5s
6s
7s
8s
9s
This is just an example of many data points to collect and evaluate. We will revisit some of them later during the RAIL discussion.
What will we learn today?
And there will be way more in it to think about and stay curious.
Protocols, Terminology, and other Things
Just a few words put in context that we might hear later again
None of these is precisely defined.
The TCP/IP reference model - Just to know how things travel around
This is highly simplified to give you an idea how many components are part of the page building and how much effort happens.
https://en.wikipedia.org/wiki/Internet_protocol_suite
The buzzword that is thrown in randomly
Real | Humanized | |
---|---|---|
CPU Cycle | 0.4 ns | 1 s |
L1 Cache | 0.9 ns | 2 s |
L2 Cache | 2.8 ns | 7 s |
L3 Cache | 28 ns | 1 min |
Memory Access | 100 ns | 4 min |
NVM SSD | 25 μs | 17 h |
SSD | 50–150 μs | 1.5-4 days |
HDD | 1–10 ms | 1-9 months |
TCP SF to NY | 65 ms | 5 years |
TCP SF to Hong Kong | 141 ms | 11 years |
http://www.prowesscorp.com/computer-latency-at-a-human-scale/
What is bandwidth?
Homepage Size | Mobile | Fixed | Limited to 5 Mbps | |
---|---|---|---|---|
Columbia | 3.3 MB | 1.2 s | 0.41 s | 5.28 s |
Crocs | 1.3 MB | 0.5 s | 0.16 s | 2.08 s |
Michaels | 4.7 MB | 1.7 s | 0.59 s | 7.52 s |
http://www.speedtest.net/reports/united-states/
The Domain Name System
$ dig www.columbia.com
;; QUESTION SECTION:
;www.columbia.com. IN A
;; ANSWER SECTION:
www.columbia.com. 680 IN CNAME www.columbia.com.cdn.cloudflare.net.
www.columbia.com.cdn.cloudflare.net. 300 IN A 104.17.8.17
www.columbia.com.cdn.cloudflare.net. 300 IN A 104.17.9.17
;; Query time: 59 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri Jun 15 19:51:46 CDT 2018
;; MSG SIZE rcvd: 126
$ dig www.yetanotherblog.de
;; QUESTION SECTION:
;www.yetanotherblog.de. IN A
;; ANSWER SECTION:
www.yetanotherblog.de. 86400 IN A 5.35.225.36
;; Query time: 211 msec
;; SERVER: 127.0.0.1#53(127.0.0.1)
;; WHEN: Fri Jun 15 20:01:55 CDT 2018
;; MSG SIZE rcvd: 66
You can barely influence this.
; <<>> DiG www.yetanotherblog.de. @8.8.4.4
;; global options: +cmd
. 117473 IN NS e.root-servers.net.
. 117473 IN NS h.root-servers.net.
. 117473 IN NS l.root-servers.net.
. 117473 IN NS i.root-servers.net.
. 117473 IN NS a.root-servers.net.
. 117473 IN NS d.root-servers.net.
. 117473 IN NS c.root-servers.net.
. 117473 IN NS b.root-servers.net.
. 117473 IN NS j.root-servers.net.
. 117473 IN NS k.root-servers.net.
. 117473 IN NS g.root-servers.net.
. 117473 IN NS m.root-servers.net.
. 117473 IN NS f.root-servers.net.
;; Received 228 bytes from 8.8.4.4#53(8.8.4.4) in 5 ms
de. 172800 IN NS a.nic.de.
de. 172800 IN NS f.nic.de.
de. 172800 IN NS l.de.net.
de. 172800 IN NS n.de.net.
de. 172800 IN NS s.de.net.
de. 172800 IN NS z.nic.de.
;; Received 381 bytes from 192.5.5.241#53(192.5.5.241) in 3 ms
yetanotherblog.de. 86400 IN NS ns1.hans.hosteurope.de.
yetanotherblog.de. 86400 IN NS ns2.hans.hosteurope.de.
;; Received 91 bytes from 194.146.107.6#53(194.146.107.6) in 1217 ms
www.yetanotherblog.de. 86400 IN A 5.35.225.36
;; Received 107 bytes from 217.115.143.140#53(217.115.143.140) in 118 ms
; <<>> DiG www.columbia.com. @8.8.4.4
;; global options: +cmd
. 65027 IN NS a.root-servers.net.
. 65027 IN NS b.root-servers.net.
condensed here
. 65027 IN NS l.root-servers.net.
. 65027 IN NS m.root-servers.net.
;; Received 228 bytes from 8.8.4.4#53(8.8.4.4) in 6 ms
com. 172800 IN NS a.gtld-servers.net.
com. 172800 IN NS b.gtld-servers.net.
com. 172800 IN NS c.gtld-servers.net.
com. 172800 IN NS d.gtld-servers.net.
com. 172800 IN NS e.gtld-servers.net.
com. 172800 IN NS f.gtld-servers.net.
com. 172800 IN NS g.gtld-servers.net.
com. 172800 IN NS h.gtld-servers.net.
com. 172800 IN NS i.gtld-servers.net.
com. 172800 IN NS j.gtld-servers.net.
com. 172800 IN NS k.gtld-servers.net.
com. 172800 IN NS l.gtld-servers.net.
com. 172800 IN NS m.gtld-servers.net.
;; Received 494 bytes from 199.7.91.13#53(199.7.91.13) in 4 ms
columbia.com. 172800 IN NS udns1.ultradns.net.
columbia.com. 172800 IN NS udns2.ultradns.net.
columbia.com. 172800 IN NS pdns3.ultradns.org.
columbia.com. 172800 IN NS pdns4.ultradns.org.
columbia.com. 172800 IN NS pdns1.ultradns.net.
columbia.com. 172800 IN NS pdns2.ultradns.net.
columbia.com. 172800 IN NS pdns5.ultradns.info.
columbia.com. 172800 IN NS pdns6.ultradns.co.uk.
;; Received 365 bytes from 192.52.178.30#53(192.52.178.30) in 24 ms
www.columbia.com. 900 IN CNAME www.columbia.com.cdn.cloudflare.net.
;; Received 83 bytes from 204.74.115.1#53(204.74.115.1) in 16 ms
https://www.digwebinterface.com/
By https://www.dnsperf.com/ from 2018-06-21
DNS is just another service
By https://www.dnsperf.com/ from 2018-06-21
A quick look at HTTP and HTTPS
https://hpbn.co/transport-layer-security-tls/
GET / HTTP/1.1
Host: www.yetananotherblog.de
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate, br
Accept-Language: de,en-US;q=0.9,en;q=0.8
Cache-Control: no-cache
Connection: keep-alive
DNT: 1
Pragma: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
HTTP/1.1 200 OK
Connection: keep-alive
Content-Encoding: gzip
Content-Length: 11299
Content-Security-Policy: default-src 'self' 'unsafe-inline' data: https:; upgrade-insecure-requests
Content-Type: text/html; charset=iso-8859-1
Date: Sat, 16 Jun 2018 14:55:47 GMT
Generator: LMNucleus CMS v3.66
Server: Apache
Set-Cookie: lastVisit=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; secure
Vary: Accept-Encoding,User-Agent
X-Content-Type-Options: nosniff
X-FRAME-OPTIONS: SAMEORIGIN
X-XSS-Protection: 1; mode=block
The payload starts here...
The new kid on the block, also known as H2
H2 is more complicated than HTTP/1.1
GET / HTTP/2
Host: www.columbia.com
:authority: www.columbia.com
:method: GET
:path: /
:scheme: https
accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
accept-encoding: gzip, deflate, br
accept-language: de,en-US;q=0.9,en;q=0.8
cache-control: no-cache
dnt: 1
pragma: no-cache
upgrade-insecure-requests: 1
user-agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36
accept-ranges: bytes
cache-control: no-cache, no-store, must-revalidate
cf-ray: 42be2de3b85454f2-ORD
content-encoding: gzip
content-type: text/html;charset=UTF-8
date: Sat, 16 Jun 2018 15:06:15 GMT
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
expires: Thu, 01 Dec 1994 16:00:00 GMT
pragma: no-cache
server: cloudflare
set-cookie: __cfduid=dbd5bbb595f00e8e9166a4f9e2ba7f6cf1529161574; expires=Sun, 16-Jun-19 15:06:14 GMT; path=/; domain=.columbia.com; HttpOnly
set-cookie: dwac_bd5D2iaaitc6EaaaddrFt9bJhC=Vyfy4tOMQG8756F9Rr8IHjR8UzXNsWzUfpk%3D|dw-only|||USD|false|US%2FPacific|true; Path=/
set-cookie: cqcid=adR56XabqtjiUW2SKVe6GLdpWV; Path=/
status: 200
vary: Accept-Encoding
x-content-type-options: nosniff
x-dw-request-base-id: OFp2ylslJ2egAgAK
The payload starts here...
And nothing here was really sent that way...
HTML, Images, Fonts, CSS, JavaScript, and more
HTML5, the cornerstone of the modern web
section
and footer
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Title of the document</title>
</head>
<body>
Content of the document......
</body>
</html>
Logo by W3C under CC-BY-3.0
Cascading Style Sheets - How to make things beautiful
.foo
: Elements with class foo.foo .bar
: Elements with class foo under elements with class bar#foobar
: Elements with id=foobarp[foo]
: p elements with attribute foop[foo="bar"]
: p elements with attribute foo and value bar.foo:not(p)
: Elements with class foo and not being a p elementsection > p
: p elements that are direct children of sectionThe Selectors will become important for performance later
Just some more important facts
@import
)@media
)@import "custom.css";
@import "common.css" screen;
@import url('landscape.css') screen and (orientation:landscape);
@media screen and (max-width: 600px) {
.example {
display: none;
}
}
<style>
* {color: White;} /* 0, 0, 0, 0, 0 */
p {color : Red !important;} /* 1, 0, 0, 0, 1 */
.foo {color : Yellow;} /* 0, 0, 0, 1, 0 */
p.foo {color : Brown;} /* 0, 0, 0, 1, 1 */
div p {color : Green;} /* 0, 0, 0, 0, 2 */
#header p {color : Green;} /* 0, 0, 1, 0, 1 */
p {color : Blue;} /* 0, 0, 0, 0, 1 */
p {color : Gray;} /* 0, 0, 0, 0, 1 */
</style>
<div id="header">
<p class="foo" style="color: Black;">Text here</p> /* 0, 1, 0, 0, 0 */
</div>
Fun game, isn't it?
Make things look even better
Ubuntu Mono
Roboto Mono
Roboto Mono 300
Hack
Roboto
Roboto Condensed
Loading of fonts will become interesting.
The dynamic part of a web page
<!DOCTYPE html>
<html>
<head>
<script>
// run this function when the document is loaded
window.onload = function() {
// create a couple of elements in an otherwise empty HTML page
var heading = document.createElement("h1");
var heading_text = document.createTextNode("Big Head!");
heading.appendChild(heading_text);
document.body.appendChild(heading);
}
</script>
</head>
<body>
<!-- empty -->
</body>
</html>
The next big thing might be WebAssembly, but not today.
The largest payload with the nicest look
SVG 3.0 kB
SVG 3.0 kB
SVG 3.0 kB
PNG 6.5 kB
JPG 20.7 kB, 100%
JPG 6.6 kB, 79%
We will come to srcset
later to make things right.
Important piece of the AJAX thing
var request = new XMLHttpRequest();
request.onreadystatechange = function () {
var DONE = this.DONE || 4;
if (this.readyState === DONE){
alert(this.readyState);
}
};
request.open('GET', 'somepage.xml', true);
// Tells server that this call is made for ajax purposes.
// Most libraries like jQuery/Prototype/Dojo do this
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
// No data needs to be sent along with the request
request.send(null);
XHR can be a burden for the server.
Small things that can get big
Cookie: __cfduid=d1f0558eb4291014c9f1ab4d49df0ee971527262512;
dwanonymous_29c8bd709bce117811b14d53deb17581=acZl83aSHkCSQRi0C21biPDfSa;
mt.v=2.970178920.1527262513452;
_ga=GA1.2.1567325025.1527262514;
tracker_device=77a185df-2e94-4fea-b5e5-6aff7e88f325;
__sonar=16246308783896654907;
sr_cr102_exp=3;
sr_browser_id=14a19809-7a3c-42f2-a6ca-7f3f994c7813;
QuantumMetricUserID=5b370292cd3498392b9a13090c6c88f8;
__cq_seg=0~0.00!1~0.00!2~0.00!3~0.00!4~0.00!5~0.00!6~0.00!7~0.00!8~0.00!9~0.00!f0~15~9;
cqcid=acZl83aSHkCSQRi0C21biPDfSa;
__cq_dnt=0;
dw_dnt=0;
dw=1;
undefined=1;
ColeHaanNewsletterVisits=2;
ColeHaanNewsletterSession=0;
QuantumMetricEnabled=true;
QuantumMetricSessionID=38436054e0b8906818d9b45d9d0e139f;
dwac_bct8giaagE38Yaaac663BfOTDo=MvJXttrDjrbZhWSoqtWjnrK5vaKqmIToA04%3D|dw-only|||USD|false|America%2FNew%5FYork|true;
sid=MvJXttrDjrbZhWSoqtWjnrK5vaKqmIToA04;
tradeGlobalGeolocation=DE;
clhSessID=yocN8p0w==;
customerID=MvJXttrDjrbZhWSoqtWjnrK5vaKqmIToA04=;
dwsid=q7w-eGxZrDtli89TV0_0Viv31GwcAqZlv0D_uPzY49QEsA3ngjKIXndKG_5g6R3fRLfCpy98ZN5fR4yocN8p0w==;
_gid=GA1.2.342874631.1529413056;
_dc_gtm_UA-38317407-1=1;
_uetsid=_uet7554f3c0;
mp_cole_haan_mixpanel=%7B%22distinct_id%22%3A%20%2216397f09133498-0d552b06f36dc5-3b7b0d58-1fa400-16397f0913442a%22%7D;
__cq_uuid=d26e3e40-7176-11e8-96f9-db11fe5c995a;
_hjIncludedInSample=1;
_gat_UA-38317407-1=1;
RT="sl=1&ss=1529413055000&tt=5016&obo=0&sh=1529413060023%3D1%3A0%3A5016&
dm=colehaan.com&si=90e14679-0448-4346-a7e6-38497ec5ee2e&bcn=%2F%2F36e4f0e7.
akstat.io%2F&ld=1529413060025&r=http%3A%2F%2Fwww.colehaan.com%2F&
ul=1529413078197";
_4c_=LY%2FrSgQxDIXfJb%2BHIUmbtJ1%2FgiA%2BhfSKoqzLungb5t03FUMhLZxzvp4dvp77CTYSTp4chsioC7
z2nw%2FYdri8tLk%2BYQMuRTWM3EnioFozh5I75txGVV8QFvieOU7QRaHgOB4L1PO%2Ff4f63rrlUFp1daa
%2B%2Fs4XT2M%2FTcL50uw%2BzAGlYXXaKrochX3OZUQ3CH1qlWNR0z3cPT3ezwRRYwmyrFYisLKQB0P%2F
%2FcZapeTFjhjx%2BgZbVI9zjuO4AQ%3D%3D
How Does a Webpage gets Loaded?
Turn Text into Graphics
URL first
Nothing fancy here yet.
Find where the system for that URL is
Tuning information will come later.
Establish connection on Internet layer
Establish TLS with a handshake
Time to ask for something useful
Wireshark was used for recording the conversation
Take care of the first content
https://html.spec.whatwg.org/multipage/parsing.html#parse-errors
Lot of things will happen now in parallel
https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/#The_main_flow
Highly optimized in modern browsers
So, let's continue to load our page.
CSS, JavaScript, Images, and Fonts
defer
or async
is lowFonts have special loading behavior
@font-face {
font-family: 'RobotoMono';
font-style: normal;
font-weight: normal;
src: url('fonts/Roboto/roboto-mono.woff') format('woff'),
url('fonts/Roboto/roboto-mono.ttf') format('truetype'),
url('fonts/Roboto/roboto-mono.svg#roboto-mono') format('svg'),
url('fonts/Roboto/roboto-mono.eot?#iefix') format('embedded-opentype');
}
https://developers.google.com/web/fundamentals/performance/optimizing-content-efficiency/webfont-optimization
JavaScript is considered a "parser blocking resource". This means that the parsing of the HTML document itself is blocked by JavaScript. When the parser reaches a
script
tag, whether that be internal or external, it stops to fetch (if it is external) and run it.
defer
async
https://bitsofco.de/async-vs-defer/
The base for any kind of rendering
https://developers.google.com/web/fundamentals/performance/critical-rendering-path/constructing-the-object-model
CSS and JS depend on each other
attr
The standard suggests a model for renderer and layouter
https://www.w3.org/TR/CSS21/intro.html#processing-model
Building the render tree
https://developers.google.com/web/fundamentals/performance/critical-rendering-path/render-tree-construction
Calculating visual appearance
Finally things appear
https://www.w3.org/TR/CSS21/zindex.html
Most important events during a page's lifecycle
https://www.w3.org/TR/navigation-timing/
When do we get things
A series of timestamps and events, measurements by Performance Timing API
https://www.w3.org/TR/html5/syntax.html#the-end
User does not care about technical details
first-paint
, first-contentful-paint
First Paint | First Contentful Paint |
---|---|
![]() |
![]() |
First Meaningful Paint | Visual Complete |
![]() |
![]() |
No relation between DOM numbers and visual impression!
How to use the measurements despite being of low interest by the user
https://www.w3.org/TR/html5/syntax.html#the-end
Your Questions and Feedback