Updates to first chapter.

master
Thomas Hintz 4 years ago
parent bdc0b9cbb8
commit aa8ece3f0c

@ -1,3 +1,16 @@
#+BEGIN_SRC emacs-lisp :exports results :results silent
(require 'ox-latex)
(add-to-list 'org-latex-packages-alist '("" "minted"))
(setq org-latex-listings 'minted)
(setq org-latex-pdf-process
'("xelatex -shell-escape -interaction nonstopmode -output-directory %o %f"))
#+END_SRC
# #+latex_class: article
# #+latex_class_options: [a4paper,8pt]
# #+latex_header: \usepackage[a4paper,top=2.5cm,bottom=2.5cm,left=1.5cm,right=1.5cm]{geometry}
# #+latex_header:\renewcommand{\baselinestretch}{1.2}
#+TITLE: High-Performance React
#+AUTHOR: Thomas Hintz
@ -87,7 +100,7 @@ Before baking is finished bread is a living organism. The way it grows
and develops and flavors depend on what you feed it and how you feed
it and massage it, care for it. If you have it grow and ferment at a
higher temperature and more yeast it overdevelops producing too much
alcohol. If you give it too much time acidity will take over the
alcohol. If you give it too much time, acidity will take over the
flavor. The recipes I used initially were missing a critical
ingredient: the rising temperature.
@ -101,13 +114,14 @@ the other ingredients to complement the temperature. Now the bread can
tell me what to do.
While React isn't technically a living organism that can tell us what
to do it is, in its whole, a complex, abstract entity. We could learn basic
recipes for how to write high-performance React code but they wouldn't
apply in all cases and as React and things under it change our recipes
would fall out-of-date. So like the bread, to produce consistently
good results we need to understand how React does what it does.
to do, it is, in its whole, a complex, abstract entity. We could learn
basic recipes for how to write high-performance React code but they
wouldn't apply in all cases, and as React and things under it change
our recipes would fall out-of-date. So like the bread, to produce
consistently good results we need to understand how React does what it
does.
** React, made of
** Components of React
Conceptually React is very simple. It starts by walking a tree of
components and building up a tree of their output. Then it compares
@ -128,41 +142,43 @@ questions with solid answers.
React is centered around the ~render~ method. The ~render~ method is
what walks our trees, diffs them with the browser's DOM tree, and
updates the DOM as needed. But before we can look at the ~render~
method me have to understand its input. The input comes from
method we have to understand its input. The input comes from
~createElement~. While ~createElement~ itself is unlikely to be a
bottleneck it's a good to understand how it works so that we can have
a complete picture of the entire process. The more black-boxes we have
bottleneck it's good to understand how it works so that we can have a
complete picture of the entire process. The more black-boxes we have
in our mental model the harder it will be for us to diagnose
performance problems.
** Markup in Javascript: ~JSX~
** Markup in JavaScript: ~JSX~
~createElement~, however, takes as input something that is probably
not familiar to us since we usually work in JSX, which is the last
element of the chain in this puzzle and the first step in solving
it. While not strictly a part of React it is almost universally used
it. While not strictly a part of React, it is almost universally used
with it. And if we understand it then ~createElement~ will be less of
a mystery since we will be able to connect all the dots.
JSX is not valid HTML or Javascript but its own language compiled by a
JSX is not valid HTML or JavaScript but its own language compiled by a
compiler, like Babel. The output of that compilation is valid
Javascript that represents the original markup.
JavaScript that represents the original markup.
Before JSX the normal way of injecting HTML into the DOM was via
directly utilizing the browser's DOM APIs. This was very cumbersome.
The code's structure did not match the structure of the HTML that it
output which made it hard to quickly understand what the output of
a piece of code would be. So naturally programmers have been endlessly
searching for better ways to mix HTML with Javascript.
Before JSX or similar compilers, the normal way of injecting HTML into
the DOM was via directly utilizing the browser's DOM APIs or by
setting ~innerHTML~. This was very cumbersome. The code's structure
did not match the structure of the HTML that it output which made it
hard to quickly understand what the output of a piece of code would
be. So naturally programmers have been endlessly searching for better
ways to mix HTML with JavaScript.
And this brings us to JSX. It is nothing new; nothing
complicated. Forms of it have been made and used long before React
adopted it. Now let's see if we can discover JSX for ourselves.
To start with we need to create a data structure that both represents
a DOM tree and can also be used to insert one into the browser's
DOM. And to do that we need to understand what a tree of DOM nodes is
constructed of. What parts do you see here?
To start with, we need to create a data-structure -- let's call it
JavaScript Markup (JSM) -- that both represents a DOM tree and can
also be used to insert one into the browser's DOM. And to do that we
need to understand what a tree of DOM nodes is constructed of. What
parts do you see here?
#+BEGIN_SRC html
<div class="header">
@ -174,26 +190,21 @@ constructed of. What parts do you see here?
I see three parts: the name of the tag, the tag's properties, and its
children.
|----------+-----------------------------|
| name | 'div', 'h1', 'input' |
| props | 'class', 'type', 'disabled' |
| children | <h1>, <input>, Hello |
#+BEGIN_SRC
tag name: 'div'
tag prop: 'class'
children: h1..., 'Hello', input...
#+END_SRC
|-----------+-----------------------------|
| Name: | 'div', 'h1', 'input' |
| Props: | 'class', 'type', 'disabled' |
| Children: | <h1>, <input>, Hello |
Now how could we recreate that in Javascript?
Now how could we recreate that in JavaScript?
In Javascript we store lists of things in arrays and key/value
properties in objects. Luckily for us Javascript even gives us literal
In JavaScript, we store lists of things in arrays, and key/value
properties in objects. Luckily for us, JavaScript even gives us literal
syntax for both so we can easily make a compact DOM tree with our own
notation.
This is what I'm thinking:
#+CAPTION: JSM - JavaScript Markup
#+BEGIN_SRC javascript
['div', { 'className': 'header' },
[['h1', {}, ['Hello']],
@ -202,11 +213,11 @@ This is what I'm thinking:
]
#+END_SRC
As you can see we have a clear mapping from our notation to the
original HTML. Our tree is made up of three element arrays. The first
item in the array is the tag, the second is an object containing the
tag's properties, and the third is an array of its children; which are
all made up of the same three element arrays.
As you can see in, we have a clear mapping from our notation, JSM, to
the original HTML. Our tree is made up of three element arrays. The
first item in the array is the tag, the second is an object containing
the tag's properties, and the third is an array of its children; which
are all made up of the same three element arrays.
The truth is though, if you stare at it long enough, although the
mapping is clear, how much fun would it be to read and write that on a
@ -224,7 +235,7 @@ And this is where our object of study enters the scene. JSX is just a
notation that a compiler takes as input and outputs in its place a
tree of nodes nearly identical to the notation we came up with! And if
you look back to our notation you can see that you can easily embed
arbitrary Javascript expressions wherever you want in a node. As you
arbitrary JavaScript expressions wherever you want in a node. As you
may have realized, that's exactly what the JSX compiler does when it
sees curly braces!
@ -232,7 +243,7 @@ There are three main differences between our data structure and the
real one that the JSX compiler outputs: it uses objects instead of
arrays, it inserts calls to React.createElement on children, and
spreads the children instead of containing them in an array. Here is
what "real" JSX compiler output looks like:
what real JSX compiler output looks like:
# #+NAME: foo
# #+CAPTION: foo bar
@ -248,10 +259,10 @@ React.createElement(
);
#+END_SRC
As you can see it is very similar to our data-structure and for the
purposes of this book we will use our own simplified data-structure as
it's a bit easier to work with. A JSX compiler also does some
validation and escapes input to prevent cross-site scripting
As you can see, it is very similar to our markup data-structure and
for the purposes of this book we will use our own simplified
data-structure as it's a bit easier to work with. A JSX compiler also
does some validation and escapes input to prevent cross-site scripting
attacks. In practice though they would behave the same in the ways
that matter to us now.
@ -266,7 +277,7 @@ achieve that objective. ~createElement~ will take as input our
JSX-like notation and output a tree of objects compatible with
~render~.
React expects nodes defined as Javascript objects that look like this:
React expects nodes defined as JavaScript objects that look like this:
#+BEGIN_SRC javascript
{

@ -4,31 +4,31 @@ Baking bread. When I first began to learn how to bake bread the recipe told me w
Understanding: that's what I was missing. The bread I make is now consistently good. The recipes I use are simpler and only give ratios and general recommendations for rests and waits. So why does the bread turn out better?
Before baking is finished bread is a living organism. The way it grows and develops and flavors depend on what you feed it and how you feed it and massage it, care for it. If you have it grow and ferment at a higher temperature and more yeast it overdevelops producing too much alcohol. If you give it too much time acidity will take over the flavor. The recipes I used initially were missing a critical ingredient: the rising temperature.
Before baking is finished bread is a living organism. The way it grows and develops and flavors depend on what you feed it and how you feed it and massage it, care for it. If you have it grow and ferment at a higher temperature and more yeast it overdevelops producing too much alcohol. If you give it too much time, acidity will take over the flavor. The recipes I used initially were missing a critical ingredient: the rising temperature.
But unlike a lot of ingredients: temperature is hard to control for the home cook. So the recipe can't just tell you exactly what temperature to grow the bread at. My initial recipes just silently made assumptions for the temperature, which rarely turn out to be true. This means that the only way to consistently make good bread is to have an understanding of how bread develops so that you can adjust the other ingredients to complement the temperature. Now the bread can tell me what to do.
While React isn't technically a living organism that can tell us what to do it is, in its whole, a complex, abstract entity. We could learn basic recipes for how to write high-performance React code but they wouldn't apply in all cases and as React and things under it change our recipes would fall out-of-date. So like the bread, to produce consistently good results we need to understand how React does what it does.
While React isn't technically a living organism that can tell us what to do, it is, in its whole, a complex, abstract entity. We could learn basic recipes for how to write high-performance React code but they wouldn't apply in all cases, and as React and things under it change our recipes would fall out-of-date. So like the bread, to produce consistently good results we need to understand how React does what it does.
## React, made of
## Components of React
Conceptually React is very simple. It starts by walking a tree of components and building up a tree of their output. Then it compares that tree to the tree currently in the browser's DOM to find any differences between them. When it finds differences it updates the browser's DOM to match its internal tree.
But what does that actually look like? If your app is janky does that explanation point you towards what is wrong? No. It might make you wonder if maybe it is too expensive to re-render the tree or if maybe the diffing React does is slow but you won't really know. When I was initially testing out different bread recipes I had guesses at why it wasn't working but I didn't really figure it out until I had a deeper understanding of how making bread worked. It's time we build up our understanding of how React works so that we can start to answer our questions with solid answers.
React is centered around the `render` method. The `render` method is what walks our trees, diffs them with the browser's DOM tree, and updates the DOM as needed. But before we can look at the `render` method me have to understand its input. The input comes from `createElement`. While `createElement` itself is unlikely to be a bottleneck it's a good to understand how it works so that we can have a complete picture of the entire process. The more black-boxes we have in our mental model the harder it will be for us to diagnose performance problems.
React is centered around the `render` method. The `render` method is what walks our trees, diffs them with the browser's DOM tree, and updates the DOM as needed. But before we can look at the `render` method we have to understand its input. The input comes from `createElement`. While `createElement` itself is unlikely to be a bottleneck it's good to understand how it works so that we can have a complete picture of the entire process. The more black-boxes we have in our mental model the harder it will be for us to diagnose performance problems.
## Markup in Javascript: `JSX`
## Markup in JavaScript: `JSX`
`createElement`, however, takes as input something that is probably not familiar to us since we usually work in JSX, which is the last element of the chain in this puzzle and the first step in solving it. While not strictly a part of React it is almost universally used with it. And if we understand it then `createElement` will be less of a mystery since we will be able to connect all the dots.
`createElement`, however, takes as input something that is probably not familiar to us since we usually work in JSX, which is the last element of the chain in this puzzle and the first step in solving it. While not strictly a part of React, it is almost universally used with it. And if we understand it then `createElement` will be less of a mystery since we will be able to connect all the dots.
JSX is not valid HTML or Javascript but its own language compiled by a compiler, like Babel. The output of that compilation is valid Javascript that represents the original markup.
JSX is not valid HTML or JavaScript but its own language compiled by a compiler, like Babel. The output of that compilation is valid JavaScript that represents the original markup.
Before JSX the normal way of injecting HTML into the DOM was via directly utilizing the browser's DOM APIs. This was very cumbersome. The code's structure did not match the structure of the HTML that it output which made it hard to quickly understand what the output of a piece of code would be. So naturally programmers have been endlessly searching for better ways to mix HTML with Javascript.
Before JSX or similar compilers, the normal way of injecting HTML into the DOM was via directly utilizing the browser's DOM APIs or by setting `innerHTML`. This was very cumbersome. The code's structure did not match the structure of the HTML that it output which made it hard to quickly understand what the output of a piece of code would be. So naturally programmers have been endlessly searching for better ways to mix HTML with JavaScript.
And this brings us to JSX. It is nothing new; nothing complicated. Forms of it have been made and used long before React adopted it. Now let's see if we can discover JSX for ourselves.
To start with we need to create a data structure that both represents a DOM tree and can also be used to insert one into the browser's DOM. And to do that we need to understand what a tree of DOM nodes is constructed of. What parts do you see here?
To start with, we need to create a data-structure -- let's call it JavaScript Markup (JSM) -- that both represents a DOM tree and can also be used to insert one into the browser's DOM. And to do that we need to understand what a tree of DOM nodes is constructed of. What parts do you see here?
{format: "html"}
```
@ -40,23 +40,17 @@ To start with we need to create a data structure that both represents a DOM tree
I see three parts: the name of the tag, the tag's properties, and its children.
| name | 'div', 'h1', 'input' |
| props | 'class', 'type', 'disabled' |
| children | <h1>, <input>, Hello |
| Name: | 'div', 'h1', 'input' |
| Props: | 'class', 'type', 'disabled' |
| Children: | <h1>, <input>, Hello |
```
tag name: 'div'
tag prop: 'class'
children: h1..., 'Hello', input...
```
Now how could we recreate that in JavaScript?
Now how could we recreate that in Javascript?
In Javascript we store lists of things in arrays and key/value properties in objects. Luckily for us Javascript even gives us literal syntax for both so we can easily make a compact DOM tree with our own notation.
In JavaScript, we store lists of things in arrays, and key/value properties in objects. Luckily for us, JavaScript even gives us literal syntax for both so we can easily make a compact DOM tree with our own notation.
This is what I'm thinking:
{format: "javascript"}
{format: "javascript", caption: "JSM - JavaScript Markup"}
```
['div', { 'className': 'header' },
[['h1', {}, ['Hello']],
@ -65,15 +59,15 @@ This is what I'm thinking:
]
```
As you can see we have a clear mapping from our notation to the original HTML. Our tree is made up of three element arrays. The first item in the array is the tag, the second is an object containing the tag's properties, and the third is an array of its children; which are all made up of the same three element arrays.
As you can see in, we have a clear mapping from our notation, JSM, to the original HTML. Our tree is made up of three element arrays. The first item in the array is the tag, the second is an object containing the tag's properties, and the third is an array of its children; which are all made up of the same three element arrays.
The truth is though, if you stare at it long enough, although the mapping is clear, how much fun would it be to read and write that on a consistent basis? I can assure you, it is rather not fun. But it has the advantage of being easy to insert into the DOM. All you need to do is write a simple recursive function that ingests our data structure and updates the DOM accordingly. We will get back to this.
So now we have a way to represent a tree of nodes and we (theoretically) have a way to get those nodes into the DOM. But if we are being honest with ourselves, while functional, it isn't a pretty notation nor easy to work with.
And this is where our object of study enters the scene. JSX is just a notation that a compiler takes as input and outputs in its place a tree of nodes nearly identical to the notation we came up with! And if you look back to our notation you can see that you can easily embed arbitrary Javascript expressions wherever you want in a node. As you may have realized, that's exactly what the JSX compiler does when it sees curly braces!
And this is where our object of study enters the scene. JSX is just a notation that a compiler takes as input and outputs in its place a tree of nodes nearly identical to the notation we came up with! And if you look back to our notation you can see that you can easily embed arbitrary JavaScript expressions wherever you want in a node. As you may have realized, that's exactly what the JSX compiler does when it sees curly braces!
There are three main differences between our data structure and the real one that the JSX compiler outputs: it uses objects instead of arrays, it inserts calls to React.createElement on children, and spreads the children instead of containing them in an array. Here is what "real" JSX compiler output looks like:
There are three main differences between our data structure and the real one that the JSX compiler outputs: it uses objects instead of arrays, it inserts calls to React.createElement on children, and spreads the children instead of containing them in an array. Here is what real JSX compiler output looks like:
{format: "javascript"}
```
@ -87,7 +81,7 @@ React.createElement(
);
```
As you can see it is very similar to our data-structure and for the purposes of this book we will use our own simplified data-structure as it's a bit easier to work with. A JSX compiler also does some validation and escapes input to prevent cross-site scripting attacks. In practice though they would behave the same in the ways that matter to us now.
As you can see, it is very similar to our markup data-structure and for the purposes of this book we will use our own simplified data-structure as it's a bit easier to work with. A JSX compiler also does some validation and escapes input to prevent cross-site scripting attacks. In practice though they would behave the same in the ways that matter to us now.
So now that we've worked through JSX we're ready to tackle `createElement`, the next item on our way to building our own React.
@ -95,7 +89,7 @@ So now that we've worked through JSX we're ready to tackle `createElement`, the
React's `render` expects to consume a tree of element objects in a specific, uniform format. `createElement` is the method by which we achieve that objective. `createElement` will take as input our JSX-like notation and output a tree of objects compatible with `render`.
React expects nodes defined as Javascript objects that look like this:
React expects nodes defined as JavaScript objects that look like this:
{format: "javascript"}
```

Loading…
Cancel
Save