Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Happy Browser, Happy User! - PerfMatters Conference 2019

1,124 views

Published on

Performance is fundamentally, a UX concern. Sites that are slow to render or janky to interact with are a bad user experience. We strive to write performant code for our users, but users don’t directly interact with our code - it all happens through the medium of the browser. The browser is the middleman between us and our users; therefore to make our users happy, we first have to make the browser happy. But how exactly do we do that?

In this talk, we’ll learn how browsers work under the hood: how they request, construct, and render a website. At each step along the way, we’ll cover what we can do as developers to make the browser’s job easier, and why those best practices work. You’ll leave with a solid understanding of how to write code that works *with* the browser, not against it, and ultimately improves your users’ experience.

Published in: Engineering
  • Be the first to comment

Happy Browser, Happy User! - PerfMatters Conference 2019

  1. 1. HAPPY BROWSER, HAPPY USER! Katie Sylor-Miller
  2. 2. Katie Sylor-Miller Staff Software Engineer Etsy Frontend Systems @ksylor ohshitgit.com
 gum.co/oh-shit-git
 @ohshitgit bit.ly/ksm-dsh
  3. 3. @ksylor PERFORMANCE IS UX
  4. 4. PERFORMANCE IS UX
  5. 5. @ksylor HOW DO WE MAKE THE BROWSER HAPPY?
  6. 6. @ksylor THE TROUBLE WITH BROWSERS TWO PROBLEMS: NETWORK LATENCY SINGLE THREAD**mostly
  7. 7. @ksylor HOW DO BROWSERS WORK? 4 PHASES ▸ Navigation ▸ Parsing ▸ Rendering ▸ Interaction
  8. 8. @ksylor HOW DO BROWSERS WORK? https://mindblowncat.com 4 PHASES ▸ Navigation ▸ Parsing ▸ Rendering ▸ Interaction
  9. 9. @ksylor GET IT OVER WITH! NAVIGATION GOAL:
  10. 10. @ksylor NAVIGATION - CONNECTION https://mindblowncat.com the internet 1. DNS lookup DNS server what is the IP address for
 mindblowncat.com? 162.144.26.144
  11. 11. @ksylor NAVIGATION - CONNECTION https://mindblowncat.com the internet 1. DNS lookup DNS server what is the IP address for
 mindblowncat.com? 162.144.26.144 SYN SYN ACK ACK 2. TCP handshake mindblowncat.com
 162.144.26.144
  12. 12. @ksylor NAVIGATION - CONNECTION https://mindblowncat.com the internet 3. SSL handshake ClientHello ServerHello & Certificate Client key FINISHED FINISHED 1. DNS lookup DNS server what is the IP address for
 mindblowncat.com? 162.144.26.144 SYN SYN ACK ACK 2. TCP handshake mindblowncat.com
 162.144.26.144
  13. 13. @ksylor NAVIGATION - CONNECTION https://mindblowncat.com the internet 3. SSL handshake ClientHello ServerHello & Certificate Client key FINISHED FINISHED 1. DNS lookup DNS server what is the IP address for
 mindblowncat.com? 162.144.26.144 SYN SYN ACK ACK 2. TCP handshake 4. Request mindblowncat.com
 162.144.26.144 HTTP GET
  14. 14. @ksylor NAVIGATION - CONNECTION https://mindblowncat.com the internet 3. SSL handshake ClientHello ServerHello & Certificate Client key FINISHED FINISHED 1. DNS lookup DNS server what is the IP address for
 mindblowncat.com? 162.144.26.144 SYN SYN ACK ACK 2. TCP handshake 4. Request mindblowncat.com
 162.144.26.144 HTTP GET 5. SERVER STUFF 6. SEND RESPONSE
  15. 15. @ksylor NAVIGATION - CONNECTION https://mindblowncat.com the internet 3. SSL handshake ClientHello ServerHello & Certificate Client key FINISHED FINISHED 1. DNS lookup DNS server what is the IP address for
 mindblowncat.com? 162.144.26.144 SYN SYN ACK ACK 2. TCP handshake 4. Request mindblowncat.com
 162.144.26.144 HTTP GET 5. SERVER STUFF 6. SEND RESPONSE ACK 2nd HTTP RESPONSE (29kb) 3rd HTTP RESPONSE (57kb) ACK etc… 1st HTTP RESPONSE (14kb) 7. TTFB
  16. 16. @ksylor NAVIGATION - CONNECTION https://mindblowncat.com the internet 3. SSL handshake ClientHello ServerHello & Certificate Client key FINISHED FINISHED 1. DNS lookup DNS server what is the IP address for
 mindblowncat.com? 162.144.26.144 SYN SYN ACK ACK 2. TCP handshake 4. Request mindblowncat.com
 162.144.26.144 HTTP GET 5. SERVER STUFF 6. SEND RESPONSE ACK 2nd HTTP RESPONSE (29kb) 3rd HTTP RESPONSE (57kb) ACK etc… 1st HTTP RESPONSE (14kb) 7. TTFB 8. Parse
  17. 17. @ksylor NAVIGATION HOW CAN WE CUT DOWN NAVIGATION TIME? ▸ HTTP/2 push ▸ Preloading & resource hints ▸ Reduce server response time ▸ Use a CDN ▸ Smaller files = fewer roundtrips ▸ First 14kb
  18. 18. @ksylor HOW DO BROWSERS WORK? https://mindblowncat.com 4 PHASES ▸ Navigation ▸ Parsing ▸ Rendering ▸ Interaction
  19. 19. @ksylor DOM + CSSOM, ASAP PARSING GOAL:
  20. 20. @ksylor PARSING SUPER SIMPLE HTML <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css" rel="stylesheet"/>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat" alt="Cat!"/>
 </div>
 </body> </html>
  21. 21. @ksylor DOM DOCUMENT OBJECT MODEL
  22. 22. @ksylor <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> PARSING - HTML TO DOM HTML html DOM NETWORK RESPONSE HTML Main Worker Network
 Process
  23. 23. @ksylor <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> PARSING - PRELOAD SCANNER HTML html DOM REQUEST STYLE.CSS NETWORK RESPONSE HTML REQUEST SCRIPT.JS REQUEST CAT.JPG Main Worker Network
 Process
  24. 24. @ksylor <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> PARSING - HTML TO DOM HTML html DOM head REQUEST STYLE.CSS NETWORK RESPONSE HTML REQUEST SCRIPT.JS REQUEST CAT.JPG Main Worker Network
 Process
  25. 25. @ksylor <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> PARSING - HTML TO DOM HTML html DOM head title REQUEST STYLE.CSS NETWORK RESPONSE HTML REQUEST SCRIPT.JS REQUEST CAT.JPG Main Worker Network
 Process
  26. 26. @ksylor <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> PARSING - HTML TO DOM HTML html DOM head title REQUEST STYLE.CSS NETWORK link RESPONSE HTML REQUEST SCRIPT.JS REQUEST CAT.JPG Main Worker Network
 Process
  27. 27. @ksylor PARSING - HTML TO DOM HTML html DOM head link title <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> REQUEST STYLE.CSS NETWORK RESPONSE HTML REQUEST SCRIPT.JS script REQUEST CAT.JPG Main Worker Network
 Process
  28. 28. @ksylor PARSING - HTML TO DOM HTML html DOM head link title <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> REQUEST STYLE.CSS NETWORK RESPONSE HTML REQUEST SCRIPT.JS script REQUEST CAT.JPG JAVASCRIPT IS RENDER BLOCKING* *when included without defer or async attributes Main Worker Network
 Process
  29. 29. @ksylor PARSING - HTML TO DOM HTML html DOM head link title <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> REQUEST STYLE.CSS NETWORK RESPONSE HTML REQUEST SCRIPT.JS script REQUEST CAT.JPG BUT FIRST... CSS BLOCKS JS RESPONSE STYLE.CSS Main Worker Network
 Process
  30. 30. @ksylor CSSOM CSS OBJECT MODEL
  31. 31. @ksylor PARSING- CSS TO CSSOM CSSOMCSS body font-family: sans-serif; body { 
 font-family: sans-serif; 
 }
 h1 { 
 color: magenta; 
 }
 .border { 
 border: 1px solid grey; 
 }
 .border img { 
 display: block; 
 margin: 1em; 
 }
 .title { 
 font-family: serif; 
 } Main Worker Network
 Process
  32. 32. @ksylor PARSING- CSS TO CSSOM CSSOMCSS body font-family: sans-serif; body { 
 font-family: sans-serif; 
 }
 h1 { 
 color: magenta; 
 }
 .border { 
 border: 1px solid grey; 
 }
 .border img { 
 display: block; 
 margin: 1em; 
 }
 .title { 
 font-family: serif; 
 } h1 color: magenta; Main Worker Network
 Process
  33. 33. @ksylor PARSING- CSS TO CSSOM CSSOMCSS body font-family: sans-serif; .border border: 1px solid gray; body { 
 font-family: sans-serif; 
 }
 h1 { 
 color: magenta; 
 }
 .border { 
 border: 1px solid grey; 
 }
 .border img { 
 display: block; 
 margin: 1em; 
 }
 .title { 
 font-family: serif; 
 } h1 color: magenta; Main Worker Network
 Process
  34. 34. @ksylor PARSING- CSS TO CSSOM CSSOMCSS body font-family: sans-serif; img display:block; margin: 1em; .border border: 1px solid gray; body { 
 font-family: sans-serif; 
 }
 h1 { 
 color: magenta; 
 }
 .border { 
 border: 1px solid grey; 
 }
 .border img { 
 display: block; 
 margin: 1em; 
 }
 .title { 
 font-family: serif; 
 } h1 color: magenta; Main Worker Network
 Process
  35. 35. @ksylor PARSING- CSS TO CSSOM CSSOMCSS body font-family: sans-serif; img display:block; margin: 1em; .title font-family: serif; .border border: 1px solid gray; body { 
 font-family: sans-serif; 
 }
 h1 { 
 color: magenta; 
 }
 .border { 
 border: 1px solid grey; 
 }
 .border img { 
 display: block; 
 margin: 1em; 
 }
 .title { 
 font-family: serif; 
 } h1 color: magenta; Main Worker Network
 Process
  36. 36. @ksylor DOM BACK TO THE
  37. 37. @ksylor PARSING - HTML TO DOM HTML html DOM head link title <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> REQUEST STYLE.CSS NETWORK RESPONSE HTML REQUEST SCRIPT.JS script REQUEST CAT.JPG RESPONSE SCRIPT.JS RESPONSE STYLE.CSS Main Worker Network
 Process
  38. 38. @ksylor AST ABSTRACT SYNTAX TREE
  39. 39. @ksylor PARSING- JAVASCRIPT AST JS ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Program body: Main Worker Network
 Process go to: https://astexplorer.net
  40. 40. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program body: FunctionDeclaration id: body:
  41. 41. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "badIdea" id: body: body:
  42. 42. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "badIdea" id: body: BlockStatement body:
  43. 43. @ksylor VariableDeclaration body: id: init: PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "badIdea" id: body: BlockStatement body:
  44. 44. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration VariableDeclaration Identifier name: "badIdea" id: id: body: Identifier name: "cat" BlockStatement body: body: init:
  45. 45. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "cat" VariableDeclaration Identifier name: "badIdea" id: init: id: body: BlockStatement body: body: CallExpression callee: arguments:
  46. 46. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "cat" VariableDeclaration Identifier name: "badIdea" CallExpression id: init: id: body: BlockStatement body: body: callee: arguments: MemberExpression object: property:
  47. 47. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "cat" VariableDeclaration Identifier name: "badIdea" CallExpression id: init: id: body: BlockStatement body: body: MemberExpressioncallee: object: Identifier name: "document" property: arguments:
  48. 48. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "cat" VariableDeclaration Identifier name: "badIdea" CallExpression id: init: id: body: BlockStatement body: body: Identifier name: "document" MemberExpressioncallee: object: property: Identifier name: "getElementById" arguments:
  49. 49. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "cat" VariableDeclaration Identifier name: "document" Identifier name: "badIdea" MemberExpression CallExpression id: init: callee: object: Identifier name: "getElementById" id: body: BlockStatement Literal value:"cat" arguments: body: body: property:
  50. 50. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "cat" VariableDeclaration Identifier name: "badIdea" CallExpression id: init: id: body: BlockStatement body: body: Identifier name: "document" MemberExpressioncallee: object: property: Identifier name: "getElementById" Literal value:"cat" arguments: ExpressionStatement AssignmentExpression operator: "=" left: right: expression:
  51. 51. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "cat" VariableDeclaration Identifier name: "badIdea" ExpressionStatement CallExpression id: init: AssignmentExpression operator: "=" left: id: body: BlockStatement MemberExpression object: property: body: body: Identifier name: "document" MemberExpressioncallee: object: property: Identifier name: "getElementById" Literal value:"cat" arguments: right: expression:
  52. 52. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "cat" VariableDeclaration Identifier name: "badIdea" ExpressionStatement CallExpression id: init: AssignmentExpression operator: "=" MemberExpressionleft: object: property: id: body: BlockStatement Identifier name: "cat" body: body: Identifier name: "document" MemberExpressioncallee: object: property: Identifier name: "getElementById" Literal value:"cat" arguments: right: expression:
  53. 53. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "cat" VariableDeclaration Identifier name: "badIdea" ExpressionStatement CallExpression id: init: AssignmentExpression operator: "=" MemberExpressionleft: Identifier name: "cat" object: property: id: body: BlockStatement Identifier name: "src" body: body: Identifier name: "document" MemberExpressioncallee: object: property: Identifier name: "getElementById" Literal value:"cat" arguments: right: expression:
  54. 54. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "cat" VariableDeclaration Identifier name: "badIdea" ExpressionStatement CallExpression id: init: AssignmentExpression operator: "=" MemberExpressionleft: Identifier name: "document" Identifier name: "getElementById" object: property: right: id: body: BlockStatement Literal value:"another-cat.gif" body: body: Identifier name: "document" MemberExpressioncallee: object: property: Identifier name: "getElementById" Literal value:"cat" arguments: expression:
  55. 55. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "cat" VariableDeclaration Identifier name: "badIdea" ExpressionStatement CallExpression id: init: AssignmentExpression operator: "=" MemberExpressionleft: Identifier name: "document" Identifier name: "getElementById" object: property: right: Literal value:"another-cat.gif" id: body: BlockStatement body: body: Identifier name: "document" MemberExpressioncallee: object: property: Identifier name: "getElementById" Literal value:"cat" arguments: expression: ExpressionStatement CallExpressionexpression: callee:
  56. 56. @ksylor PARSING- JAVASCRIPT TO ABSTRACT SYNTAX TREE (AST) ASTJS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); Main Program FunctionDeclaration Identifier name: "cat" VariableDeclaration Identifier name: "badIdea" ExpressionStatement CallExpression id: init: AssignmentExpression operator: "=" MemberExpressionleft: Identifier name: "document" Identifier name: "getElementById" object: property: right: Literal value:"another-cat.gif" ExpressionStatement CallExpression callee: id: body: BlockStatement Identifier name: "badIdea" body: body: Identifier name: "document" MemberExpressioncallee: object: property: Identifier name: "getElementById" Literal value:"cat" arguments: expression:
  57. 57. @ksylor PARSING - JAVASCRIPT INTERPRETATION & COMPILATION (VERY) SIMPLIFIED INTERPRETATION & COMPILATION PROCESS INTERPRETER OPTIMIZING COMPILER(S) BYTECODE OPTIMIZED CODE slower execution faster execution AST Main Worker Network
 Process
  58. 58. @ksylor JAVASCRIPT EXECUTION JS function badIdea() {
 var cat =
 document.getElementById("cat");
 
 cat.src = "another-cat.gif";
 }
 
 badIdea(); html head link title script DOM ! Uncaught TypeError: 
 Cannot set property 'src' of null
 at badIdea (script.js:5) Main Worker Network
 Process
  59. 59. @ksylor DOM II BACK TO THE
  60. 60. @ksylor PARSING - HTML TO DOM (AGAIN) HTML html DOM head link title <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> REQUEST STYLE.CSS NETWORK RESPONSE HTML REQUEST SCRIPT.JS script REQUEST CAT.JPG RESPONSE SCRIPT.JS RESPONSE STYLE.CSS Main Worker Network
 Process
  61. 61. @ksylor <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> PARSING - HTML TO DOM (AGAIN) HTML html DOM head link title NETWORK script REQUEST STYLE.CSS RESPONSE HTML REQUEST SCRIPT.JS REQUEST CAT.JPG RESPONSE SCRIPT.JS RESPONSE STYLE.CSS Main Worker Network
 Process
  62. 62. @ksylor <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> PARSING - HTML TO DOM (AGAIN) HTML html DOM head link title NETWORK body script REQUEST STYLE.CSS RESPONSE HTML REQUEST SCRIPT.JS REQUEST CAT.JPG RESPONSE SCRIPT.JS RESPONSE STYLE.CSS Main Worker Network
 Process
  63. 63. @ksylor <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> PARSING - HTML TO DOM (AGAIN) HTML html DOM head link title NETWORK body h1 class:“title” Hi! script REQUEST STYLE.CSS RESPONSE HTML REQUEST SCRIPT.JS REQUEST CAT.JPG RESPONSE SCRIPT.JS RESPONSE STYLE.CSS Main Worker Network
 Process
  64. 64. @ksylor <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> PARSING - HTML TO DOM (AGAIN) HTML html DOM head link title NETWORK paragraph Here is a cat. body h1 class:“title” Hi! script REQUEST STYLE.CSS RESPONSE HTML REQUEST SCRIPT.JS REQUEST CAT.JPG RESPONSE SCRIPT.JS RESPONSE STYLE.CSS Main Worker Network
 Process
  65. 65. @ksylor <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> PARSING - HTML TO DOM (AGAIN) HTML html DOM head link title NETWORK paragraph Here is a cat. div class:”border” body h1 class:“title” Hi! script REQUEST STYLE.CSS RESPONSE HTML REQUEST SCRIPT.JS REQUEST CAT.JPG RESPONSE SCRIPT.JS RESPONSE STYLE.CSS Main Worker Network
 Process
  66. 66. @ksylor <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> PARSING - HTML TO DOM (AGAIN) HTML html DOM head link title NETWORK paragraph div class:”border” Here is a cat. body h1 class:“title” Hi! script REQUEST STYLE.CSS RESPONSE HTML REQUEST SCRIPT.JS REQUEST CAT.JPG RESPONSE SCRIPT.JS RESPONSE STYLE.CSS image id="cat" Main Worker Network
 Process
  67. 67. @ksylor <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css".../>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat"
 alt="Cat!"/>
 </div>
 </body>
 </html> PARSING - HTML TO DOM (AGAIN) HTML html DOM head link title NETWORK paragraph div class:”border” Here is a cat. body h1 class:“title” Hi! script image id="cat" REQUEST STYLE.CSS RESPONSE HTML REQUEST SCRIPT.JS REQUEST CAT.JPG RESPONSE SCRIPT.JS RESPONSE STYLE.CSS Main Worker Network
 Process
  68. 68. @ksylor HOW CAN WE MAKE THAT BETTER?
  69. 69. @ksylor DOM + CSSOM, ASAP PARSING GOAL:
  70. 70. @ksylor PARSING - TIMELINE CHECK HTML Main Worker Network
 Process parse html request css parse css parse html DomContentLoaded <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css" rel="stylesheet"/>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat" 
 alt="Cat!"/>
 </div>
 </body>
 </html> request js request image parse & execute js DomInteractive &wait at <script> for
 CSSOM preload scanner
  71. 71. @ksylor PARSING - TIMELINE IMPROVEMENTS MOVE STYLES INLINE Main Worker Network
 Process parse html parse css parse html DomContentLoaded <html>
 <head>
 <title>Cats are fun!</title>
 <style>...</style>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat" 
 alt="Cat!"/>
 </div>
 </body>
 </html> request image parse & execute js request js DomInteractive & preload scanner
  72. 72. @ksylor PARSING - TIMELINE IMPROVEMENTS MOVE SCRIPTS INLINE & TO THE BOTTOM Main Worker Network
 Process parse html parse css parse html DomContentLoaded <html>
 <head>
 <title>Cats are fun!</title>
 <style>...</style>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat" 
 alt="Cat!"/>
 </div>
 <script>...</script>
 </body>
 </html> request image parse & execute js preload scanner DomInteractive
  73. 73. @ksylor parse & execute js PARSING - TIMELINE IMPROVEMENTS ASYNC EXTERNAL JS Main Worker Network
 Process parse html parse css DomContentLoaded <html>
 <head>
 <title>Cats are fun!</title>
 <style>...</style>
 <script async src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat" 
 alt="Cat!"/>
 </div>
 </body>
 </html> request image request js html html DomInteractive & preload scanner
  74. 74. @ksylor parse & execute js PARSING - TIMELINE IMPROVEMENTS ASYNC EXTERNAL JS (BIGGER FILE/SLOWER NETWORK) Main Worker Network
 Process parse html parse css DomContentLoaded <html>
 <head>
 <title>Cats are fun!</title>
 <style>...</style>
 <script async src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat" 
 alt="Cat!"/>
 </div>
 </body>
 </html> request image request js parse html DomInteractive & preload scanner
  75. 75. @ksylor parse & execute js PARSING - TIMELINE IMPROVEMENTS DEFER EXTERNAL JS Main Worker Network
 Process parse html parse css DomContentLoaded <html>
 <head>
 <title>Cats are fun!</title>
 <style>...</style>
 <script defer src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat" 
 alt="Cat!"/>
 </div>
 </body>
 </html> request image request js parse html DomInteractive preload scanner
  76. 76. @ksylor THE TROUBLE WITH BROWSERS THE MAIN THREAD DOES IT ALL ▸ Parsing HTML into DOM ▸ Parsing CSS into CSSOM ▸ JS into JS AST ▸ JS Execution
  77. 77. @ksylor HOW DO BROWSERS WORK? https://mindblowncat.com 4 PHASES ▸ Navigation ▸ Parsing ▸ Rendering ▸ Interaction
  78. 78. @ksylor DO LESS WORK RENDERING GOAL:
  79. 79. @ksylor STYLE LAYOUT PAINT COMPOSITE THE RENDER PIPELINE
  80. 80. @ksylor STYLE LAYOUT PAINT COMPOSITE THE RENDER PIPELINE
  81. 81. @ksylor + BROWSER DEFAULT STYLES + USER-PROVIDED STYLESHEETS RENDERING - STYLE CALCULATION html DOM head link title body h1 class:“title” paragraph image div class:”border” Hi! Here is a cat. CSSOM body font-family: sans-serif; .border border: 1px solid gray; img display:block; margin: 1em; .title font-family: serif; COMPUTED STYLE root <body> font-family: sans-serif; <h1> color: magenta;
 font-family: serif; Hi! <p> font-family: sans-serif; <div> border: 1px solid gray; font-family: sans-serif; <img> display:block; margin: 1em; Here is a cat. h1 color: magenta; script Main Raster/
 Compositor Network
 Process
  82. 82. @ksylor STYLE LAYOUT PAINT COMPOSITE THE RENDER PIPELINE
  83. 83. @ksylor RENDERING - LAYOUT https://mindblowncat.comroot/html <body> font-family: sans-serif; <h1> color: magenta;
 font-family: serif; Hi! <p> font-family: sans-serif; <div> border: 1px solid gray; font-family: sans-serif; <img> display:block; margin: 1em; Here is a cat. html/viewporthtml/viewport COMPUTED STYLE Main Raster/
 Compositor Network
 Process
  84. 84. @ksylor root/html <body> font-family: sans-serif; <h1> color: magenta;
 font-family: serif; Hi! <p> font-family: sans-serif; <div> border: 1px solid gray; font-family: sans-serif; <img> display:block; margin: 1em; Here is a cat. COMPUTED STYLE RENDERING - LAYOUT html/viewport body COMPUTED STYLE Main Raster/
 Compositor Network
 Process
  85. 85. @ksylor RENDERING - LAYOUT html/viewport body h1 root/html <body> font-family: sans-serif; <h1> color: magenta;
 font-family: serif; Hi! <p> font-family: sans-serif; <div> border: 1px solid gray; font-family: sans-serif; <img> display:block; margin: 1em; Here is a cat. COMPUTED STYLE Main Raster/
 Compositor Network
 Process
  86. 86. @ksylor root/html <body> font-family: sans-serif; <h1> color: magenta;
 font-family: serif; Hi! <p> font-family: sans-serif; <div> border: 1px solid gray; font-family: sans-serif; <img> display:block; margin: 1em; Here is a cat. COMPUTED STYLE RENDERING - LAYOUT html/viewport body h1 Hi! Main Raster/
 Compositor Network
 Process
  87. 87. @ksylor root/html <body> font-family: sans-serif; <h1> color: magenta;
 font-family: serif; Hi! <p> font-family: sans-serif; <div> border: 1px solid gray; font-family: sans-serif; <img> display:block; margin: 1em; Here is a cat. COMPUTED STYLE RENDERING - LAYOUT html/viewport body h1 Hi! p Main Raster/
 Compositor Network
 Process
  88. 88. @ksylor RENDERING - LAYOUT html/viewport body h1 Hi! Here is a cat. p root/html <body> font-family: sans-serif; <h1> color: magenta;
 font-family: serif; Hi! <p> font-family: sans-serif; <div> border: 1px solid gray; font-family: sans-serif; <img> display:block; margin: 1em; Here is a cat. COMPUTED STYLE Main Raster/
 Compositor Network
 Process
  89. 89. @ksylor root/html <body> font-family: sans-serif; <h1> color: magenta;
 font-family: serif; Hi! <p> font-family: sans-serif; <div> border: 1px solid gray; font-family: sans-serif; <img> display:block; margin: 1em; Here is a cat. COMPUTED STYLE RENDERING - LAYOUT html/viewport body h1 Hi! Here is a cat. p div Main Raster/
 Compositor Network
 Process
  90. 90. @ksylor RENDERING - LAYOUT html/viewport body h1 Hi! Here is a cat. div p img root/html <body> font-family: sans-serif; <h1> color: magenta;
 font-family: serif; Hi! <p> font-family: sans-serif; <div> border: 1px solid gray; font-family: sans-serif; <img> display:block; margin: 1em; Here is a cat. COMPUTED STYLE Main Raster/
 Compositor Network
 Process
  91. 91. @ksylor STYLE LAYOUT PAINT COMPOSITE THE RENDER PIPELINE
  92. 92. @ksylor [ 
 [r, g, b, a],
 [r, g, b, a],
 [r, g, b, a], 
 ...
 ] RENDERING - PIXELS FRAME BUFFER
  93. 93. @ksylor RENDERING - PIXELS FRAME BUFFER [ 
 [r, g, b, a],
 [r, g, b, a],
 [r, g, b, a], 
 ...
 ] } 2.7Mpixels - iPhone X
  94. 94. @ksylor RENDERING - LAYERS PIXELS ARE PAINTED ON LAYERS RASTERIZE Main Raster/
 Compositor Network
 Process *layers pictured are imaginary for 
 demonstration purposes only ▸ 3D transforms ▸ CSS animation using opacity or transform ▸ will-change ▸ "accelerated" CSS filters ▸ <video> or <canvas> ▸ z-index above another layer CREATE A NEW LAYER
  95. 95. @ksylor STYLE LAYOUT PAINT COMPOSITE THE RENDER PIPELINE
  96. 96. @ksylor THE GPU OUR NEW COMPOSITING BFF
  97. 97. @ksylor Network
 Process RENDERING - COMPOSITE FLATTEN THE LAYERS (WITH MATH) Main Raster/
 Compositor background_layer = [
 [ 244, 0, 32, 1 ],
 [ 248, 10, 50, .5 ],
 ...
 ]; 
 layer_1 = [
 [ 33, 12, 42, 1 ],
 [ 0, 0, 15, 1 ],
 ...
 ]; applyCSSTransforms();
 applyCSSFilters(); return blendMode(
 background_layer,
 layer_1
 ) GPU background_layer = [
 [ 33, 12, 42, 1 ],
 [ 0, 0, 50, .5 ],
 ...
 ];
  98. 98. @ksylor Network
 Process RENDERING - COMPOSITE FINALLY! SOMETHING ON THE SCREEN! https://mindblowncat.com Hi! Here is a cat. Main Raster/
 Compositor
  99. 99. @ksylor RENDERING - TIMELINE CHECK HTML Main Worker/GPU/
 Compositor Network
 Process parse html request css parse css parse html <html>
 <head>
 <title>Cats are fun!</title>
 <link href="style.css" rel="stylesheet"/>
 <script src="script.js"></script>
 </head>
 <body>
 <h1 class="title">Hi!</h1>
 <p>Here is a cat.
 <div class="border">
 <img src="cat.gif" id="cat" 
 alt="Cat!"/>
 </div>
 </body>
 </html> request js request image parse & execute js preload scanner DCL FirstMeaningfulPaint style paint composite layout
  100. 100. @ksylor REFLOW :(
  101. 101. @ksylor STYLE LAYOUT PAINT COMPOSITE LET'S DO THAT AGAIN
  102. 102. @ksylor RENDERING - REFLOW RE-LAYOUT Hi! Here is a cat. Hi! Here is a cat. img Main
  103. 103. @ksylor RENDERING - REFLOW RE-PAINT Hi! Here is a cat. Raster/
 Compositor RASTERIZE
  104. 104. @ksylor RENDERING - REFLOW RE-COMPOSITE Raster/
 Compositor MATH! https://mindblowncat.com Hi! Here is a cat.
  105. 105. @ksylor RENDERING - SLIGHTLY LESS REFLOW IMAGE DIMENSIONS <img src="cat.gif" id="cat" alt="Cat!" height="442" width="500"/>
 STYLE LAYOUT PAINT COMPOSITE
  106. 106. @ksylor THE TROUBLE WITH BROWSERS THE MAIN THREAD DOES IT ALL ▸ Parsing HTML into DOM ▸ Parsing CSS into CSSOM ▸ JS into JS AST ▸ JS Execution ▸ Style Calculation (and re-style) ▸ Layout (and re-layout) ▸ Paint (and re-paint)
  107. 107. @ksylor HOW DO BROWSERS WORK? https://mindblowncat.com 4 PHASES ▸ Navigation ▸ Parsing ▸ Rendering ▸ Interaction Hi! Here is a cat.
  108. 108. @ksylor BE JANK FREE INTERACTION GOAL:
  109. 109. @ksylor INTERACTION THE MAIN THREAD DOES IT ALL ▸ Parsing HTML into DOM ▸ Parsing CSS into CSSOM ▸ JS into JS AST ▸ JS Execution ▸ Style Calculation (and re-style) ▸ Layout (and re-layout) ▸ Paint (and re-paint) ▸ User interaction
  110. 110. @ksylor INTERACTION - ANIMATION FRAME BUFFER [ 
 [r, g, b, a],
 [r, g, b, a],
 [r, g, b, a], 
 ...
 ] } 2.7Mpixels - iPhone X 60 fps FRAME RATE 16.67msto draw each frame}
  111. 111. @ksylor INTERACTION - ANIMATION HTML <button id="my-button"
 aria-controls="awesomeness">
 Click me!
 </button> <div class="dialog" 
 id="awesomeness"
 role="dialog"
 aria-hidden="true"
 aria-modal="false"
 aria-label="Awesomeness selector">
 <h1>Can you handle the awesome?</h1>
 <button>Yes</button> 
 <button>no</button>
 </div> .dialog[aria-hidden="true"] {
 display: none;
 } .dialog[aria-hidden="false"] {
 display: block;
 } CSS JS document.getElementById("my-button")
 .addEventListener("click",
 showDialog); function showDialog() {
 // ...get the dialog
 dialog.setAttribute("aria-hidden",
 "false");
 }
  112. 112. @ksylor INTERACTION - JANK "DROPPING" FRAMES FROM THE MAIN THREAD 16.67ms frame! frame! re-style re-layoutjs event handler button click opens
 an overlay dialog frame! frame! frame! <div>'s style changes
 from display: none;
 to display: block; re-paint jank :( jank :( jank :( jank :( re-composite
 on the GPU
  113. 113. @ksylor RENDERING - LAYERS LAYERS ARE AWESOME Main Raster/
 Compositor Network
 Process ▸ Repaint only the layer that changed, all other layers stay the same ▸ Easier to move/animate layers without repainting the whole page. ▸ But layers are expensive in memory! ▸ Don't create layers that don't change how the page is rendered.
  114. 114. @ksylor INTERACTION - BETTER ANIMATION HTML <button id="my-button"
 aria-controls="awesomeness">
 Click me!
 </button> <div class="dialog" 
 id="awesomeness"
 role="dialog"
 aria-hidden="true"
 aria-modal="false"
 aria-label="Awesomeness selector">
 <h1>Can you handle the awesome?</h1>
 <button>Yes</button> 
 <button>no</button>
 </div> .dialog {
 transition: visibility 0ms linear 300ms;
 } .dialog[aria-hidden="true"] {
 visibility: hidden;
 } .dialog[aria-hidden="false"] {
 visibility: visible;
 } CSS JS document.getElementById("my-button")
 .addEventListener("click",
 showDialog); function showDialog() {
 // ...get the dialog
 dialog.setAttribute("aria-hidden",
 "false");
 }
  115. 115. @ksylor INTERACTION - LESS JANK! "DROPPING" FRAMES FROM THE MAIN THREAD 16.67ms frame! frame! stylejs event handler button click opens
 an overlay dialog frame! frame! frame! <div>'s style changes
 from visibility: hidden;
 to visibility: visible;
 and uses css animations jank :( jank :( re-composite
 on the GPU frame! frame!frame!
  116. 116. @ksylor HOW DO WE MAKE BROWSERS HAPPY? https://mindblowncat.com 4 PHASES ▸ Navigation GET IT OVER WITH! ▸ Parsing DOM + CSSOM, ASAP ▸ Rendering DO LESS WORK (ON THE CPU) ▸ Interaction BE JANK FREE Hi! Here is a cat.
  117. 117. @ksylor THANK YOU!https://github.com/ksylor/happy-browser-happy-user

×