<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Anvil Engineering</title>
    <description>The latest articles on Forem by Anvil Engineering (@useanvil).</description>
    <link>https://forem.com/useanvil</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F606097%2Fa0781fad-7430-45b1-bf12-34df4f6b05a9.png</url>
      <title>Forem: Anvil Engineering</title>
      <link>https://forem.com/useanvil</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/useanvil"/>
    <language>en</language>
    <item>
      <title>Converting your vanilla Javascript app to TypeScript</title>
      <dc:creator>Anvil Engineering</dc:creator>
      <pubDate>Mon, 09 May 2022 21:18:12 +0000</pubDate>
      <link>https://forem.com/useanvil/converting-your-vanilla-javascript-app-to-typescript-1bki</link>
      <guid>https://forem.com/useanvil/converting-your-vanilla-javascript-app-to-typescript-1bki</guid>
      <description>&lt;p&gt;The Javascript language has gone through many updates throughout its long (in internet terms) history. Along with its&lt;br&gt;
rapidly changing ecosystem and maturing developer base came attempts to ease some of Javascript’s shortcomings. Of note,&lt;br&gt;
one of the more significant attempts was &lt;a href="https://coffeescript.org/"&gt;CoffeeScript&lt;/a&gt; (initial release in 2009) which adds&lt;br&gt;
syntactic sugar and features that make programming easier.&lt;/p&gt;

&lt;p&gt;In late 2012, TypeScript was publicly released at version&lt;br&gt;
0.8 &lt;sup&gt;&lt;a href="https://en.wikipedia.org/wiki/TypeScript#History"&gt;1&lt;/a&gt; &lt;/sup&gt;. Similar to CoffeeScript, TypeScript attempted to&lt;br&gt;
add more features onto Javascript. The biggest feature TypeScript brought to the table, as its name implies, was types.&lt;br&gt;
Types, and all other features that build on top of types such as generics, were already enjoyed by developers on other&lt;br&gt;
languages like Java and C#, but this felt like the start of something big for Javascript.&lt;/p&gt;

&lt;p&gt;Fast-forward to 2016 – the first time TypeScript is mentioned&lt;br&gt;
on &lt;a href="https://insights.stackoverflow.com/survey/2016"&gt;Stack Overflow’s Developer Survey&lt;/a&gt;. In 2016, a whopping 0.47% of&lt;br&gt;
survey respondents have used TypeScript. Skipping ahead two more years&lt;br&gt;
to &lt;a href="https://insights.stackoverflow.com/survey/2018#technology"&gt;the 2018 survey&lt;/a&gt; and TypeScript jumps to 17.4% of&lt;br&gt;
respondents using TypeScript. You probably get where this is heading now. In&lt;br&gt;
the &lt;a href="https://insights.stackoverflow.com/survey/2021"&gt;most recent survey (2021)&lt;/a&gt; TypeScript jumped to 30.19%, even moving&lt;br&gt;
past languages like C# and PHP. This is definitely a sign that TypeScript is something to pay attention to and maybe&lt;br&gt;
your vanilla Javascript app could use a little makeover.&lt;/p&gt;

&lt;p&gt;This post will go through an example TODO app repo we’ve set up&lt;br&gt;
here: &lt;a href="https://github.com/anvilco/anvil-ts-upgrade-example"&gt;https://github.com/anvilco/anvil-ts-upgrade-example&lt;/a&gt;. This repo is in plain vanilla Javascript and runs on Node.js&lt;br&gt;
and uses Express. There are some basic tests included, but it’s as simple as can be. We will go through a few strategies&lt;br&gt;
that one can take when attempting to migrate to using TypeScript from Javascript.&lt;/p&gt;

&lt;p&gt;This post will not go through TypeScript programming concepts in depth and will only gloss over them briefly since those&lt;br&gt;
are huge chunks of information themselves. The&lt;br&gt;
official &lt;a href="https://www.typescriptlang.org/docs/handbook/intro.html"&gt;TypeScript Handbook&lt;/a&gt; is a great resource if you want&lt;br&gt;
to learn more.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 0
&lt;/h2&gt;

&lt;p&gt;Before starting, it’s important to know our starting point with our app’s functionality. We need tests. If you don’t&lt;br&gt;
have any, it’s worth it to at least create a few tests for happy path tests: that is, tests that do the simplest “good”&lt;br&gt;
thing.&lt;/p&gt;

&lt;p&gt;Also worth mentioning before you start: have your code on a versioning system (i.e. git). A lot of files are likely to&lt;br&gt;
change and you’ll want an easy way to undo everything.&lt;/p&gt;
&lt;h2&gt;
  
  
  Install TypeScript
&lt;/h2&gt;

&lt;p&gt;Simple enough. Let’s get started:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--save-dev&lt;/span&gt; typescript
&lt;span class="c"&gt;# or &lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add &lt;span class="nt"&gt;--dev&lt;/span&gt; typescript
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;TypeScript is a superset of Javascript, so any valid Javascript program is also a valid TypeScript&lt;br&gt;
program &lt;sup&gt;&lt;a href="https://en.wikipedia.org/wiki/TypeScript"&gt;2&lt;/a&gt; &lt;/sup&gt;. Essentially, if we run our code through the TypeScript&lt;br&gt;
compiler &lt;code&gt;tsc&lt;/code&gt; (which is provided when you install &lt;code&gt;typescript&lt;/code&gt; above) without any major problems, we should be good to&lt;br&gt;
go!&lt;/p&gt;
&lt;h3&gt;
  
  
  tsconfig.json
&lt;/h3&gt;

&lt;p&gt;After installing, we also need to set up a basic &lt;code&gt;tsconfig.json&lt;/code&gt; file for how we want &lt;code&gt;tsc&lt;/code&gt; to behave with our app. We&lt;br&gt;
will use one of the recommended &lt;code&gt;tsconfig&lt;/code&gt; files&lt;br&gt;
here: &lt;a href="https://github.com/tsconfig/bases#centralized-recommendations-for-tsconfig-bases"&gt;https://github.com/tsconfig/bases#centralized-recommendations-for-tsconfig-bases&lt;/a&gt;. This contains a list of&lt;br&gt;
community recommended configs depending on your app type. We’re using Node 16 and want to be extremely strict on the&lt;br&gt;
first pass to clean up any bad code habits and enforce some consistency. We’ll use the one&lt;br&gt;
located: &lt;a href="https://github.com/tsconfig/bases/blob/main/bases/node16-strictest.combined.json"&gt;https://github.com/tsconfig/bases/blob/main/bases/node16-strictest.combined.json&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"display"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Node 16 + Strictest"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="s2"&gt;"es2021"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"module"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"commonjs"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"target"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"es2021"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"strict"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"esModuleInterop"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"skipLibCheck"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"forceConsistentCasingInFileNames"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowUnusedLabels"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowUnreachableCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"exactOptionalPropertyTypes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noFallthroughCasesInSwitch"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noImplicitOverride"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noImplicitReturns"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noPropertyAccessFromIndexSignature"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noUncheckedIndexedAccess"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noUnusedLocals"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"noUnusedParameters"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"importsNotUsedAsValues"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"checkJs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Everything&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;below&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;are&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;custom&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;changes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;this&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;app&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"allowJs"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"outDir"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dist"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"include"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"./src/**/*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"./__tests__/**/*"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Compile and fix errors
&lt;/h2&gt;

&lt;p&gt;Now let’s run &lt;code&gt;tsc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn tsc
&lt;span class="c"&gt;# or &lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;npx tsc
Found 68 errors &lt;span class="k"&gt;in &lt;/span&gt;5 files.

Errors  Files
    13  __tests__/app.test.js:1
    28  __tests__/store.test.js:3
    14  src/app.js:1
     1  src/models/Todo.js:4
    12  src/store.js:13
error Command failed with &lt;span class="nb"&gt;exit &lt;/span&gt;code 2.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;68 errors. Not too bad especially with extremely strict rules on. Many of the errors are “implicitly has an 'any' type”&lt;br&gt;
and should have easy fixes.&lt;/p&gt;

&lt;p&gt;Aside from those, there are a few interesting errors:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;src/app.js:1:25 - error TS7016: Could not find a declaration file &lt;span class="k"&gt;for &lt;/span&gt;module &lt;span class="s1"&gt;'express'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'anvil-ts-upgrade-example/node_modules/express/index.js'&lt;/span&gt; implicitly has an &lt;span class="s1"&gt;'any'&lt;/span&gt; type.
  Try &lt;span class="sb"&gt;`&lt;/span&gt;npm i &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @types/express&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;it exists or add a new declaration &lt;span class="o"&gt;(&lt;/span&gt;.d.ts&lt;span class="o"&gt;)&lt;/span&gt; file containing &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;declare &lt;/span&gt;module &lt;span class="s1"&gt;'express'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;

1 const express &lt;span class="o"&gt;=&lt;/span&gt; require&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'express'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                          ~~~~~~~~~

src/app.js:2:28 - error TS7016: Could not find a declaration file &lt;span class="k"&gt;for &lt;/span&gt;module &lt;span class="s1"&gt;'body-parser'&lt;/span&gt;&lt;span class="nb"&gt;.&lt;/span&gt; &lt;span class="s1"&gt;'anvil-ts-upgrade-example/node_modules/body-parser/index.js'&lt;/span&gt; implicitly has an &lt;span class="s1"&gt;'any'&lt;/span&gt; type.
  Try &lt;span class="sb"&gt;`&lt;/span&gt;npm i &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @types/body-parser&lt;span class="sb"&gt;`&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;it exists or add a new declaration &lt;span class="o"&gt;(&lt;/span&gt;.d.ts&lt;span class="o"&gt;)&lt;/span&gt; file containing &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;declare &lt;/span&gt;module &lt;span class="s1"&gt;'body-parser'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;

2 const bodyParser &lt;span class="o"&gt;=&lt;/span&gt; require&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'body-parser'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
                             ~~~~~~~~~~~~~
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These error messages tell us how to fix the errors and also point to how parts of the typing system works in TypeScript.&lt;br&gt;
Packages can provide typing declarations (with the *.d.ts file extension). These are generated automatically through&lt;br&gt;
the &lt;code&gt;tsc&lt;/code&gt; compiler. If you have a publicly accessible TypeScript app, you can also provide official typing declarations&lt;br&gt;
by submitting a pull request to the DefinitelyTyped repo: &lt;a href="https://github.com/DefinitelyTyped/DefinitelyTyped"&gt;https://github.com/DefinitelyTyped/DefinitelyTyped&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The two packages in the snippet are very popular modules, so they’ll definitely have type declarations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# We’re also adding in type declarations for modules used in testing: supertest, jest&lt;/span&gt;
npm i &lt;span class="nt"&gt;--save-dev&lt;/span&gt; @types/body-parser @types/express @types/supertest @types/jest
&lt;span class="c"&gt;# or&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; @types/body-parser @types/express @types/supertest @types/jest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let’s check on &lt;code&gt;tsc&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Found 15 errors &lt;span class="k"&gt;in &lt;/span&gt;3 files.

Errors  Files
     2  src/app.js:13
     1  src/models/Todo.js:4
    12  src/store.js:13
error Command failed with &lt;span class="nb"&gt;exit &lt;/span&gt;code 2.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From 68 errors to 15. That’s much more manageable. The rest of the errors should now be actually related to our own&lt;br&gt;
code. Let’s take the one that repeats the most:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;src/store.js:28:16 - error TS7053: Element implicitly has an &lt;span class="s1"&gt;'any'&lt;/span&gt; &lt;span class="nb"&gt;type &lt;/span&gt;because expression of &lt;span class="nb"&gt;type&lt;/span&gt; &lt;span class="s1"&gt;'any'&lt;/span&gt; can&lt;span class="s1"&gt;'t be used to index type '&lt;/span&gt;&lt;span class="o"&gt;{}&lt;/span&gt;&lt;span class="s1"&gt;'.

28     let item = localStore?.[id]
                  ~~~~~~~~~~~~~~~~
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What does this mean? Our &lt;code&gt;localStore&lt;/code&gt; variable is an Object, but its key type is &lt;code&gt;any&lt;/code&gt;. In strict TypeScript, we need to&lt;br&gt;
be clear what our indexes can be. In this case we use numbers as indexes.&lt;/p&gt;

&lt;p&gt;Before we fix this, let’s change our file’s extension to the &lt;code&gt;*.ts&lt;/code&gt;:  &lt;code&gt;store.js -&amp;gt; store.ts&lt;/code&gt;. This will let &lt;code&gt;tsc&lt;/code&gt; know&lt;br&gt;
this is a TypeScript file, as well as our IDE. Now we start actually writing TypeScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;LocalAppStore&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;TodoModel&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;localStore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;LocalAppStore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We’ve created our first interface. It tells the TypeScript compiler what a &lt;code&gt;LocalAppStore&lt;/code&gt; object looks like with its&lt;br&gt;
keys as numbers and its values as a &lt;code&gt;TodoModel&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We also need to create a new interface &lt;code&gt;TodoData&lt;/code&gt; which defines the object we pass to create and update &lt;code&gt;Todo&lt;/code&gt;&lt;br&gt;
instances.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/models/Todo.ts  (renamed from Todo.js)&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;TodoData&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can then import that interface and use it as type annotations throughout the app.&lt;/p&gt;

&lt;p&gt;Without getting too verbose and explaining all the other smaller errors, you can take a look at the branch we have here&lt;br&gt;
to see what changed: &lt;a href="https://github.com/anvilco/anvil-ts-upgrade-example/tree/ts-convert"&gt;https://github.com/anvilco/anvil-ts-upgrade-example/tree/ts-convert&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In summary, after installing TypeScript and creating its config file we:&lt;br&gt;
Get &lt;code&gt;tsc&lt;/code&gt; to run without failing – not including errors it finds in our code Look for any missing type declarations. In&lt;br&gt;
this case we were missing types from jest, express, body-parser, and supertest. Rename files from &lt;code&gt;.js&lt;/code&gt;  to &lt;code&gt;.ts&lt;/code&gt;&lt;br&gt;
Fix errors by creating type aliases or interfaces, adding type annotations, etc. This can potentially take the most time&lt;br&gt;
as you’ll need to take a look at how functions are used, how and what kind of data is passed.&lt;/p&gt;

&lt;p&gt;One thing to keep in mind is that the migration process to TypeScript can be done at your own pace. Since valid&lt;br&gt;
Javascript is also valid TypeScript, you don’t have to rename all files to &lt;code&gt;.ts&lt;/code&gt;. You don’t have to create type&lt;br&gt;
interfaces for all objects until you’re ready. Using a less-strict &lt;code&gt;tsconfig.json&lt;/code&gt;&lt;br&gt;
file (&lt;a href="https://github.com/tsconfig/bases/blob/main/bases/node16.json"&gt;https://github.com/tsconfig/bases/blob/main/bases/node16.json&lt;/a&gt;), together with &lt;code&gt;// @ts-ignore&lt;/code&gt; comments to ignore&lt;br&gt;
errors you don’t agree with or maybe aren’t ready for yet.&lt;/p&gt;
&lt;h2&gt;
  
  
  After compiling
&lt;/h2&gt;

&lt;p&gt;After &lt;code&gt;tsc&lt;/code&gt; finally compiles your project, you may need to adjust your &lt;code&gt;package.json&lt;/code&gt; file. In our &lt;code&gt;package.json&lt;/code&gt; we&lt;br&gt;
have:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "main": "src/server.js",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;which now points to a file that doesn’t exist. Since this should point to a Javascript file, we need to update this to&lt;br&gt;
point to the compiled version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  "main": "dist/server.js",
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that you will need to compile your app code every time your entry point needs to be updated. This can be done&lt;br&gt;
automatically as you develop with packages such as &lt;a href="https://www.npmjs.com/package/tsc-watch"&gt;tsc-watch&lt;/a&gt;&lt;br&gt;
and &lt;a href="https://www.npmjs.com/package/nodemon"&gt;nodemon&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also see if the compiled version of the app runs manually through a command like &lt;code&gt;node dist/server.js&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  IDE Support
&lt;/h2&gt;

&lt;p&gt;One of the major side effects from migrating to TypeScript, if you use a supported IDE such as Visual Studio Code or one&lt;br&gt;
of the JetBrains IDEs, is better integration with the IDE. This includes, but isn’t limited to, better autocomplete and&lt;br&gt;
better popup hints for function types (see image below). This brings the language much closer to typed, compiled&lt;br&gt;
languages like C# and Java.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VV7lJghb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ds4c3jhnczdgf79nhkf9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VV7lJghb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ds4c3jhnczdgf79nhkf9.png" alt="IDE Support" width="494" height="310"&gt;&lt;/a&gt;(./ide-support.png)&lt;/p&gt;

&lt;h2&gt;
  
  
  Other tooling
&lt;/h2&gt;

&lt;p&gt;This post has only covered a very narrow migration case involving a basic Node.js app and a few unit tests. Real&lt;br&gt;
applications are much more complex than this and would involve other transpilers and builders such as webpack, rollup,&lt;br&gt;
and babel. Adding TypeScript to those build processes would be separate blog posts themselves, but I believe the general&lt;br&gt;
advice here is still 100% applicable in complex situations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Migrating an app to another platform or language is never easy. Fortunately, if you want to migrate your vanilla&lt;br&gt;
Javascript app to TypeScript, it can be done progressively, as fast or as slow as you want. Additionally, the TypeScript&lt;br&gt;
compiler can be configured to provide as much feedback as we need throughout the process to ensure your code runs.&lt;br&gt;
Hopefully this post has inspired you to at least think about the possibility of migrating your Javascript app.&lt;/p&gt;

&lt;p&gt;At Anvil, we’ve begun migrating some of our public projects to TypeScript as well. So far it’s been painless and fairly&lt;br&gt;
straightforward. If you're developing something cool with our libraries or paperwork automation, let us know at&lt;br&gt;
&lt;a href="mailto:developers@useanvil.com"&gt;developers@useanvil.com&lt;/a&gt;. We'd love to hear from you.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>typescript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Measuring React styled-components performance &amp; best practices</title>
      <dc:creator>Anvil Engineering</dc:creator>
      <pubDate>Thu, 05 May 2022 21:56:46 +0000</pubDate>
      <link>https://forem.com/useanvil/measuring-react-styled-components-performance-best-practices-2ggb</link>
      <guid>https://forem.com/useanvil/measuring-react-styled-components-performance-best-practices-2ggb</guid>
      <description>&lt;p&gt;Nothing feels worse to a new user than having to navigate across a slow-performing webapp. Nine out of ten times, I hit 'back' on a webpage once I realize a page is rendering excruciatingly slow. Webapp performance is one of the most important components of user experience, and that is why search engines take into account website metrics such as 'first contentful paint' or 'time to interactive' when ranking.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xk4k0vzkr56g4ataa6x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6xk4k0vzkr56g4ataa6x.png" alt="Lighthouse metrics"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Lighthouse metrics for an example webpage&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I'll assume you already have some working knowledge on what styled-components is and how it works. But just in case, styled-components is one of the most popular open-source styling libraries, especially in the React ecosystem. Instead of applying styles to an entire webpage or specific HTML elements using the class/id system, you can apply styles onto individual React components. One of my favorite aspects of the styled-components approach is it neatly blends together logic &amp;amp; styling – JS, HTML, and CSS – so everything is accessible from just one file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;StyledButton&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt;&lt;span class="s2"&gt;`
  font-size: 14px;
  color: #525252;
  background-color: #7AEFB2;
  border-color: transparent;
`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ButtonComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;isLoading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;StyledButton&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt;&lt;span class="nx"&gt;example&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;btn&lt;/span&gt;&lt;span class="err"&gt;”&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isLoading&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;LoadingSpinner&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/StyledButton&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;ButtonComponent&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example styled component button in React&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now that we've covered the background, let's ask the important questions. How can we gauge how well our styled-components are performing? What metrics should we look out for? And what are some best practices we can implement to keep our code efficient? &lt;/p&gt;

&lt;h2&gt;
  
  
  Measuring performance
&lt;/h2&gt;

&lt;p&gt;We'll be using Chrome DevTools' Performance Monitor to gauge a page's performance in real time. It will appear like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzuicp2bpgq5d0f7wx58i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzuicp2bpgq5d0f7wx58i.png" alt="Performance monitor"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Chome DevTools performance monitor&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Navigate to the page containing your code, open up the performance monitor, press record, perform an action, and stop recording. You'll see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vses2mu3r02eedn0v3r.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vses2mu3r02eedn0v3r.png" alt="Performance timeline &amp;amp; summary"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Performance timeline &amp;amp; summary&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Looking at the summary, we can see scripting takes up the majority of the recording time – 1904ms out of 2880ms. It appears we can make the most significant improvements in this department. Let's dive further by clicking into the 'Bottom-up' tab.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqz5itjs3w7a79ps514h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feqz5itjs3w7a79ps514h.png" alt="Performance bottom-up tab"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Performance Bottom-up tab&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The 'insertBefore' scripting activity takes 364.4ms – the longest of any process. Let's figure out where this code comes from.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F87pjhe7k679q5z8gdk2f.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F87pjhe7k679q5z8gdk2f.png" alt="Performance bottom-up tab details"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;&lt;code&gt;insertBefore&lt;/code&gt; subfolders&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The code with the greatest 'Self time' comes from styled-components. Now that we've identified where the problem lies, let's fix it by making our code more efficient.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;To learn more about using the DevTools performance monitor, check out &lt;a href="https://www.useanvil.com/blog/engineering/improve-optimize-react-render-performance-part-1/" rel="noopener noreferrer"&gt;this blog post about optimizing render performance&lt;/a&gt;!&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Best practices
&lt;/h2&gt;

&lt;p&gt;The first step in code optimization is to examine the way our code is structured. Let's take a look at some of those best practices for styled-components.&lt;/p&gt;
&lt;h3&gt;
  
  
  Dynamic styling
&lt;/h3&gt;

&lt;p&gt;Oftentimes we want the styling of a UI component to be dependent upon some logic or state in the application. For example, we may want the background of a div to be gray when being hovered over. We can achieve this by applying dynamic styling.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="s2"&gt;`
  background: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isHover&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#E2EEF0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#FFFFFF&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example of dynamic styling - div with light cyan background upon hover&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;What if we want multiple dynamic styles to be applied? It could look quite repetitive.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="s2"&gt;`
  color: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isSelected&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#2D2D2D&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#7A7A7A&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
  border-radius: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isSelected&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;4px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;0px&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
  background: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isHover&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#E2EEF0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#FFFFFF&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;;
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Multiple dynamic styles - the 'meh' way&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's clean up our code by importing the props once for each prop instead of doing it on a per-line basis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="s2"&gt;`
  color: #7A7A7A;
  border-radius: 0px;
  background: #FFFFFF;

  &lt;/span&gt;&lt;span class="p"&gt;${({&lt;/span&gt; &lt;span class="nx"&gt;isSelected&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;isSelected&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;`
    color: #2D2D2D;
    border-radius: 4px;
  `&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;${({&lt;/span&gt; &lt;span class="nx"&gt;isHover&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;isHover&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;`
    background: #E2EEF0;
  `&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Multiple dynamic styles - the okay way&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Having a bunch of dynamic styles can quickly get complicated. Let's imagine we have a styled-component that takes a 'displayStyle' prop that applies various combinations of CSS. Like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;StyledInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="s2"&gt;`
  font-size: 14px;
  border-radius: 2px;

  &lt;/span&gt;&lt;span class="p"&gt;${({&lt;/span&gt;  &lt;span class="nx"&gt;displayStyle&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;displayStyle&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;compact&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;`
    border-top: none;
    border-left: none;
    border-right: none;
    padding-top: 0;
    padding-left: 0;
    padding-right: 0;
    margin-left: 0;
    margin-right: 0;
    font-size: 12px;
    box-shadow: none;
  `&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;${({&lt;/span&gt; &lt;span class="nx"&gt;displayStyle&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;displayStyle&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;internal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;`
    border: none;
    margin-left: 0;
    margin-right: 0;
    font-weight: bold;
  `&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;

  &lt;/span&gt;&lt;span class="p"&gt;${({&lt;/span&gt; &lt;span class="nx"&gt;displayStyle&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;displayStyle&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;large&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="s2"&gt;`
    border: 2px;
    margin-left: 10px;
    margin-right: 10px;
    font-size: 22px;
  `&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
  …
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Another example of multiple dynamic styles - the okay way&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;It can get quite confusing to track all the CSS rules when there are a bunch of different display styles. We can compartmentalize everything by creating distinct styled-components for each display style.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;StyledInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="s2"&gt;`
  font-size: 14px;
  border-radius: 2px;
`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;CompactInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;StyledInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;`
  border-top: none;
  border-left: none;
  border-right: none;
  padding-top: 0;
  padding-left: 0;
  padding-right: 0;
  margin-left: 0;
  margin-right: 0;
  font-size: 12px;
  box-shadow: none;
`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;InternalInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;StyledInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;`
  border: none;
  margin-left: 0;
  margin-right: 0;
  font-weight: bold;
`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;LargeInput&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;StyledInput&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;`
  border: 2px;
  margin-left: 10px;
  margin-right: 10px;
  font-size: 22px;
`&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Input&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;displayStyle&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;InputComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;StyledInput&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;displayStyle&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;compact&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;InputComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;CompactInput&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;displayStyle&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;internal&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;InputComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;InternalInput&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;displayStyle&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;large&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;InputComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;LargeInput&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InputComponent&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Multiple dynamic styles - the cleanest way&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;By adopting this improved format of structuring your styled-components, I hope you'll see some improvement in performance.&lt;/p&gt;

&lt;h3&gt;
  
  
  Global styles
&lt;/h3&gt;

&lt;p&gt;Styled-components has a helper function named &lt;a href="https://styled-components.com/docs/api#createglobalstyle" rel="noopener noreferrer"&gt;&lt;code&gt;createGlobalStyle&lt;/code&gt;&lt;/a&gt; which generates a special component that handles global styles. The function works by creating a HTML style tag. Whenever a React component with &lt;code&gt;createGlobalStyle&lt;/code&gt; is mounted, &lt;code&gt;createGlobalStyle&lt;/code&gt; is called and a new style tag is generated. Using the helper function with a React component that is mounted &amp;amp; unmounted frequently will lead to redundant style tags in the DOM, so it is best to minimize the number of times the function is used.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;DropdownGlobalStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createGlobalStyle&lt;/span&gt;&lt;span class="s2"&gt;`
  .selected-option {
    background-color: #3E3E57;
  }
`&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Dropdown&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="err"&gt;…&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;DropdownGlobalStyle&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;InputGlobalStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createGlobalStyle&lt;/span&gt;&lt;span class="s2"&gt;`
  .error-container {
    color: #FB7578;
  }
`&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;Input&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="err"&gt;…&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;InputGlobalStyle&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Using &lt;code&gt;createGlobalStyle&lt;/code&gt; for multiple components - the bad way&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Let's create global styles once only in the App component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;AppGlobalStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;createGlobalStyle&lt;/span&gt;&lt;span class="s2"&gt;`
  .selected-option {
    background-color: #3E3E57;
  }

  .error-container {
    color: #FB7578;
  }
`&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="err"&gt;…&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AppGlobalStyle&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Using &lt;code&gt;createGlobalStyle&lt;/code&gt; once in the root component - the better way&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;We've covered how to measure the performance of your styled-components and best practices on structuring your code. By implementing these techniques into your development process, you can worry less about having a slow-performing web app!&lt;/p&gt;

&lt;p&gt;We've applied these practices to our code at Anvil, and believe sharing our experience helps everyone in creating awesome products. If you're developing something cool with PDFs or paperwork automation, let us know at &lt;a href="//mailto:developers@useanvil.com"&gt;developers@useanvil.com&lt;/a&gt;. We'd love to hear from you.&lt;/p&gt;

</description>
      <category>react</category>
      <category>tutorial</category>
      <category>html</category>
      <category>css</category>
    </item>
    <item>
      <title>Introducing SpectaQL 1.0 - an even better way to autogenerate GraphQL API documentation</title>
      <dc:creator>Anvil Engineering</dc:creator>
      <pubDate>Tue, 03 May 2022 22:42:38 +0000</pubDate>
      <link>https://forem.com/useanvil/introducing-spectaql-10-an-even-better-way-to-autogenerate-graphql-api-documentation-32cg</link>
      <guid>https://forem.com/useanvil/introducing-spectaql-10-an-even-better-way-to-autogenerate-graphql-api-documentation-32cg</guid>
      <description>&lt;p&gt;Back in March 2021, Anvil released SpectaQL to the open source community with the goal of becoming the de-facto, go-to library to use for auto-generating static HTML documentation for any GraphQL API. So far we're very pleased with the progress we've made:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It gets downloaded thousands of times per week on &lt;a href="https://www.npmjs.com/package/spectaql"&gt;NPM&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;It has over 500 stars on &lt;a href="https://github.com/anvilco/spectaql"&gt;Github&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;It has a healthy amount of user support and Github issue activity&lt;/li&gt;
&lt;li&gt;There have been several articles written about it, like &lt;a href="https://blog.graphqleditor.com/spectaql"&gt;this one&lt;/a&gt; and &lt;a href="https://stepzen.com/blog/creating-static-documentation-for-graphql-apis-using-graphql-sdl"&gt;this one&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Despite the success of SpectaQL over the last year or so, it was still in a "pre 1.0" stage as we learned more and more about what worked well, heard from users about what they wanted, and of course fixed a whole bunch of bugs. After all that time, feedback, and thought we decided that it was time to devote some resources to make a major internal overhaul, improve some existing features and APIs, and create or expose some new features and APIs that prepare SpectaQL for the future. We are happy to announce the culmination of all that work with the release of SpectaQL 1.0!&lt;/p&gt;

&lt;p&gt;In the rest of this article, I'm going to outline some of the major changes, enhancements, and new features, as well as the decision process around some of the things we've done. I hope you find it informative and interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why did we decide to do it? And why now?
&lt;/h2&gt;

&lt;p&gt;In order to increase their reliability and usefulness, most open source projects, and especially libraries and packages, follow the Semantic Versioning (aka &lt;a href="https://semver.org/"&gt;Semver&lt;/a&gt;) specification. Perhaps the most important takeaway from Semver is that if you make any "breaking changes" to your library, you should release those changes as a new Major version—e.g. go from &lt;code&gt;1.x.x =&amp;gt; 2.0.0&lt;/code&gt;. While the possibility of breaking changes without a major version change was something I warned users about while SpectaQL was on version &lt;code&gt;0.x.x&lt;/code&gt;, I was still hesitant to cause any breaking changes due to the amount of usage the package was getting.&lt;/p&gt;

&lt;p&gt;As a developer who uses open source packages myself, I know that upgrading package dependencies by a "patch" or "minor" amount is usually no big deal, but that upgrading a package by a "major" amount is something that requires careful consideration and oftentimes some (major) code changes and real work. For this reason, I wanted to be careful about introducing breaking changes too often, so I waited for more understanding.&lt;/p&gt;

&lt;p&gt;After what felt like enough experience, feedback, discussion, thought, and research there ended up being many things that I wanted to change about SpectaQL that would be considered "breaking changes." That time and perspective also allowed me to be more confident that the APIs and ergonomics of the changes I wanted to make would prove to be smart and complete enough to avoid having to make any breaking changes for some time. And so I began developing SpectaQL &lt;code&gt;1.0&lt;/code&gt;. &lt;a href="https://github.com/anvilco/spectaql/blob/main/BREAKING_CHANGES_1.md"&gt;Here is&lt;/a&gt; a somewhat exhaustive list of the "breaking changes" intended to help users migration from &lt;code&gt;0.x.x&lt;/code&gt; to &lt;code&gt;1.0.0&lt;/code&gt;. I'll focus the rest of this article on some of the major and more interesting parts of this work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Internal DNA based on JSON Schema and Swagger/OpenAPI
&lt;/h2&gt;

&lt;p&gt;SpectaQL was originally forked from a project called &lt;a href="https://github.com/wayfair/dociql"&gt;DociQL&lt;/a&gt; to add some enhancements there. And DociQL was originally forked from a project called &lt;a href="https://github.com/sourcey/spectacle"&gt;Spectacle&lt;/a&gt; to make it work with GraphQL. And (finally) Spectacle was designed to work with &lt;a href="https://swagger.io/resources/open-api/"&gt;Swagger/OpenAPI&lt;/a&gt;. Swagger/OpenAPI is a specification designed to help standardize the description of REST APIs with many routes, and uses JSON Schema as the way to define Data Types/Models. This means that SpectaQL had to wrestle with several layers of history and transformations; making SpectaQL's enhancements fit into the DociQL world, which in turn had to make things fit into the Spectacle/Swagger/OpenAPI world.&lt;/p&gt;

&lt;p&gt;This presented many challenges, but there were a few in particular that made things feel like they were really trying to fit a round peg into a square hole:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Unlike REST APIs, GraphQL does not have many different endpoints or paths to represent. It usually has just 1 which accepts any valid Queries or Mutations.&lt;/li&gt;
&lt;li&gt;GraphQL already has a Schema definition and strict Typing built into the language, so conversion to JSON Schema felt unnecessary.&lt;/li&gt;
&lt;li&gt;GraphQL already had a number of tools to work with and interact with schemas in useful and interesting ways.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are just a few of the big ones, but there were other reasons as well, and eventually it became clear that all signs pointed to re-writing SpectaQL's internals to use pure GraphQL tools—no more Swagger/OpenAPI, and no more JSON Schema. The responses and comments on this &lt;a href="https://github.com/anvilco/spectaql/issues/111"&gt;issue&lt;/a&gt;  I opened up confirmed my feelings.&lt;/p&gt;

&lt;p&gt;This re-writing of the internals took up the bulk of the time to get SpectaQL 1.0 ready, and in the end, provided little-to-no immediate User-facing changes. However, it was well worth the trouble as it dramatically simplified the codebase, making it much easier to make other changes and enhancements. Things that used to take a great deal of experience in and understanding of the codebase can now be easily understood and figured out by a much more casual observer of the code. This has already been proven by receiving pull requests from users wanting to fix bugs or add new features with just a few intuitive lines of code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Simpler schema manipulation, and the creation of Microfiber
&lt;/h2&gt;

&lt;p&gt;One major feature of SpectaQL is its ability to filter (or "hide") things in your GraphQL schema that you don't want documented. Most schemas have at least a few Types, Queries, or Mutations that are for administrators only, or that are sensitive for various reasons. We put a lot of effort into making this possible for the original launch of SpectaQL, but as time went on it became increasingly challenging to implement complex logic. For example, if you tell SpectaQL to hide your custom type &lt;code&gt;Foo&lt;/code&gt;, you probably also want to hide all references to &lt;code&gt;Foo&lt;/code&gt;: Queries or Mutations that return &lt;code&gt;Foo&lt;/code&gt;, fields that return &lt;code&gt;Foo&lt;/code&gt;, arguments of type &lt;code&gt;Foo&lt;/code&gt;, etc. This was very tricky to do in the old system.&lt;/p&gt;

&lt;p&gt;After starting from scratch with a purely GraphQL mindset and landscape, these sorts of advanced manipulations became much easier to reason about and implement. Since there was no existing tool for it, we ended up creating a standalone package just for querying and manipulating the GraphQL schema in the ways that we needed. We then decided that others might find this tool useful, so we recently open sourced it as &lt;a href="https://github.com/anvilco/graphql-introspection-tools"&gt;Microfiber&lt;/a&gt;. You can read my blog post about its release &lt;a href="https://www.useanvil.com/blog/engineering/manipulate-graphql-schemas-with-microfiber"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Increase customizabilty and reduce forking via "themes"
&lt;/h2&gt;

&lt;p&gt;By far the biggest user-facing changes that were made for SpectaQL 1.0 were around allowing for customization. In the pre-1.0 world, there was a limited, difficult, disjointed set of ways to customize the CSS, JavaScript, and output. Even worse, there was no real way to customize the data arrangement / grouping or to really control the HTML structure. All of these shortcomings would either leave some users frustrated, or perhaps looking elsewhere for another solution for them. Even worse than a user deciding not to use SpectaQL would be having a user need to fork the project in order to make the changes they need. Forking, we reasoned, was a sign that we'd not given enough flexibility and power to the users. With all of this in mind, we decided that the goal of our customization system in SpectaQL would be to reduce the need to fork the project in order to get any sort of reasonable customization that a user might want.&lt;/p&gt;

&lt;p&gt;We accomplished this through the creation of a "theme" system that gives users the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complete control of the HTML templates (SpectaQL uses Handlebars) to render any DOM structure you like.&lt;/li&gt;
&lt;li&gt;Complete control over the SCSS/CSS supplied along with your HTML.&lt;/li&gt;
&lt;li&gt;Complete control over the JavaScript files that are loaded with your HTML.&lt;/li&gt;
&lt;li&gt;Complete control over the GraphQL data that gets passed to the HTML template engines, allowing you to group, order, and arrange the data however you like.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Some other cool things to note about themes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;SpectaQL comes with 3 built-in themes to choose from.&lt;/li&gt;
&lt;li&gt;User-created theme files and structure will be overlaid on top of the default theme files and structure so that the theme only needs to contain files that are supplemental or that should be overwritten in the default theme. This makes it easy for the user to provide minor tweaks to the default theme without a lot of code and without missing out on any future updates and bug fixes made to the original/underlying theme.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're interested in learning more about SpectaQL's theming system, please check out &lt;a href="https://github.com/anvilco/spectaql#customizing-css-js-html-and-data-arrangement-via-themes"&gt;the docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;While SpectaQL owes a great deal to its original DNA, over time some of that legacy code became a hindrance. Converting GraphQL to Swagger/OpenAPI was tough to reason about and follow. Converting GraphQL to JSON Schema also provided challenges. A "feel good" way to support customizing all aspects of the output was also just not there. Over time, it became clear that some old patterns were not necessary, and that things would be a lot better off after a major refactoring. Time, feedback, and research were also necessary before being able to design and implement a robust customization system via "themes."&lt;/p&gt;

&lt;p&gt;The big takeaway? While you don't want to be hasty and end up rolling out major breaking changes too frequently, you should also not be afraid to act once you feel you've gathered enough understanding and a critical mass of things that need to change for the project to succeed. For SpectaQL, this was a major investment of time and effort but already it has borne much fruit. We feel confident that we made the right decisions and have set up SpectaQL for long-term success. Happy coding!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
      <category>javascript</category>
      <category>css</category>
    </item>
    <item>
      <title>PurgeCSS &amp; styled-components: Does It Work?</title>
      <dc:creator>Anvil Engineering</dc:creator>
      <pubDate>Fri, 29 Apr 2022 22:53:56 +0000</pubDate>
      <link>https://forem.com/useanvil/purgecss-styled-components-does-it-work-4i0g</link>
      <guid>https://forem.com/useanvil/purgecss-styled-components-does-it-work-4i0g</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6u4gi9oqctz2xv3dfo68.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6u4gi9oqctz2xv3dfo68.png" alt="Image description"&gt;&lt;/a&gt;While CSS itself is ubiquitous, the way each project uses it is certainly not. Before preprocessors like &lt;a href="https://sass-lang.com/" rel="noopener noreferrer"&gt;Sass&lt;/a&gt; and &lt;a href="https://lesscss.org/" rel="noopener noreferrer"&gt;Less&lt;/a&gt;, there were entire methodologies, like &lt;a href="http://getbem.com/" rel="noopener noreferrer"&gt;BEM&lt;/a&gt;, for writing and maintaining your CSS. Even with methodologies and preprocessors to help our style writing, there is still an abundance of CSS bloat in all projects.&lt;/p&gt;

&lt;p&gt;Enter &lt;a href="https://purgecss.com/" rel="noopener noreferrer"&gt;PurgeCSS&lt;/a&gt;: a tool used to eliminate unused CSS from your codebase. PurgeCSS helps projects with performance and UX by reducing overall bundle size. Preprocessors, methodologies, and all of the actions we take before building our projects are wonderful, but it's unrealistic to expect them to completely solve maintainability &amp;amp; performance issues. Despite our best efforts as developers to keep a lean codebase, unnecessary CSS will inevitably come up during development. PurgeCSS is our fail-safe to ensure we ship the least amount of CSS that's needed.&lt;/p&gt;

&lt;p&gt;Here at Anvil, we use &lt;a href="https://styled-components.com/" rel="noopener noreferrer"&gt;styled-components&lt;/a&gt;. PurgeCSS functionality is essentially baked into styled-components, with a few caveats. If PurgeCSS is already included in styled-components, can you still use both? And if you can, is there any benefit to doing so?&lt;/p&gt;

&lt;p&gt;This blog post will answer these questions, as well as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How PurgeCSS works&lt;/li&gt;
&lt;li&gt;The benefits of using styled-components&lt;/li&gt;
&lt;li&gt;The caveats with styled-components' 'PurgeCSS' functionality&lt;/li&gt;
&lt;li&gt;Discuss some competitors to PurgeCSS &amp;amp; why PurgeCSS is the de facto solution&lt;/li&gt;
&lt;li&gt;Show you how to include PurgeCSS on a Gatsby site&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What is PurgeCSS and why should I care?
&lt;/h2&gt;

&lt;p&gt;PurgeCSS is a build/bundle time tool to transform your CSS into the bare minimum it should be. It aims to reduce your overall bundle size by sending only the critical CSS you need, instead of all the CSS you have written and imported. You can use it with any flavor of CSS you use: Sass, Less, &lt;a href="https://tailwindcss.com/" rel="noopener noreferrer"&gt;Tailwind&lt;/a&gt;, &lt;a href="https://getbootstrap.com/" rel="noopener noreferrer"&gt;Bootstrap&lt;/a&gt;, &lt;a href="https://mui.com/" rel="noopener noreferrer"&gt;Material UI&lt;/a&gt;, &lt;a href="https://bulma.io/" rel="noopener noreferrer"&gt;Bulma&lt;/a&gt;, the list goes on.&lt;/p&gt;

&lt;p&gt;The core reason to use PurgeCSS is to improve your site's performance. I also like using it to see a 'diff' of what CSS isn't being used. It's hard to track down what CSS is or isn't being used, so after building your site with PurgeCSS it's much easier to see what classes don't belong. After finding those classes, you can safely delete them from your codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  How PurgeCSS works
&lt;/h3&gt;

&lt;p&gt;PurgeCSS analyzes your HTML and internally keeps track of which selectors are being used or not. PurgeCSS actually analyzes other types of files besides HTML for selectors, such as template files and JavaScript. This feature is what makes PurgeCSS different from a similar solution, &lt;a href="https://github.com/uncss/uncss" rel="noopener noreferrer"&gt;UnCSS&lt;/a&gt;, and related to a 'predecessor' solution called &lt;a href="https://github.com/purifycss/purifycss" rel="noopener noreferrer"&gt;PurifyCSS&lt;/a&gt;. More on both of those later on.&lt;/p&gt;

&lt;p&gt;After finding which selectors are actually being used, PurgeCSS analyzes your CSS files and deletes the ones that aren't used. The CSS files with only the used selectors are included in the bundle. It's important to note that this only works by comparing selectors across your HTML and CSS; it's entirely possible that you have an unnecessary CSS property and value within a rule and that is entirely up to you to find and delete. Unfortunately, it's impossible (for now) for a program to determine if a CSS property is necessary or not.&lt;/p&gt;

&lt;p&gt;There might be cases where you want to keep CSS selectors/rules in the bundle no matter what. PurgeCSS comes with a 'safelist' option so you can configure what selectors you want to keep, even if they aren't used. You can also toggle the &lt;a href="https://purgecss.com/safelisting.html#in-the-css-directly" rel="noopener noreferrer"&gt;safelist directly in your CSS with comments&lt;/a&gt;, similar to &lt;a href="https://eslint.org/docs/user-guide/configuring/rules#using-configuration-comments" rel="noopener noreferrer"&gt;ESLint's configuration comments&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Styled-components
&lt;/h2&gt;

&lt;p&gt;On the other side of our titular question is styled-components. While I'm talking about styled-components specifically, the topics and concepts here apply to any CSS-in-JS provider (e.g. &lt;a href="https://github.com/emotion-js/emotion" rel="noopener noreferrer"&gt;emotion&lt;/a&gt;). There is a smaller CSS-in-JS library called &lt;a href="https://github.com/4Catalyzer/astroturf" rel="noopener noreferrer"&gt;astroturf&lt;/a&gt; that aims to give the developer the best of all worlds, so the limitations I'll discuss later on don't apply there. But be careful with smaller projects/ones that claim you can have it all! You are wading through uncharted territory :)&lt;/p&gt;

&lt;p&gt;Writing styles with styled-components, simply put, is &lt;strong&gt;amazing&lt;/strong&gt;. The primary motivation to use it is to improve DX (developer experience) and through that, increase development speed. React revolutionized web development by introducing component-based development to JS, and styled-components took that a step further by tying styles directly to components. It's a natural fit, as CSS classes are meant to be reused throughout the site, much like how a component is reused in many places in your application.&lt;/p&gt;

&lt;p&gt;Another benefit of using CSS within JS: built-in processing. Using preprocessors, leveraging dynamic props, trimming whitespace from your CSS, and even purging your CSS of unneeded selectors all take time to configure; styled-components comes with all of that 'out of the box' since it's embedded into JavaScript.&lt;/p&gt;

&lt;p&gt;While using styled-components is certainly more powerful than CSS by itself (or its preprocessor derivatives), it comes with its own caveats and considerations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Do you even need JavaScript? If your project is small, you should stick to HTML &amp;amp; CSS. &lt;a href="https://en.wikipedia.org/wiki/KISS_principle" rel="noopener noreferrer"&gt;Keep It Simple, Stupid&lt;/a&gt;!&lt;/li&gt;
&lt;li&gt;Are you introducing styled-components into a legacy codebase? You should probably clean up the cruft first before introducing more complexity.&lt;/li&gt;
&lt;li&gt;Does styled-components really include all the functionality of PurgeCSS? Let's find out!&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What's the diff between styled-components and PurgeCSS?
&lt;/h3&gt;

&lt;p&gt;From the documentation for styled-components, you get &lt;a href="https://styled-components.com/docs/basics#motivation" rel="noopener noreferrer"&gt;'Automatic critical CSS'&lt;/a&gt; out of the box:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Automatic critical CSS: styled-components keeps track of which components are rendered on a page and injects their styles and nothing else, fully automatically. Combined with code splitting, this means your users load the least amount of code necessary.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This boils down to: if a component is unused, the CSS isn't included in the bundle. Effectively, that is what PurgeCSS does. But let's understand how each technique works.&lt;/p&gt;

&lt;p&gt;Styled-components is 100% JavaScript-based, which is how it manages to keep track of what components are rendered on the client. This makes styled-components a &lt;strong&gt;run-time optimization&lt;/strong&gt;. PurgeCSS works by analyzing your content files and, based off what selectors it finds, removes rules from your CSS files before including them in the final bundle. This makes PurgeCSS a &lt;strong&gt;build-time optimization.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You need to consider your project's unique constraints and concerns, but in general build-time optimizations are better than run-time optimizations.&lt;/p&gt;

&lt;h4&gt;
  
  
  Quick note on PurgeCSS' comparison logic
&lt;/h4&gt;

&lt;p&gt;Before we go any further, I want to make sure you understand how PurgeCSS does its 'magic'. While an incredible tool, &lt;em&gt;PurgeCSS doesn't do anything fancy&lt;/em&gt;. None of the tools for removing CSS are intelligent by nature; they all remove CSS by pretty simple comparison.&lt;/p&gt;

&lt;p&gt;In PurgeCSS' case, it builds up a list of selectors from your HTML/JS/template files. You have the power to control what selectors make it into this list via &lt;a href="https://purgecss.com/extractors.html" rel="noopener noreferrer"&gt;extractors&lt;/a&gt;, but that is considered advanced and is out of scope for this post. After building up a list of selectors, PurgeCSS compares the selectors from CSS to that list. If a CSS selector is found that doesn't exist in the generated list, remove it! That's about it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Feature comparison: what about nested selectors?
&lt;/h3&gt;

&lt;p&gt;Effectively styled-components and PurgeCSS do the same thing. Let's see if we can poke a hole in that. Consider nested/combined selectors. Let's say you have a styled component like &lt;code&gt;Parent&lt;/code&gt; below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Parent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="s2"&gt;`
  width: 300px;
  height: 300px;
  background: yellow;

  .child {
    width: 100px;
    height: 100px;
    background: black;
  }
`&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App-header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Parent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/header&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;styled-components nested selector&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The class names of &lt;code&gt;App&lt;/code&gt; and &lt;code&gt;App-header&lt;/code&gt; are from create-react-app, and are irrelevant for the whole blog post. We are only focusing on parent and child styles.&lt;/p&gt;

&lt;p&gt;But looking at what React is going to render, we don't have any element with the class name 'child' as it is nested within the &lt;code&gt;Parent&lt;/code&gt; component. So ideally, the &lt;code&gt;.child&lt;/code&gt; CSS rule would not be included in our bundle, which for styled-components is injected CSS into the head of our document. Here's what was sent:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fow89xndivzips5fqhiob.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fow89xndivzips5fqhiob.png" alt="Styles in head for styled-components"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;.child rule is sent to the browser in the &lt;code&gt;head&lt;/code&gt; tag of our document&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Bummer, so styled-components doesn't handle nested selectors. PurgeCSS should be able to remove the selector from the equivalent CSS project right? Here's that same project, using React + CSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles/App.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;App-header&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;parent&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/header&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;React component using CSS directly from App.css&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.parent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;yellow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.parent&lt;/span&gt; &lt;span class="nc"&gt;.child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;CSS for our React + CSS project&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And here's the resulting CSS file after running PurgeCSS:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.parent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;300px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;yellow&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nc"&gt;.parent&lt;/span&gt; &lt;span class="nc"&gt;.child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PurgeCSS output file&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Wait, we still have that selector with &lt;code&gt;.child&lt;/code&gt;... what's going on here? As it turns out, &lt;a href="https://github.com/FullHuman/purgecss/issues/72" rel="noopener noreferrer"&gt;PurgeCSS doesn't handle descendant selectors/combinators&lt;/a&gt; like these well, just like styled-components. If we go back to the quick note on PurgeCSS' comparison logic, this actually makes sense. PurgeCSS isn't yet smart enough to build up nested selectors; so even though the HTML does represent &lt;code&gt;.parent .child&lt;/code&gt; in this case, the list of selectors are only the smallest possible, e.g.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;listOfSelectors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;parent&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;child&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And in our CSS, does this rule have a selector from the list?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="nc"&gt;.parent&lt;/span&gt; &lt;span class="nc"&gt;.child&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="m"&gt;100px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;background&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="no"&gt;black&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Yep, &lt;em&gt;clearly&lt;/em&gt; we have &lt;code&gt;.parent&lt;/code&gt; in our selector. PurgeCSS thinks this rule is used, even though it's not because of the increased specificity with &lt;code&gt;.child&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;While this is hugely disappointing, this is a known issue the PurgeCSS team is developing towards. The goal of styled-components is to provide great developer experience while styling, which has many subgoals. PurgeCSS, on the other hand, has only one goal of eliminating unused CSS to increase performance. I bet PurgeCSS will get this functionality before styled-components does.&lt;/p&gt;

&lt;h2&gt;
  
  
  Alternatives to PurgeCSS
&lt;/h2&gt;

&lt;p&gt;As mentioned before, there are 2 alternatives to PurgeCSS: &lt;a href="https://github.com/uncss/uncss" rel="noopener noreferrer"&gt;UnCSS&lt;/a&gt; &amp;amp; &lt;a href="https://github.com/purifycss/purifycss" rel="noopener noreferrer"&gt;PurifyCSS&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  PurifyCSS
&lt;/h3&gt;

&lt;p&gt;PurifyCSS works much the same way as PurgeCSS: build up a list of selectors from your content and delete the CSS rules with those selectors. The downside of this project is that it scopes out all the content from your project, so if you have a CSS class called 'arrow' and you happen to have the word 'arrow' in a paragraph, PurifyCSS will consider that selector used and keep it in the outputted CSS.&lt;/p&gt;

&lt;p&gt;This problem was one of the main goals of PurgeCSS and it solves this quite well.&lt;/p&gt;

&lt;h3&gt;
  
  
  UnCSS
&lt;/h3&gt;

&lt;p&gt;This project is very interesting. It actually solves the problem of excess CSS the best; it does so by loading your HTML into &lt;a href="https://github.com/jsdom/jsdom" rel="noopener noreferrer"&gt;jsdom&lt;/a&gt;, and then &lt;code&gt;querySelector&lt;/code&gt;-ing all of the selectors found in your CSS against the emulated DOM. If a selector isn't found in the emulated DOM, UnCSS will not include the CSS rule in its output.&lt;/p&gt;

&lt;p&gt;Because UnCSS compares in the 'other direction' (CSS → content, instead of content → CSS like PurgeCSS), it removes CSS much more accurately, including our edge case of nested selectors! In the example above, &lt;code&gt;document.querySelector('.parent .child')&lt;/code&gt; would return &lt;code&gt;null&lt;/code&gt;, and that CSS rule wouldn't be included.&lt;/p&gt;

&lt;h4&gt;
  
  
  If UnCSS is so accurate, why do we use PurgeCSS?
&lt;/h4&gt;

&lt;p&gt;What do you think is quicker, statically analyzing content for text (CSS selectors) and doing simple string comparison against CSS files or emulating the entire DOM in JavaScript, loading your HTML/CSS into it, and then running &lt;code&gt;document.querySelector&lt;/code&gt; on the emulated DOM for each CSS rule?&lt;/p&gt;

&lt;p&gt;UnCSS is splendid, but very costly to run. Imagine a huge project and doing all that work, just to get a few more KB of savings! PurgeCSS is the de facto standard because out of all the solutions, it's the most bang for your buck: remove most of the unused CSS in your project, but keep your build times low.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to use both PurgeCSS &amp;amp; styled-components
&lt;/h2&gt;

&lt;p&gt;As of writing this, there is no way to integrate both technologies for a couple of reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Styled-components works by injecting critical CSS directly into the &lt;code&gt;head&lt;/code&gt; of your HTML; the CSS files needed for PurgeCSS never exist.&lt;/li&gt;
&lt;li&gt;PurgeCSS is primarily run with &lt;a href="https://postcss.org/" rel="noopener noreferrer"&gt;PostCSS&lt;/a&gt;, which is not supported with styled-components.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The second of those two reasons is very disappointing, as &lt;a href="https://postcss.org/" rel="noopener noreferrer"&gt;PostCSS&lt;/a&gt; is a rich ecosystem of plugins to extend your CSS' functionality and build process. PostCSS is what &lt;a href="https://babeljs.io/" rel="noopener noreferrer"&gt;Babel&lt;/a&gt; is for JavaScript, and unfortunately styled-components is missing out on an entire suite of new functionality.&lt;/p&gt;

&lt;p&gt;I have some good news for you though: there is a very common case where you can use both!&lt;/p&gt;

&lt;h3&gt;
  
  
  CSS Frameworks
&lt;/h3&gt;

&lt;p&gt;I'm not sure what the stats are, but I'm willing to bet that over 50% of websites and webapps started off using a CSS framework. I'm talking about frameworks like Bootstrap, Bulma, &lt;a href="https://ant.design/" rel="noopener noreferrer"&gt;Ant&lt;/a&gt;, Material UI, &lt;a href="http://getskeleton.com/" rel="noopener noreferrer"&gt;Skeleton&lt;/a&gt;, and many more.&lt;/p&gt;

&lt;p&gt;Using a CSS framework lets developers get up and running much faster than building custom HTML/CSS for components that already exist. And including a framework in your website alongside styled-components is a breeze - add in the classic &lt;code&gt;&amp;lt;link rel="stylesheet" href="styles.css"&amp;gt;&lt;/code&gt; with your framework's stylesheets, and those classes will be available to you globally.&lt;/p&gt;

&lt;p&gt;But this is exactly what PurgeCSS was written for. You only need a few components from the CSS framework, not thousands of classes you'll never use. So even though we can't integrate PurgeCSS and styled-components directly, they still mesh well together to bring your bundle size to the lowest possible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Set up PurgeCSS with Gatsby
&lt;/h2&gt;

&lt;p&gt;To help you get up and running with PurgeCSS, I'll show you how to set up PurgeCSS with Gatsby. The options used here can be applied to any other PurgeCSS setup as well.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Install gatsby-plugin-purgecss: &lt;code&gt;yarn add gatsby-plugin-purgecss&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Configure the plugin in &lt;code&gt;gatsby-config.js&lt;/code&gt;, ensuring you place this plugin AFTER all your other style plugins:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`gatsby-plugin-purgecss`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nl"&gt;printRejected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;purgeCSSOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Default configuration for &lt;code&gt;gatsby-plugin-purgecss&lt;/code&gt;; be sure to add LAST after all CSS plugins&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you import your styles directly (e.g. &lt;code&gt;import './styles.css'&lt;/code&gt; instead of &lt;code&gt;import styles from './styles.css'&lt;/code&gt;), this is all you have to do. During your &lt;code&gt;gatsby build&lt;/code&gt; command you'll see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1bbz656to2gbt7kej6qg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1bbz656to2gbt7kej6qg.png" alt="PurgeCSS savings without antd config"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The savings we got from plugging and playing the PurgeCSS plugin&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And will feel much better about shipping your CSS to the browser :)&lt;/p&gt;

&lt;p&gt;There are two edge cases I'll cover here. The first: if you don't import your styles directly. If you set class names like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mySelector&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have a couple of options. You can safelist the selector so it never gets purged:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;purgeCSSOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;safelist&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-selector&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="c1"&gt;// Don't remove this selector&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Using PurgeCSS' native &lt;code&gt;safelist&lt;/code&gt; configuration as part of the Gatsby plugin&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Or you can use a comment above your component with the correct format of the selector so it gets purged, which is the method I prefer. That way, it's easier to manage if you end up never using the selector and it can be purged safely; the safelist option is a good fail-safe, but it's a bit aggressive in keeping styles. Here's an example with the comment:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./styles.css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// my-selector&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;mySelector&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;PurgeCSS comment to ensure the correctly formatted selector gets purged&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Ant Design
&lt;/h3&gt;

&lt;p&gt;The other edge case to consider is if, like us at Anvil, you use &lt;a href="https://ant.design/" rel="noopener noreferrer"&gt;Ant  Design&lt;/a&gt;. PurgeCSS has a hard time with Ant Design to keep the correct styles, and PurgeCSS is aware of this. &lt;a href="https://purgecss.com/ant_design.html" rel="noopener noreferrer"&gt;Here's the solution straight from the docs&lt;/a&gt;, but it isn't adapted for the Gatsby plugin.&lt;/p&gt;

&lt;p&gt;Below is how I adapted the solution for Gatsby. The gist: use the LESS/CSS files as content. Using your style files as content is a bit confusing, but this makes it so we are getting the selectors in our list of 'used' styles, so when PurgeCSS compares against the same exact files, we are guaranteed to keep those styles we need.&lt;/p&gt;

&lt;p&gt;For any components we need &lt;em&gt;all&lt;/em&gt; of the styles for, we use the Gatsby plugin's &lt;code&gt;ignore&lt;/code&gt; field to ensure nothing from those directories gets purged.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`gatsby-plugin-purgecss`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// set this to true for debugging purposes; see what was removed&lt;/span&gt;
    &lt;span class="nl"&gt;printRejected&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="c1"&gt;// ignore the antd styles you want to completely keep&lt;/span&gt;
    &lt;span class="nx"&gt;ignore&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node_modules/antd/lib/select&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node_modules/antd/lib/checkbox&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;purgeCSSOptions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nl"&gt;content&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/**/!(*.d).{ts,js,jsx,tsx}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="c1"&gt;// antd doesn't mesh well w purgecss, so keep the files we use&lt;/span&gt;
        &lt;span class="c1"&gt;// by listing them as content files.&lt;/span&gt;
        &lt;span class="c1"&gt;// reference: https://purgecss.com/ant_design.html&lt;/span&gt;
        &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node_modules/antd/lib/{tooltip,modal,radio}/**/*.{css,less}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="c1"&gt;// utility styles from ant, let's keep it&lt;/span&gt;
        &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node_modules/antd/lib/style/**/*.{css,less}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="nx"&gt;extractors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="c1"&gt;// on top of listing antd files as content, we need an extractor to work&lt;/span&gt;
          &lt;span class="c1"&gt;// with css/less to get the selectors&lt;/span&gt;
          &lt;span class="na"&gt;extractor&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
            &lt;span class="nx"&gt;content&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;([&lt;/span&gt;&lt;span class="sr"&gt;a-zA-Z-0-9-@&amp;amp;:{}&lt;/span&gt;&lt;span class="se"&gt;]&lt;/span&gt;&lt;span class="sr"&gt;+&lt;/span&gt;&lt;span class="se"&gt;)(?=&lt;/span&gt;&lt;span class="sr"&gt; {&lt;/span&gt;&lt;span class="se"&gt;)&lt;/span&gt;&lt;span class="sr"&gt;/g&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
          &lt;span class="na"&gt;extensions&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;css&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;less&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;gatsby-plugin-purgecss configured to keep select antd styles&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Our final CSS savings isn't as much as I wanted, but over 50% is still pretty good:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvjnlinlyfccdfzgdzr5v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvjnlinlyfccdfzgdzr5v.png" alt="Final CSS savings with PurgeCSS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Putting it all together
&lt;/h2&gt;

&lt;p&gt;Both PurgeCSS and styled-components are popular for a reason. Web development has no one 'correct' way to implement a solution, but both technologies are great additions to any project. And when the two are combined in the case of using a CSS framework, you're guaranteed to get production-ready UX, DX, stylability, and performance. Have any other CSS optimization tips? We'd love to hear from you at &lt;a href="mailto:developers@useanvil.com"&gt;developers@useanvil.com&lt;/a&gt;. Happy coding!&lt;/p&gt;

</description>
      <category>css</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Manipulate and query GraphQL Schemas with ease using Microfiber</title>
      <dc:creator>Anvil Engineering</dc:creator>
      <pubDate>Wed, 13 Apr 2022 16:55:51 +0000</pubDate>
      <link>https://forem.com/useanvil/manipulate-and-query-graphql-schemas-with-ease-using-microfiber-1e3o</link>
      <guid>https://forem.com/useanvil/manipulate-and-query-graphql-schemas-with-ease-using-microfiber-1e3o</guid>
      <description>&lt;p&gt;A while back we &lt;a href="https://www.useanvil.com/blog/engineering/autogenerate-graphql-docs-with-spectaql/"&gt;introduced&lt;/a&gt; &lt;a href="https://github.com/anvilco/spectaql"&gt;SpectaQL&lt;/a&gt; to the open source community and it's been a big success. It gets thousands of weekly downloads, has a healthy amount of user support and interest via github, and has had a number of articles written about it like &lt;a href="https://blog.graphqleditor.com/spectaql"&gt;this one&lt;/a&gt; and &lt;a href="https://blog.graphqleditor.com/spectaql"&gt;this one&lt;/a&gt;. Our goal for SpectaQL has always been to be the de-facto go-to library to use for auto-generating static HTML documentation for any GraphQL API. A very important feature of SpectaQL is its ability to "hide" any parts of your API that you don't want to expose in your documentation. This sounds like a simple task, but in practice it's actually a bit tricky. In order to make interacting and manipulating a GraphQL schema easy, we developed a tool designed specifically for this purpose. Eventually we realized that while this tool was super integral to SpectaQL, it would also be useful for other applications so we decided to break it out into its own library and &lt;a href="https://github.com/anvilco/graphql-introspection-tools"&gt;open source&lt;/a&gt; it! In this post, I'll introduce &lt;a href="https://github.com/anvilco/graphql-introspection-tools"&gt;Microfiber&lt;/a&gt; and give an overview of its most interesting features and capabilities.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Unless you're an expert, GraphQL schemas can be a bit tricky to wrap your head around and understand their structure. For example, not everyone understands that your queries are actually defined as Fields on a type that you have specified as a special "Query" type (either by convention or by configuration, depending on the implementation you're using). Also, it can be tricky to understand what you need to know about the Type of certain Fields, Arguments or query/mutation results: are they nullable? Are they a single item or a list? If it's a list, can any of the items be null? Furthermore, if you want to "hide" a Type from your schema, how do you go about finding all the references to that Type in Fields, Arguments, or query/mutation results and remove those things as well? Enter Microfiber!&lt;/p&gt;

&lt;h2&gt;
  
  
  Why "Microfiber"?
&lt;/h2&gt;

&lt;p&gt;Before we dive in further, you may be wondering: why is it called "microfiber"? You know that little fibrous thing that comes with your glasses and is used to clean the lenses? That's a microfiber. Since a microfiber is used for cleaning up things, and our microfiber is used for "cleaning up" your GraphQL schema, we thought the name made sense. Also, since a microfiber is often used to clean glasses, and our microfiber is used heavily by SpectaQL (a reference to glasses) we thought the name fit doubly as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started
&lt;/h2&gt;

&lt;p&gt;In order to keep Microfiber lightweight in terms of dependencies, it requires you to provide it your schema in the form of an &lt;a href="https://graphql.org/learn/introspection/"&gt;Introspection Query&lt;/a&gt; result. This result is just a simple JSON object. You can set a number of interesting options when creating your Microfiber instance, however the defaults are all pretty "sane" for must use cases. You can see all the options that are supported in the &lt;a href="https://github.com/anvilco/graphql-introspection-tools"&gt;documentation&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Microfiber&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;microfiber&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;introspectionQueryResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{...}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;microfiber&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;Microfiber&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;introspectionQueryResults&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// ...do some things to your schema with `microfiber`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cleanedIntrospectonQueryResults&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;microfiber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getResponse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// ...do something with your cleaned Introspection Query Results.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Querying Your Schema
&lt;/h2&gt;

&lt;p&gt;It's not always easy to traverse a schema to find what you're looking for, or to check if it exists. Microfiber provides a number of "get" functions that can do this for you with ease. Here are a few examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Get a specific Query from your schema.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;query&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;microfiber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getQuery&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;users&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Get a specific Mutation from your schema.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;mutation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;microfiber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getMutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;createUser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Get a specific Field from your schema.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;microfiber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getField&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;typeKind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OBJECT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;typeName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;// Get a specific Arg from your schema.&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;arg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;microfiber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getArg&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;typeKind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OBJECT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;typeName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;addresses&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;argName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;countryFilter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Modifying Your Schema
&lt;/h2&gt;

&lt;p&gt;While querying with your schema is useful, the real power of Microfiber comes with the manipulations that it can perform. For example, you may want to hide a specific Field on a Type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;microfiber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeField&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;typeKind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OBJECT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;typeName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;fieldName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;email&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or you may want to hide a mutation that you don't want anyone to know exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;microfiber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeMutation&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;deleteUser&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or, perhaps the most useful feature of Microfiber, you may want to remove a Type completely from your schema. That is, not only remove the Type, but also remove any Fields, InputFields, Union Type options, Args, Queries, or Mutations of that Type. This can be tricky to do on your own but is easy with Microfiber:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;microfiber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;removeType&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;OBJECT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;SecretType&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Additionally, Microfiber can automatically clean things up by—for example—removing all Types from your schema that are not actually used anywhere. This can sometimes occur when you've hidden certain Fields, etc, that reference a Type, but did not explicitly remove that Type yourself.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;microfiber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cleanSchema&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can retrieve your modified schema with ease, and pass it along where you need it to go:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cleanedResponse&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;microfiber&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getResponse&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;If you're looking for an easy way to query your GraphQL schema—especially in the form of an Introspection Query result—then Microfiber is a great option instead of trying to write your own helpers. However, if you are trying to clean up or modify your schema by hiding things, then Microfiber can really make your life easier. We'll continue to add more features as we identify them, and if you find microfiber helpful (or have questions) please reach out to us at &lt;a href="mailto:developers@useanvil.com"&gt;developers@useanvil.com&lt;/a&gt;, or swing on by the repo and leave a message. Happy developing!&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>tutorial</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Techniques to optimize React render performance: part 2</title>
      <dc:creator>Anvil Engineering</dc:creator>
      <pubDate>Fri, 11 Mar 2022 21:11:05 +0000</pubDate>
      <link>https://forem.com/useanvil/techniques-to-optimize-react-render-performance-part-2-5baf</link>
      <guid>https://forem.com/useanvil/techniques-to-optimize-react-render-performance-part-2-5baf</guid>
      <description>&lt;p&gt;This is the final part in a two part series on optimizing React component render performance in your UI. In &lt;a href="https://dev.to/blog/engineering/improve-optimize-react-render-performance-part-1"&gt;part one of optimizing React performance&lt;/a&gt;, we covered tooling, profiling, and generally tracking down exactly where your UI is slow. If you haven't read it yet, check it out. Part 1 was trying to answer &lt;em&gt;Where is it slow?&lt;/em&gt; and &lt;em&gt;Why is it slow?&lt;/em&gt; Like debugging, knowing exactly where you need to spend your time will make the solution come a lot easier.&lt;/p&gt;

&lt;p&gt;By now you should have some UI profiling under your belt and have a good idea of which components are slow. It is high time to fix them. In this post, we will focus on just that: techniques and pitfalls to improve your slow React components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Render less
&lt;/h2&gt;

&lt;p&gt;The central tenet of improving performance in general is effectively: "do less work." In React land, that usually translates into rendering less often. One of the initial promises of React and the &lt;a href="https://www.codecademy.com/article/react-virtual-dom"&gt;virtual DOM&lt;/a&gt; was that you didn't need to think very hard about rendering performance: slowness is caused by updates to the Real DOM, and React abstracts the Real DOM from you in a smart way. &lt;a href="https://reactjs.org/docs/reconciliation.html"&gt;Diffing of the virtual DOM&lt;/a&gt; and only updating the necessary elements in the Real DOM will save you.&lt;/p&gt;

&lt;p&gt;In UIs with a lot of components, the reality is that you still need to be concerned with how often your components are rendering. The less DOM diffing React needs to do, the faster your UI will be. Do less work, render less often. This will be the focus of our initial performance efforts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: list of fields
&lt;/h2&gt;

&lt;p&gt;We'll be applying several different optimization techniques to the same example: a list of webform fields. We'll pretend that we've identified this part of the UI as something to optimize. This same example was used in our &lt;a href="https://dev.to/blog/engineering/improve-optimize-react-render-performance-part-1"&gt;first React performance post&lt;/a&gt; and we identified a couple issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;When the list re-renders with a lot of fields, it feels slow.&lt;/li&gt;
&lt;li&gt;Each field in the list &lt;a href="https://dev.to/blog/engineering/improve-optimize-react-render-performance-part-1#react-profiler"&gt;renders too often&lt;/a&gt;; we only want fields that have changed to re-render.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--NsfHXqfR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n5n7bw6pq8wj775g97z2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--NsfHXqfR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/n5n7bw6pq8wj775g97z2.png" alt="Example list of webform fields" width="880" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A simplified version of the code and a basis for our optimization work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Each individual field&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;isActive&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// Renders all fields&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ListOfFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Keep track of the active field based on which one&lt;/span&gt;
  &lt;span class="c1"&gt;// was clicked last&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setActiveField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Field&lt;/span&gt;
          &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setActiveField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Our example for techniques in this post&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Note that we are keeping track of an active field in &lt;code&gt;ListOfFields&lt;/code&gt;. Each time a &lt;code&gt;Field&lt;/code&gt; is clicked, it will store the last-clicked &lt;code&gt;Field&lt;/code&gt;'s id in the &lt;code&gt;ListOfFields&lt;/code&gt; state. The state change will trigger &lt;code&gt;ListOfFields&lt;/code&gt; to re-render.&lt;/p&gt;

&lt;p&gt;By default, when &lt;code&gt;ListOfFields&lt;/code&gt; re-renders, &lt;em&gt;all&lt;/em&gt; of the child &lt;code&gt;Field&lt;/code&gt; components will re-render as well. For example, clicking one &lt;code&gt;Field&lt;/code&gt; will set &lt;code&gt;activeField&lt;/code&gt; state in &lt;code&gt;ListOfFields&lt;/code&gt; which will cause a &lt;code&gt;ListOfFields&lt;/code&gt; re-render. The parent re-render will cause all of the child &lt;code&gt;Field&lt;/code&gt; components to re-render. Every one of them! Every time!&lt;/p&gt;

&lt;h2&gt;
  
  
  Solutions
&lt;/h2&gt;

&lt;p&gt;Our potential solutions will center around two main goals:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Render child &lt;code&gt;Field&lt;/code&gt; components less often&lt;/li&gt;
&lt;li&gt;Compute expensive operations in the render function less often&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After this post, you should be able to apply all these techniques to your own codebase while avoiding the pitfalls. Here's what we'll be covering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pure components&lt;/li&gt;
&lt;li&gt;shouldComponentUpdate&lt;/li&gt;
&lt;li&gt;Caching computed values&lt;/li&gt;
&lt;li&gt;Consider your architecture&lt;/li&gt;
&lt;li&gt;Other solutions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's dig in!&lt;/p&gt;

&lt;h2&gt;
  
  
  Pure components
&lt;/h2&gt;

&lt;p&gt;The first potential solution to selective component re-rendering is converting our &lt;code&gt;Field&lt;/code&gt; component into a &lt;a href="https://reactjs.org/docs/react-api.html#reactpurecomponent"&gt;pure component&lt;/a&gt;. A pure component will only re-render if the component's props change. There are caveats, of course, but we'll get to those in a minute.&lt;/p&gt;

&lt;p&gt;In our example above, when a &lt;code&gt;Field&lt;/code&gt; is clicked and the &lt;code&gt;activeField&lt;/code&gt; state is set, &lt;strong&gt;all&lt;/strong&gt; &lt;code&gt;Field&lt;/code&gt; components are re-rendered. Not good! The ideal scenario is that only two &lt;code&gt;Field&lt;/code&gt; components are re-rendered: the previously-active and the newly-active &lt;code&gt;Field&lt;/code&gt;s. It should skip rendering all of the other &lt;code&gt;Fields&lt;/code&gt; that did not change.&lt;/p&gt;

&lt;p&gt;Pure components are extremely easy to use. Either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wrap a functional component with &lt;code&gt;React.memo&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Or define your class component with &lt;code&gt;React.PureComponent&lt;/code&gt; instead of &lt;code&gt;React.Component&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="c1"&gt;// These components will only re-render&lt;/span&gt;
&lt;span class="c1"&gt;// when their props change!&lt;/span&gt;

&lt;span class="c1"&gt;// Pure functional component&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// Pure class component&lt;/span&gt;
&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PureComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using pure components can be an easy win, but it is also very easy to shoot yourself in the foot and unknowingly break re-render prevention.&lt;/p&gt;

&lt;p&gt;The big caveat is that a pure component's props are shallow-compared by default. Basically, &lt;code&gt;if (newProps.label !== oldProps.label) reRender()&lt;/code&gt;. This is fine if all of your props are primitives: strings, numbers, booleans. But things get more complicated if you are passing anything else as props: objects, arrays, or functions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pure component pitfall: callback functions
&lt;/h3&gt;

&lt;p&gt;Here is our original example with &lt;code&gt;Field&lt;/code&gt; as a pure component. Turns out even in our new example using pure components, the re-rendering issue has not improved—all &lt;code&gt;Field&lt;/code&gt; components are still being rendered on each &lt;code&gt;ListOfFields&lt;/code&gt; render. Why?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Still re-renders all of the fields :(&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ListOfFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setActiveField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Field&lt;/span&gt;
          &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setActiveField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt; &lt;span class="c1"&gt;// Problem!!!&lt;/span&gt;
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue is that the &lt;code&gt;onClick&lt;/code&gt; callback function is being created in the render function. Remember that pure components do a shallow props comparison; they test equality by reference, but two &lt;code&gt;onClick&lt;/code&gt; functions are not equal between renders: &lt;code&gt;(() =&amp;gt; {}) === (() =&amp;gt; {})&lt;/code&gt; is &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;How can we fix this? By passing the same function to &lt;code&gt;onClick&lt;/code&gt; in each re-render. You have a couple options here:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pass in &lt;code&gt;setActiveField&lt;/code&gt; directly&lt;/li&gt;
&lt;li&gt;Wrap your callback in the &lt;code&gt;useCallback&lt;/code&gt; hook&lt;/li&gt;
&lt;li&gt;Use bound member functions when using class components&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here the issue is fixed with the first two options in a functional component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ListOfFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// The useState hook will keep setActiveField the same&lt;/span&gt;
  &lt;span class="c1"&gt;// shallow-equal function between renders&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setActiveField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Field&lt;/span&gt;
          &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

          &lt;span class="c1"&gt;// Option 1: setActiveField does not change between renders,&lt;/span&gt;
          &lt;span class="c1"&gt;// you can pass it directly without breaking React.memo&lt;/span&gt;
          &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setActiveField&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

          &lt;span class="c1"&gt;// Option 2: memoize the callback with useCallback&lt;/span&gt;
          &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;setActiveField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;])}&lt;/span&gt;
        &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;      &lt;span class="p"&gt;))}&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// An anonymous function in the render method here will not&lt;/span&gt;
&lt;span class="c1"&gt;// trigger additional re-renders&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;
    &lt;span class="c1"&gt;// Option 1: Since setActiveField is passed in directly,&lt;/span&gt;
    &lt;span class="c1"&gt;// we need to give it an id. An inline function here is ok&lt;/span&gt;
    &lt;span class="c1"&gt;// and will not trigger re-renders&lt;/span&gt;
    &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;

    &lt;span class="c1"&gt;// Option 2: Since the id is passed to the setActiveField&lt;/span&gt;
    &lt;span class="c1"&gt;// in the parent component, you can use the callback directly&lt;/span&gt;
    &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And a fix using class components:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PureComponent&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;
    &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;isActive&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ListOfFields&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c1"&gt;// Use a bound function&lt;/span&gt;
  &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;activeField&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Field&lt;/span&gt;
            &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

            &lt;span class="c1"&gt;// Solved! The bound function does not change between renders&lt;/span&gt;
            &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="p"&gt;))}&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Pure component pitfall: dynamic data in the render function
&lt;/h3&gt;

&lt;p&gt;The function callback pitfall described above is really a subset of a larger issue: passing props dynamically created in the render function. For example, because &lt;code&gt;{ color: 'blue' }&lt;/code&gt; is defined in the render function here, it will be different on each render, which will force a re-render on every &lt;code&gt;Field&lt;/code&gt; component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Pure component for each individual field&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ListOfFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Problem!&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Field&lt;/span&gt;
      &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The ideal solution is to create the style prop's object somewhere outside of the render function. If you must dynamically create an object or array in the render function, the created object can be wrapped in the &lt;code&gt;useMemo&lt;/code&gt; hook. The &lt;code&gt;useMemo&lt;/code&gt; hook is covered in the caching computed values section below.&lt;/p&gt;

&lt;h2&gt;
  
  
  shouldComponentUpdate
&lt;/h2&gt;

&lt;p&gt;By default, pure components shallow-compare props. If you have props that need to be compared in a more complex way, there is a &lt;code&gt;shouldComponentUpdate&lt;/code&gt; lifecycle function for class components and a functional / hooks equivalent in &lt;code&gt;React.memo&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the functional implementation, &lt;code&gt;React.memo&lt;/code&gt; takes a second param: a function to do the props comparison. It's still beneficial to shoot for props that do not change between renders unless a re-render is necessary, but the real world is messy and these functions provide an escape hatch.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="c1"&gt;// Return true to NOT re-render&lt;/span&gt;
  &lt;span class="c1"&gt;// We can shallow-compare the label&lt;/span&gt;
  &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;nextProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;
    &lt;span class="c1"&gt;// But we deep compare the `style` prop&lt;/span&gt;
    &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then implemented as a class component&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;shouldComponentUpdate&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Return false to NOT re-render&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;nextProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt;
      &lt;span class="c1"&gt;// Here we deep compare style&lt;/span&gt;
      &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;nextProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Caching computed values
&lt;/h2&gt;

&lt;p&gt;Let's say that while &lt;a href="https://dev.to/blog/engineering/improve-optimize-react-render-performance-part-1"&gt;profiling your app&lt;/a&gt; you've identified an expensive operation happening on each render of &lt;code&gt;ListOfFields&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ListOfFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filterCriteria&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setActiveField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// This is slow!&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;verySlowFunctionToFilterFields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filterCriteria&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;filteredFields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Field&lt;/span&gt;
      &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setActiveField&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, every time a &lt;code&gt;Field&lt;/code&gt; is clicked, it will re-run &lt;code&gt;verySlowFunctionToFilterFields&lt;/code&gt;. But it doesn't need to! The &lt;code&gt;filteredFields&lt;/code&gt; only need to be computed each time either the &lt;code&gt;fields&lt;/code&gt; or &lt;code&gt;filterCriteria&lt;/code&gt; are changed. You can wrap your slow function in the &lt;code&gt;useMemo()&lt;/code&gt; hook to &lt;a href="https://en.wikipedia.org/wiki/Memoization"&gt;memoize&lt;/a&gt; &lt;code&gt;filteredFields&lt;/code&gt;. Once it's memoized, &lt;code&gt;verySlowFunctionToFilterFields&lt;/code&gt; will only re-run when &lt;code&gt;fields&lt;/code&gt; or &lt;code&gt;filterCriteria&lt;/code&gt; changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useMemo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ListOfFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filterCriteria&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setActiveField&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Better, yay&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;verySlowFunctionToFilterFields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filterCriteria&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filterCriteria&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;filteredFields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Field&lt;/span&gt;
      &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setActiveField&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Like pure components, you need to be careful that you do not break the comparison. &lt;code&gt;useMemo&lt;/code&gt; suffers from the same pitfalls as pure components: it performs a shallow-comparison of arguments. That means if &lt;code&gt;fields&lt;/code&gt; or &lt;code&gt;filterCriteria&lt;/code&gt; are re-created between renders, it will &lt;em&gt;still&lt;/em&gt; re-compute your expensive operation on each render.&lt;/p&gt;

&lt;p&gt;Unfortunately &lt;code&gt;useMemo&lt;/code&gt; does not accept a second comparison argument like &lt;code&gt;React.memo&lt;/code&gt;. If you want to do a deep comparison there are several &lt;a href="https://usehooks.com/useMemoCompare/"&gt;code samples&lt;/a&gt; and &lt;a href="https://github.com/kentcdodds/use-deep-compare-effect"&gt;libraries&lt;/a&gt; out there you can use.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using &lt;code&gt;useMemo&lt;/code&gt; to limit re-renders
&lt;/h3&gt;

&lt;p&gt;In our pure component pitfalls above, we noted that passing objects created in the render function can break a pure component's benefits. Note here that the &lt;code&gt;style&lt;/code&gt; object is being created on each render of &lt;code&gt;ListOfFields&lt;/code&gt;, forcing all &lt;code&gt;Field&lt;/code&gt;s to render all the time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Pure component for each individual field&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;memo&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ListOfFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// Problem! Forces Field to always re-render&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Field&lt;/span&gt;
      &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;While the ideal scenario is to move creation of the &lt;code&gt;style&lt;/code&gt; object out of the render function, sometimes creating an object in the render function is necessary. In those instances, &lt;code&gt;useMemo&lt;/code&gt; can be helpful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ListOfFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// This will be cached until the `color` prop changes&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;style&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;color&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;color&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Field&lt;/span&gt;
      &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Caching computed values in class components
&lt;/h3&gt;

&lt;p&gt;Caching computed values in class components is a bit clunkier, especially if you are trying to avoid the &lt;code&gt;UNSAFE_componentWillReceiveProps()&lt;/code&gt; lifecycle function. The React maintainers &lt;a href="https://reactjs.org/blog/2018/06/07/you-probably-dont-need-derived-state.html#what-about-memoization"&gt;recommend&lt;/a&gt; using the &lt;a href="https://github.com/alexreardon/memoize-one"&gt;&lt;code&gt;memoize-one&lt;/code&gt;&lt;/a&gt; library:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;memoize&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;memoize-one&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;ListOfFields&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;handleClick&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

  &lt;span class="nx"&gt;getFilteredFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;memoize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filterCriteria&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nx"&gt;verySlowFunctionToFilterFields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filterCriteria&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filterCriteria&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filteredFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getFilteredFields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;filterCriteria&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;filteredFields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Field&lt;/span&gt;
        &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;isActive&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;activeField&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nx"&gt;onClick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handleClick&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;))&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Consider your architecture
&lt;/h2&gt;

&lt;p&gt;So far, we've focused on pretty tactical solutions: e.g. use this library function in this way. A much broader tool in your toolbox is adjusting your application's architecture to re-render fewer components when things change. At the very least, it is helpful to understand how your app's data flow and data locality affects performance.&lt;/p&gt;

&lt;p&gt;A couple questions to answer: at what level are you storing application state? When something changes deep in the component tree, where is the new data stored? Which components are being rendered when state changes?&lt;/p&gt;

&lt;p&gt;In the spirit of our webform example, consider the following component tree:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Application&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Navbar&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;AnExpensiveComponent&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ExpensiveChild&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/AnExpensiveComponent&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Webform&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ListOfFields&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Field&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Field&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;Field&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/ListOfFields&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/Webform&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Application&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the webform editor, we need an array of &lt;code&gt;fields&lt;/code&gt; stored &lt;em&gt;somewhere&lt;/em&gt; in this tree. When a field is clicked or label is updated, the array of &lt;code&gt;fields&lt;/code&gt; needs to be updated, and some components need to be re-rendered.&lt;/p&gt;

&lt;p&gt;Let's say at first we keep the &lt;code&gt;fields&lt;/code&gt; state in the &lt;code&gt;&amp;lt;Application /&amp;gt;&lt;/code&gt; Component. When a field changes, the newly changed field will bubble up all the way to the &lt;code&gt;Application&lt;/code&gt; component's state.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setFields&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;one&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}])&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Navbar&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnExpensiveComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Webform&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onChangeFields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setFields&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this architecture, every field change will cause a re-render of &lt;code&gt;Application&lt;/code&gt;, which will rightly re-render &lt;code&gt;Webform&lt;/code&gt; and all the child &lt;code&gt;Field&lt;/code&gt; components. The downside is that each &lt;code&gt;Field&lt;/code&gt; change will &lt;em&gt;also&lt;/em&gt; trigger a re-render of &lt;code&gt;Navbar&lt;/code&gt; and &lt;code&gt;AnExpensiveComponent&lt;/code&gt;. Not ideal! &lt;code&gt;AnExpensiveComponent&lt;/code&gt; sounds slow! These components do not even care about &lt;code&gt;fields&lt;/code&gt;, why are they being unnecessarily re-rendered here?&lt;/p&gt;

&lt;p&gt;A more performant alternative would be to store the state closer to the components that care about the &lt;code&gt;fields&lt;/code&gt; array.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Navbar&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnExpensiveComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Webform&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Webform&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setFields&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;one&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}])&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListOfFields&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;onChangeFields&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;setFields&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this new setup, &lt;code&gt;Application&lt;/code&gt;, &lt;code&gt;Navbar&lt;/code&gt;, and &lt;code&gt;AnExpensiveComponent&lt;/code&gt; are all blissfully unaware of &lt;code&gt;fields&lt;/code&gt;. Don't render, ain't care.&lt;/p&gt;

&lt;h3&gt;
  
  
  In practice: Redux
&lt;/h3&gt;

&lt;p&gt;While I am &lt;a href="https://blog.openreplay.com/is-redux-dead"&gt;not a Redux advocate&lt;/a&gt;, it really shines in this scenario. The &lt;a href="https://redux.js.org/faq/general#when-should-i-use-redux"&gt;Redux docs&lt;/a&gt; even outline this as the number one reason to use Redux:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;You have large amounts of application state that are needed in many places in the app.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;"Many places in the app" is the key for us here. Redux allows you to &lt;code&gt;connect()&lt;/code&gt; any component to the Redux store at any level. That way, only the components that need to will re-render when the requisite piece of state changes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Application does not need to know about fields&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Application&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Navbar&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;AnExpensiveComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ListOfFields&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;span class="c1"&gt;// ListOfFieldsComponent does need to know about&lt;/span&gt;
&lt;span class="c1"&gt;// fields and how to update them&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ListOfFieldsComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onChangeFields&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onChangeFields&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Field&lt;/span&gt;
      &lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="nx"&gt;onChange&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;eventuallyCallOnChangeFields&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// This will connect the Redux store only to the component&lt;/span&gt;
&lt;span class="c1"&gt;// where we need the state: ListOfFields&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ListOfFields&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;connect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;onChangeFields&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;dispatch&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;CHANGE_FIELDS&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fields&lt;/span&gt;
    &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;)(&lt;/span&gt;&lt;span class="nx"&gt;ListOfFieldsComponent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you're using Redux, it's worth checking which components are being connected to which parts of the store.&lt;/p&gt;

&lt;h3&gt;
  
  
  App state best practices?
&lt;/h3&gt;

&lt;p&gt;Deciding where to put your application state, or pieces of your application state is tricky. It depends heavily on what data you are storing, how it needs to be updated, and libraries you're using. In my opinion, there are no hard / fast rules here due to the many tradeoffs.&lt;/p&gt;

&lt;p&gt;My philosophy is to initially optimize for consistency and developer reasonability. On many pages, it doesn't matter where the state is, so it makes the most sense to keep the ugly bits in one place. State is where the bugs are, &lt;a href="https://en.wikipedia.org/wiki/Program_optimization#When_to_optimize"&gt;premature optimization is the root of all evil&lt;/a&gt;, so for the sake of our own sanity let's not scatter state around if we can help it.&lt;/p&gt;

&lt;p&gt;For example, your company's about page can have all data come into the top-level component. It's fine, and is likely more ideal for developer UX. If performance is an issue for some component, &lt;em&gt;then&lt;/em&gt; it's time to think deeper about the performance of your app's state flow and maybe break the paradigm for performance reasons.&lt;/p&gt;

&lt;p&gt;At Anvil, we use &lt;a href="https://www.apollographql.com/docs/react/"&gt;Apollo&lt;/a&gt; to store app state from the API, and mostly adhere to the &lt;a href="https://reactpatterns.com/#container-component"&gt;Container pattern&lt;/a&gt;: there is a "Container" component at a high level doing the fetching + updating via the API, then "Presentational" component children that consume the data as props. To be a little more concrete:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Our app's pages all start out with all data for a page being fetched and stored at the &lt;code&gt;Route&lt;/code&gt; level.&lt;/li&gt;
&lt;li&gt;For complex components with a lot of changes to state, we store state at the deepest level that makes sense.&lt;/li&gt;
&lt;li&gt;We store ephemeral UI state like hover, 'active' elements, modal visibility, etc., as deep as possible.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is how we approach things, but your organization is likely different. While your approach and philosophical leanings may be different, it's helpful to understand that &lt;em&gt;the higher the state is in the component tree, the more components React will try to re-render.&lt;/em&gt; Is that an issue? If so, what are the tools to fix it? Those are hard questions. Hopefully the sections above can help give you a bit of direction.&lt;/p&gt;

&lt;h2&gt;
  
  
  Other potential solutions
&lt;/h2&gt;

&lt;p&gt;The options covered in the meat of this post can help solve many of your performance ills. But of course they not the end-all to react performance optimization. Here are a couple other quick potential solutions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Debouncing
&lt;/h3&gt;

&lt;p&gt;The most important thing to a user is perceived speed. If your app does something slow when they aren't looking, they don't care. &lt;a href="https://css-tricks.com/debouncing-throttling-explained-examples/"&gt;Debouncing&lt;/a&gt; is a way to improve perceived speed, i.e. it helps you move some actual work away from a critical part of a user interaction.&lt;/p&gt;

&lt;p&gt;A debounced function will ratelimit or group function calls into one function call over some time limit. It's often used to limit events that happen frequently in quick succession, for example keydown events or mousemove events. In those scenarios, instead of doing work on each keystroke or mouse event, it would call your event handler function when a user has stopped typing, or has stopped moving the mouse for some amount of time.&lt;/p&gt;

&lt;p&gt;Here's an example using &lt;a href="https://lodash.com/docs/4.17.15#debounce"&gt;lodash debounce&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;lodash&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;handleKeyDown&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;User stopped typing!&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Call handleKeyDown if the user has stopped&lt;/span&gt;
&lt;span class="c1"&gt;// typing for 300 milliseconds&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleKeyDownDebounced&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;debounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;handleKeyDown&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="mi"&gt;300&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;input&lt;/span&gt; &lt;span class="nx"&gt;onKeyDown&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleKeyDownDebounced&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rendering very large lists of elements
&lt;/h3&gt;

&lt;p&gt;Do you need to render several hundred or thousands of items in a list? If so, the DOM itself might be the bottleneck. If there are a very large number of elements in the DOM, the browser itself will slow. The technique to solve for this situation is a scrollable list where only the items visible to the user are rendered to the DOM.&lt;/p&gt;

&lt;p&gt;You can leverage libraries like &lt;a href="https://github.com/bvaughn/react-virtualized"&gt;react-virtualized&lt;/a&gt; or &lt;a href="https://github.com/bvaughn/react-window"&gt;react-window&lt;/a&gt; to handle this for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  You made it!
&lt;/h2&gt;

&lt;p&gt;Performance optimization is tricky work; it is filled with tradeoffs and could always be better. Hopefully this post helped add tools to your performance optimization toolbox.&lt;/p&gt;

&lt;p&gt;Before we depart, I want to stress the importance of &lt;a href="https://dev.to/blog/engineering/improve-optimize-react-render-performance-part-1"&gt;profiling your UI&lt;/a&gt; before applying any of these techniques. You should have a really good idea of which components need to be optimized before digging in. Performance optimization often comes at the expense of readability and almost always adds complexity.&lt;/p&gt;

&lt;p&gt;In some cases, blindly adding performance optimizations could actually make your UI slower. For example, it may be tempting to make everything a pure component. Unfortunately that would add overhead. If everything is a pure component, React will be doing unnecessary work comparing props on components that do not need it. Performance work is best applied only to the problem areas. Profile first!&lt;/p&gt;

&lt;p&gt;Do you have any feedback? Are you developing something cool with PDFs or paperwork automation? Let us know at &lt;a href="mailto:developers@useanvil.com"&gt;developers@useanvil.com&lt;/a&gt;. We’d love to hear from you!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>react</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Understanding SEO and ways to improve it</title>
      <dc:creator>Anvil Engineering</dc:creator>
      <pubDate>Fri, 11 Feb 2022 20:57:55 +0000</pubDate>
      <link>https://forem.com/useanvil/understanding-seo-and-ways-to-improve-it-22h9</link>
      <guid>https://forem.com/useanvil/understanding-seo-and-ways-to-improve-it-22h9</guid>
      <description>&lt;p&gt;With the abundance of digital content and distractions today, it has become increasingly tricky navigating the path to publishing content online and making sure it gets seen. Search engines have adopted complex and evolving algorithms factoring in a number of metrics to determine a site's ranking on their results page. How do you make sure your content gets seen? To answer this, we look to SEO (search engine optimization).&lt;/p&gt;

&lt;p&gt;SEO is the process of improving the metrics search engines look at to increase the ranking of a website in search results. In this post, we'll be diving into how search engines work, the foundations of SEO, and the specific changes you can make on your web app to ensure your content consistently shows up on the front page. We'll be covering the many small but incremental changes you can make that build into a noticeable impact in user experience on your site. The extra steps you take in doing so will naturally translate into search engines prioritizing your content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search engines: how do they work?
&lt;/h2&gt;

&lt;p&gt;When you type 'cats' into Google images, the search engine returns a never-ending gallery of lovely cat images. Every one of these images are known to the search engine because they have been discovered prior by one of Google's web crawlers. This step of discovering webpages by search engines is called crawling. Web crawlers work by visiting links found in online content, and are crawling the internet nonstop to discover newly published websites.&lt;/p&gt;

&lt;p&gt;Next comes indexing. Upon discovering a webpage, web crawlers must parse the data to make sense of what the page is about. Indexing involves analyzing the text, metadata, images, and video files embedded into webpages. The results are stored into a gigantic database belonging to the search engine called the index.&lt;/p&gt;

&lt;p&gt;The last step is serving. Based on the input given by the user, which in our case is 'cats', search engines query, filter, and return the most relevant webpages from its index. Serving also takes into account the user's information such as location, language, and search history.&lt;/p&gt;

&lt;p&gt;When thinking about SEO, we must consider all of these steps: crawling, indexing, and serving. We need to make it easy for search engines to do their job every step of the way. So, our web app needs to be discoverable, easy to understand, and descriptive. Once search engines find it easily, humans will too.&lt;/p&gt;

&lt;h2&gt;
  
  
  Increase crawl accessibility
&lt;/h2&gt;

&lt;p&gt;Crawl accessibility is important for the discoverability of your website to web crawlers, and the best way of improving that metric is providing sitemaps.  Crawlers automatically traverse through webpages regardless of whether sitemaps are provided, but including them provides a number of advantages. First, pages listed in sitemaps are prioritized by crawlers, giving your webpages earlier exposure and more frequent indexing by search engines. This is especially important if your content is rapidly evolving or not close in proximity to sites with heavy traffic. Second, sitemaps enable the communication of additional information to crawlers, such as update frequency and image or video metadata. Providing crawlers with more data is especially helpful for pages with lots of non-textual content, as crawlers typically rely on text for context.&lt;/p&gt;

&lt;p&gt;There are several formats for sitemaps: XML, RSS, and text. Different search engines may accept different formats.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;urlset&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.sitemaps.org/schemas/sitemap/0.9"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;http://www.example.com/foo.html&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;lastmod&amp;gt;&lt;/span&gt;2020-12-04&lt;span class="nt"&gt;&amp;lt;/lastmod&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;changefreq&amp;gt;&lt;/span&gt;monthly&lt;span class="nt"&gt;&amp;lt;/changefreq&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;priority&amp;gt;&lt;/span&gt;0.9&lt;span class="nt"&gt;&amp;lt;/priority&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/urlset&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;An example of a sitemap in XML format.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;As you can see, the code snippet shown communicates to crawlers about the date the webpage was last modified, the likely frequency of changes to the page, and priority of the webpage's URL relative to other pages on the domain.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;urlset&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.sitemaps.org/schemas/sitemap/0.9"&lt;/span&gt;
        &lt;span class="na"&gt;xmlns:image=&lt;/span&gt;&lt;span class="s"&gt;"http://www.google.com/schemas/sitemap-image/1.1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;http://example.org/page1.html&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;image:image&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;image:loc&amp;gt;&lt;/span&gt;http://example.org/image1.jpg&lt;span class="nt"&gt;&amp;lt;/image:loc&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/image:image&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;http://example.org/page2.html&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;image:image&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;image:loc&amp;gt;&lt;/span&gt;http://example.org/image2.jpg&lt;span class="nt"&gt;&amp;lt;/image:loc&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;image:caption&amp;gt;&lt;/span&gt;Cats in a pet-friendly office&lt;span class="nt"&gt;&amp;lt;/image:caption&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;image:geo_location&amp;gt;&lt;/span&gt;San Francisco, CA&lt;span class="nt"&gt;&amp;lt;/image:geo_location&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;image:title&amp;gt;&lt;/span&gt;Office cats&lt;span class="nt"&gt;&amp;lt;/image:title&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;image:license&amp;gt;&lt;/span&gt;http://example.org/image-license&lt;span class="nt"&gt;&amp;lt;/image:license&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/image:image&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/urlset&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;An example sitemap for two webpages with images in XML format.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.sitemaps.org/" rel="noopener noreferrer"&gt;Visit this page&lt;/a&gt; to learn more about sitemaps and its documentation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prevent crawling on irrelevant data
&lt;/h2&gt;

&lt;p&gt;In contrast to encouraging crawling, we need rules to disable crawlers from accessing sensitive, duplicate, or unimportant content. There are numerous scenarios where we want content hidden. There may be pages with private data on your domain you want hidden from search results. In addition, it's good practice to prevent crawlers from seeing repeated content in your web app, as it can be mistaken for spam thus lowering your ranking in search results. Your webpage may have also embedded content from third party sites which can be irrelevant to your topic.&lt;/p&gt;

&lt;p&gt;Multiple approaches are available for hiding content from search engines, such as removing the content directly, requiring passwords for certain webpages, or using the &lt;code&gt;noindex&lt;/code&gt; directive. Adding a &lt;code&gt;robots.txt&lt;/code&gt; file to your web app is the most flexible approach.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User-agent: Googlebot
Disallow: /private/media/

User-agent: *
Allow: /

Sitemap: http://useanvil.com/sitemap.xml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;An example &lt;code&gt;robots.txt&lt;/code&gt; file&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The above example prevents Google search's web crawler from accessing routes under &lt;code&gt;/private/media/&lt;/code&gt;, but all other visitors are given full site access. It's important to allow crawlers access to JavaScript, CSS, and image files with the exception of sensitive data to avoid negative impacts on indexing. And finally, the last line tells the crawler where the sitemap can be found.&lt;/p&gt;

&lt;p&gt;The file must be named &lt;code&gt;robots.txt&lt;/code&gt; and placed at the root of the website host for crawlers to find. &lt;code&gt;robots.txt&lt;/code&gt; works by specifying rules, with each rule involving a group specified using &lt;code&gt;User-agent&lt;/code&gt; and their permissions specified using &lt;code&gt;Allow&lt;/code&gt; or &lt;code&gt;Disallow&lt;/code&gt;. Only one rule may apply to a group at a time.&lt;/p&gt;

&lt;p&gt;For more information regarding &lt;code&gt;robots.txt&lt;/code&gt; files, &lt;a href="https://developers.google.com/search/docs/advanced/robots/create-robots-txt" rel="noopener noreferrer"&gt;refer to these docs&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;noindex&lt;/code&gt; directive
&lt;/h3&gt;

&lt;p&gt;Besides the &lt;code&gt;robots.txt&lt;/code&gt; approach, using the &lt;code&gt;noindex&lt;/code&gt; directive is just as effective. &lt;code&gt;noindex&lt;/code&gt; can be placed within a meta tag in HTML or an HTTP response header, telling web crawlers indexing the webpage to prevent the page from being shown in search results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;404 Page not found&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"robots"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"noindex"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
  …
&lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;404 page should not be shown in search results&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;HTTP/2 200 OK
…
X-Robots-Tag: noindex
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Response body will not be shown in search results. Body can include HTML, image, video, PDF files.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developers.google.com/search/docs/advanced/crawling/block-indexing" rel="noopener noreferrer"&gt;Refer to this page&lt;/a&gt; for more information.&lt;/p&gt;

&lt;h3&gt;
  
  
  Return helpful HTTP status codes
&lt;/h3&gt;

&lt;p&gt;Web crawlers rely on status codes to determine whether a page should be crawled and if it contains meaningful content. Make use of '301' (moved permanently), '401' (unauthorized), or '404' (not found) statuses so crawlers know how to update the index. Google's web crawler, for example, doesn't save webpages that respond with 4xx or 5xx into the index.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make indexing easy
&lt;/h2&gt;

&lt;p&gt;Once web crawlers have found your website, you want your webpages to be easy to understand. This involves using concise and unique page titles and descriptions. Each webpage should have a title that is focused on what the content is about and is distinguishable. It's also a good idea to include the business name or location if applicable.&lt;/p&gt;

&lt;p&gt;Make use of title and meta tags. Titles should include seven to eight words at most, to avoid any text cut off when shown in search results. Descriptions should include a hook to grab users' attention and get clicks. Having a one to three  sentence description is optimal.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;Minimizing webpack bundle size - Anvil&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"description"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"Learn how to minimize your Webpack bundle size by following these best practices, ensuring an optimal user experience."&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fai76c4abpdesn29t8v0j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fai76c4abpdesn29t8v0j.png" alt="Google search result"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;First page on Google results&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Performance
&lt;/h3&gt;

&lt;p&gt;Besides the basics such as title and description, user experience plays a huge role. Factors such as performance and web accessibility belong under that category. Metrics such as 'first contentful paint' and 'time to interactive' factor into whether users will remain on the site. You can gather these metrics for your web app using &lt;a href="https://developers.google.com/web/tools/lighthouse" rel="noopener noreferrer"&gt;Lighthouse&lt;/a&gt; made available by Google.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58kjk3q85m3th79cw0ob.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F58kjk3q85m3th79cw0ob.png" alt="Lighthouse performance metrics"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Performance metrics for Anvil's main page&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can improve your performance metrics by compressing images, decluttering your files, code splitting, using lighter dependencies, and so on. If you use Webpack to compile your web app, I highly recommend taking a look at my post about &lt;a href="https://www.useanvil.com/blog/engineering/minimizing-webpack-bundle-size/" rel="noopener noreferrer"&gt;Minimizing webpack bundle size&lt;/a&gt;, which covers the subject comprehensively with solutions.&lt;/p&gt;
&lt;h3&gt;
  
  
  Web accessibility
&lt;/h3&gt;

&lt;p&gt;Enabling your content to be accessible to everyone, including those with impairments, can provide a considerable boost to your ranking. Best practices to adopt include using header tags (i.e. &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;h2&amp;gt;&lt;/code&gt;), setting &lt;code&gt;alt&lt;/code&gt; attributes to images, and providing labels to control elements (e.g. &lt;code&gt;&amp;lt;button&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;checkbox&amp;gt;&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;h1&amp;gt;&lt;/span&gt;Yellow Cab Inc.&lt;span class="nt"&gt;&amp;lt;/h1&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"https://yellowcab.com/assets/logo"&lt;/span&gt; &lt;span class="na"&gt;alt=&lt;/span&gt;&lt;span class="s"&gt;"Yellow Cab Inc. logo"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;h2&amp;gt;&lt;/span&gt;Contact us&lt;span class="nt"&gt;&amp;lt;/h2&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;label&lt;/span&gt; &lt;span class="na"&gt;for=&lt;/span&gt;&lt;span class="s"&gt;"fullName"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Full name:&lt;span class="nt"&gt;&amp;lt;/label&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"fullName"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;button&lt;/span&gt; &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"submit"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;Submit&lt;span class="nt"&gt;&amp;lt;/button&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Make use of header tags, the alt attribute, and labels.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9q8behx9jki7s674togx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9q8behx9jki7s674togx.png" alt="Lighthouse accessibility metrics"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Accessibility metrics&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Mobile-friendly
&lt;/h3&gt;

&lt;p&gt;Users expect websites to be usable on mobile, and having a web app that is responsive to that format is crucial for online presence. The most common mobile strategy is &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design" rel="noopener noreferrer"&gt;responsive web design&lt;/a&gt;. With this approach, telling the browser how to adjust content on the viewport is necessary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The browser is instructed to handle the viewport's dimensions. The width of the webpage is set to the device's width, and with a zoom ratio of 1.0.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;A good way to check whether your web app is ready for use on mobile devices is the &lt;a href="https://search.google.com/test/mobile-friendly" rel="noopener noreferrer"&gt;Mobile-Friendly Test&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Optimize images
&lt;/h3&gt;

&lt;p&gt;Always use the &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; tag to display pictures instead of alternate methods such as CSS. Crawlers respond positively to images having &lt;code&gt;alt&lt;/code&gt; attributes in case the image cannot be found. Compress your images so they don't take forever to load and lazy load images that have a high file size. Image filenames also matter, as it gives crawlers context on what the image is. Also, avoid using images as links.&lt;/p&gt;

&lt;p&gt;Ex: use 'dog-in-office.png'  instead of 'dog1.png'.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use simple and clear URLs
&lt;/h3&gt;

&lt;p&gt;It may not be apparent, but users do pay attention to the format of URLs. Structure your routes so that they are organized, concise, and clear. Having unstructured URLs can prevent users from clicking and sharing.&lt;/p&gt;

&lt;p&gt;Ex: use &lt;code&gt;https://useanvil.com/docs/api/getting-started&lt;/code&gt;, not &lt;code&gt;https://useanvil.com/folder-1/file-2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;While on the topic of URLs, I recommend creating a 404 not found page for your web app. It's almost guaranteed that someone will hit a broken link sooner or later.&lt;/p&gt;

&lt;h2&gt;
  
  
  Provide useful content
&lt;/h2&gt;

&lt;p&gt;I've suggested all the changes you can make to your code to boost your SEO ranking, but the central factor is providing good content. Make sure your blog, service, newsletter, or whatever it is provides information valuable to users. Using keywords, encouraging sharing, adding links to other pieces of useful information, and understanding your audience are all factors to consider.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;We've covered the concept of SEO, the steps involved in displaying a webpage on search results, increasing web app crawl accessibility, optimizing code in handling indexing, and providing a better user experience. We also looked into SEO tools and general web development best practices. With these concepts introduced into your code, you can worry less about whether your content will be discovered.&lt;/p&gt;

&lt;p&gt;We've applied these practices to our code at Anvil, and believe sharing our experience helps everyone in creating awesome products. If you're developing something cool with PDFs or paperwork automation, let us know at &lt;a href="//mailto:developers@useanvil.com"&gt;developers@useanvil.com&lt;/a&gt;. We'd love to hear from you.&lt;/p&gt;

</description>
      <category>seo</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Introduction to the Twelve-Factor App Part 3</title>
      <dc:creator>Anvil Engineering</dc:creator>
      <pubDate>Fri, 11 Feb 2022 20:53:19 +0000</pubDate>
      <link>https://forem.com/useanvil/introduction-to-the-twelve-factor-app-part-3-3oid</link>
      <guid>https://forem.com/useanvil/introduction-to-the-twelve-factor-app-part-3-3oid</guid>
      <description>&lt;h1&gt;
  
  
  12 Factor App Blog Post Part 3
&lt;/h1&gt;

&lt;p&gt;Summary: Make your toy web apps more robust and manageable by following the Twelve-Factor App methodology.&lt;/p&gt;

&lt;p&gt;This is the third and last part in a series of posts detailing the &lt;a href="https://12factor.net/"&gt;12 Factor App&lt;/a&gt;. In the last&lt;br&gt;
post we looked at:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Build, release, and run stages and how segmenting your development processes can open up possibilities in terms of
automation&lt;/li&gt;
&lt;li&gt;Explored the benefits of running your app as a stateless process&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you need a refresher or would like to take a look at the previous posts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.useanvil.com/blog/engineering/introduction-twelve-factor-app/"&gt;Introduction to the Twelve-Factor App&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.useanvil.com/blog/engineering/introduction-twelve-factor-app-pt2"&gt;Introduction to the Twelve-Factor App Part 2&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As with the last post, most of the remaining factors come about as downstream results from implementing the previous&lt;br&gt;
factors. If you’ve been following along, many of these will be on the easier side of implementing – or it may even be&lt;br&gt;
done already if you’re using certain services.&lt;/p&gt;

&lt;h2&gt;
  
  
  VII. Port binding
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Export services via port binding - &lt;a href="https://12factor.net/port-binding"&gt;https://12factor.net/port-binding&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once your application becomes more or less&lt;br&gt;
stateless (&lt;a href="https://www.useanvil.com/blog/engineering/introduction-twelve-factor-app/"&gt;Factors II, III, IV&lt;/a&gt;, you’re now&lt;br&gt;
able to think of your application itself as a backing service. One of the last steps would be to export HTTP as a&lt;br&gt;
service by binding to a port.&lt;/p&gt;

&lt;p&gt;For example, when developing a frontend application, you may be familiar with a development server listening on your&lt;br&gt;
local port 3000 (i.e. &lt;code&gt;http://localhost:3000&lt;/code&gt;). Exporting your app as a service would work the same. Some frameworks may&lt;br&gt;
have it built-in already and can be deployed with a simple &lt;code&gt;node app.js&lt;/code&gt;. You may have to look into adding additional&lt;br&gt;
dependencies such as uWSGI/Gunicorn in the Python world.&lt;/p&gt;

&lt;h2&gt;
  
  
  VIII. Concurrency
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Scale out via the process model - &lt;a href="https://12factor.net/concurrency"&gt;https://12factor.net/concurrency&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The obvious first thought when attempting to scale your app is “Can we just run more instances of the app?” If you’ve&lt;br&gt;
been following along so far and implemented all the previous factors, the answer should be “Yes!*”&lt;/p&gt;

&lt;p&gt;* But you should still look at the remaining factors :)&lt;/p&gt;

&lt;p&gt;Some of the main hurdles at this point will be to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Assess your infrastructure and see if this can be done automatically, like with Kubernetes. Scaling up and down
automatically, depending on usage, can save your site when unexpected traffic hits.&lt;/li&gt;
&lt;li&gt;Assess your code and backing services. If a bunch of users hit an endpoint at the same time on multiple app instances,
will something catch on fire? Can your database support all the new connections/queries from the new instance?&lt;/li&gt;
&lt;li&gt;Start thinking about any additional costs when new instances are created. How much additional resources your entire
application plus infrastructure will start to consume?&lt;/li&gt;
&lt;li&gt;Think about how data and user flow will work when a new instance is created &lt;em&gt;and&lt;/em&gt; destroyed (covered in IX.
Disposability).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  IX. Disposability
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Maximize robustness with fast startup and graceful shutdown - &lt;a href="https://12factor.net/disposability"&gt;https://12factor.net/disposability&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Since your app is stateless, you won’t have to worry about any stored data in your app instance as anything important is&lt;br&gt;
stored in the cloud and/or in a database. Going hand-in-hand with concurrency above, this gives you the freedom of&lt;br&gt;
creating and destroying instances at any time. You can create new instances to handle more load on your application and&lt;br&gt;
also destroy any excess to avoid incurring extra infrastructure costs.&lt;/p&gt;

&lt;p&gt;When thinking about disposability, your app should be resilient against interruptions at any point in its lifecycle.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What will your app do when a long-running request gets cancelled?&lt;/li&gt;
&lt;li&gt;Will your database be left with incomplete data?&lt;/li&gt;
&lt;li&gt;Will your job queue be left with stale jobs that never finished?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Addressing these sorts of potential problems may lead to a lot of work, but will definitely be worth it since the work&lt;br&gt;
you do here will also help mitigate any problems when more catastrophic app failures happen.&lt;/p&gt;

&lt;p&gt;Again, if using a Kubernetes cluster, a lot of this is handled automatically, however, you will still need to think&lt;br&gt;
about your codebase and backing services and how they will react to sudden interruptions.&lt;/p&gt;

&lt;h2&gt;
  
  
  X. Dev/prod parity
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Keep development, staging, and production as similar as possible - &lt;a href="https://12factor.net/dev-prod-parity"&gt;https://12factor.net/dev-prod-parity&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In a modern development environment, this is much less of an issue because of the popularity of Docker and automation.&lt;br&gt;
Nevertheless, it’s still important to try to keep development and production environments as similar as possible. Of&lt;br&gt;
course, this does not mean you should be developing on the live production database, but if your app in production uses&lt;br&gt;
PostgreSQL, you should also be using PostgreSQL in development, and so on.&lt;/p&gt;

&lt;p&gt;The most common way of achieving this is to use Docker. Docker makes this easy by making development environments&lt;br&gt;
extremely reproducible which leads to less ramp up time for new team members and more time working on your app’s&lt;br&gt;
features. Docker also makes it easy to have the same (or nearly the same) backing services available for your app in&lt;br&gt;
development with docker-compose.&lt;/p&gt;

&lt;p&gt;Keeping development and production as identical as possible should:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Decrease backing service issues during deployment.&lt;/li&gt;
&lt;li&gt;Give more confidence to developers that their code will work the way it does in their own development environment.&lt;/li&gt;
&lt;li&gt;Allow higher chance of reproducibility for any issues seen on production.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  XI. Logs
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Treat logs as event streams - &lt;a href="https://12factor.net/logs"&gt;https://12factor.net/logs&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With smaller, earlier stage apps, logging is most likely an afterthought, or not as robust, so this may not seem that&lt;br&gt;
important. In a 12 factor app, logs are treated as &lt;em&gt;event streams&lt;/em&gt;. This can be done through external services such as&lt;br&gt;
Papertrail, or possibly already handled by your app’s deployment platform such as Heroku or Google Cloud Platform.&lt;/p&gt;

&lt;p&gt;Essentially 12 factor apps should only be concerned with sending log output to the system’s &lt;code&gt;stdout&lt;/code&gt;. This allows for&lt;br&gt;
other backing services or apps to manage log data and whether or not to store it. Again, this keeps the app stateless as&lt;br&gt;
it decouples log storage and it also centralizes all log data, which is especially useful when there’s more than one app&lt;br&gt;
instance up.&lt;/p&gt;

&lt;p&gt;Logging itself, as well as best practices, what to log, etc. is a whole different beast, but good logging should allow&lt;br&gt;
for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finding specific events in the past.&lt;/li&gt;
&lt;li&gt;Large-scale graphing of trends (such as requests per minute).&lt;/li&gt;
&lt;li&gt;Active alerting according to user-defined heuristics (such as an alert when the quantity of errors per minute exceeds
a certain threshold). &lt;a href="https://12factor.net/logs"&gt;https://12factor.net/logs&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  XII. Admin processes
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Run admin/management tasks as one-off processes - &lt;a href="https://12factor.net/admin-processes"&gt;https://12factor.net/admin-processes&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;More likely than not, your application will have to run admin processes every now and then. An example of this includes&lt;br&gt;
database migrations to change table structures and/or data. In a 12 factor app, these admin processes should be stored&lt;br&gt;
in the same codebase as the app, and it should also run in the same environment as the app.&lt;/p&gt;

&lt;p&gt;This prevents extra dependencies and unexpected issues from things such as one-off shell scripts. Being in the same&lt;br&gt;
codebase, and in the same environment, we’re able to control the one-off processes’s execution to ensure it runs as&lt;br&gt;
expected.&lt;/p&gt;

&lt;p&gt;As examples: In the node world, you could have &lt;code&gt;npm&lt;/code&gt; or &lt;code&gt;yarn&lt;/code&gt; scripts that would bootstrap part of your application to&lt;br&gt;
run these one-off tasks. Also in the Python world, Django has its own REPL and framework to create your own custom&lt;br&gt;
commands which run via &lt;code&gt;python manage.py &amp;lt;YOUR_COMMAND&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A caveat: while doing research for this, some articles mention that having an REPL available in production (which is&lt;br&gt;
what 12factor.net recommends) is a potential security concern as it gives almost complete access to your entire&lt;br&gt;
application. Depending on how your infrastructure is designed, you may also want to incorporate more security for&lt;br&gt;
one-off admin processes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Twelve-Factor_App_methodology"&gt;According to Wikipedia&lt;/a&gt; the Twelve-Factor app is over 10&lt;br&gt;
years old(!) at the time of writing this post. As this post was written, it’s incredible how many of these concepts are&lt;br&gt;
still absolutely valuable and used in practice in the modern development world we’re in today. We here at Anvil follow&lt;br&gt;
nearly all of the 12 factors and our development team performs like a well oiled machine because of it.&lt;/p&gt;

&lt;p&gt;Are you developing your apps with the 12 Factor methodology in mind? Are you using or want to use Anvil as a backing&lt;br&gt;
service? If you’re developing something cool with PDFs or paperwork automation, let us know at &lt;a href="mailto:developers@useanvil.com"&gt;developers@useanvil.com&lt;/a&gt;.&lt;br&gt;
We’d love to hear from you.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Image Processing in Gatsby</title>
      <dc:creator>Anvil Engineering</dc:creator>
      <pubDate>Fri, 14 Jan 2022 20:26:55 +0000</pubDate>
      <link>https://forem.com/useanvil/image-processing-in-gatsby-4ioj</link>
      <guid>https://forem.com/useanvil/image-processing-in-gatsby-4ioj</guid>
      <description>&lt;p&gt;According to &lt;a href="https://almanac.httparchive.org/en/2019/page-weight"&gt;The HTTP Archive&lt;/a&gt;, 90% of the pages on the web contain about 7MB of data, with 5.2MB being unoptimized images. That means no matter what you do to your site, if your images aren't optimized then your site is falling behind in terms of performance alone. Add in accessibility concerns and responsive design, and you have a recipe for disaster.&lt;/p&gt;

&lt;p&gt;Luckily, Gatsby handles most image optimization problems for us. Out of the box, Gatsby compresses your images, converts them to modern formats (e.g. webp), and adds cache-control headers to them. With Gatsby's newest &lt;a href="https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-plugin-image/"&gt;image plugin&lt;/a&gt;, you can also set up responsive images for your entire site. The topic of this blog post is not to discuss these optimizations themselves (look out for a future blog post on that), but rather how Gatsby does all that ‘magic' for you and how you can get the most out of Gatsby's image processing.&lt;/p&gt;

&lt;p&gt;Ready to dive in?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Basics
&lt;/h2&gt;

&lt;p&gt;First and foremost, make sure you understand image formats.&lt;/p&gt;

&lt;h3&gt;
  
  
  Image formats
&lt;/h3&gt;

&lt;p&gt;The old school, raster image formats are PNG and JPEG (or JPG). These image formats are best suited for actual photographs and pictures because the pixels in these images are explicitly defined.&lt;/p&gt;

&lt;p&gt;We also have vector images, such as SVG. These image formats are for everything else that isn't a photograph. Icons and designed graphics come to mind here. SVGs should make up most of your site's images and be used whenever possible. They have huge benefits over raster image formats, such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Smaller file sizes&lt;/em&gt;. SVGs define shapes, lines, etc. and let the browser fill those in. Since the images don't need to explicitly define each pixel, file sizes are much smaller.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Inherently responsive&lt;/em&gt;. Again because of not explicitly defining pixels, SVGs will look nice and clean on any screen size. You can dynamically resize them too!&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Can be written inline&lt;/em&gt;. SVGs don't actually have to be assets. You can write them inline in your HTML (or React).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lastly, we have the new school raster image formats, WebP and AVIF. These follow the same usage guidelines as PNG and JPEG: only use them for photographs/images. The difference with these image formats is they are better for compression and quality.&lt;/p&gt;

&lt;h3&gt;
  
  
  Importing assets in Gatsby
&lt;/h3&gt;

&lt;p&gt;Gatsby leverages a widely-used module bundler called &lt;em&gt;webpack&lt;/em&gt;. Through webpack, you as a developer can import assets directly in your JavaScript files, like the example below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="c1"&gt;// path can be absolute (like below) or relative to the current file&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;heroAsset&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;~/dev/super-sophisticated-site/hero-asset.png&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;MyComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;render&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;img&lt;/span&gt; &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;heroAsset&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Super Sophisticated's Hero Asset&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Webpack is what enables line 3, where we import an image directly into JS&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This import syntax, enabled by webpack, automatically minifies and bundles your assets, pushes any errors to build time instead of run time, and sets up caching on your assets.&lt;/p&gt;

&lt;p&gt;What's also important to note here for image optimization is that these imports are where &lt;a href="https://www.gatsbyjs.com/docs/how-to/images-and-media/importing-assets-into-files/#importing-assets-with-webpack"&gt;Gatsby applies a conversion for images to data URIs if the image is less than 10,000 bytes&lt;/a&gt;. It's more cost effective to embed the data directly in HTML in this case - the less network requests, the better!&lt;/p&gt;

&lt;h3&gt;
  
  
  The &lt;code&gt;static&lt;/code&gt; folder
&lt;/h3&gt;

&lt;p&gt;The last piece of the basics of images in Gatsby, is the &lt;code&gt;static&lt;/code&gt; folder. It sits at the top-level directory of your project, and serves as an escape hatch for everything I talked about in the previous section on importing assets.&lt;/p&gt;

&lt;p&gt;We do not use the &lt;code&gt;static&lt;/code&gt; folder here at Anvil, and neither should you. All the optimizations above improve your site's performance, usability, and maintainability drastically, so only use this folder if you really need to. &lt;a href="https://www.gatsbyjs.com/docs/how-to/images-and-media/static-folder/#when-to-use-the-static-folder"&gt;Gatsby has a good list on when you should use the &lt;code&gt;static&lt;/code&gt; folder&lt;/a&gt;, but in general it's used for when you want to keep the name of an asset the same at run time or if you want to serve a custom script.&lt;/p&gt;

&lt;h2&gt;
  
  
  Under the hood
&lt;/h2&gt;

&lt;p&gt;With the basics out of the way, let's get into what powers Gatsby's system to perform actions like data sourcing, dynamic image processing, and generating responsive images.&lt;/p&gt;

&lt;h3&gt;
  
  
  Data layer
&lt;/h3&gt;

&lt;p&gt;At the core of Gatsby is the data layer. This is built into Gatsby and provides a uniform interface to access any data you need for your site.&lt;/p&gt;

&lt;p&gt;Most static sites are article-based. But how do you host your content? Do you opt for a CMS like &lt;a href="https://wordpress.com/"&gt;WordPress&lt;/a&gt;, &lt;a href="https://www.sanity.io/"&gt;Sanity&lt;/a&gt;, or &lt;a href="https://www.contentful.com/"&gt;Contentful&lt;/a&gt;? Or what if you want something simple, like keeping your content in markdown alongside your code? There are many places for your content to live, and the questions above are only for static content. Many more questions arise when user-specific, dynamic content is involved, likely requiring a database.&lt;/p&gt;

&lt;p&gt;Designing the right solution for your content and site is complex, but the data layer Gatsby provides is a way to simplify accessing your data regardless of its &lt;strong&gt;source&lt;/strong&gt;. Gatsby also has ways to &lt;strong&gt;transform&lt;/strong&gt; your data nodes after sourcing it into the data layer, so by the time you access the data on your site, it is exactly in the format we want: optimized for production.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hEHjr7gl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wpbwugvzv1e9uzulnh6a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hEHjr7gl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wpbwugvzv1e9uzulnh6a.png" alt="Gatsby Data Layer" width="880" height="566"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The diagram above uses 'source plugins' to gather data. We'll take a deeper look at plugins later on, but for now let's start an example of sourcing data using the &lt;code&gt;gatsby-source-filesystem&lt;/code&gt; plugin.&lt;/p&gt;

&lt;p&gt;Let's say we are starting a blog website that will feature technical writers. Since the blog authors will be technical, we aren't going to need a CMS; we are comfortable with the authors writing in markdown and potentially even having access to the entire codebase. With this in mind, all we need is markdown articles served right from the same repository as our code. This will be our directory structure:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;super-sophisticated-technical-website
    | - src
        | - components
        | - pages
    | - markdown-articles
        | - blog-posts
    | - gatsby-config.js
    | - gatsby-node.js
    | - package.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Super Sophisticated™'s directory structure&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With this directory structure, the configuration for our technical blog will be as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;siteMetadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;siteName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Super Sophisticated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The most sophisticated business&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Reduce costs and unlock growth by transitioning from paper and PDF-based processes to simple and flexible online workflows.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;website,sophisticated,super,gatsby&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-source-filesystem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/markdown-articles/blog-posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blog-posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The plugins section uses &lt;code&gt;gatsby-source-filesystem&lt;/code&gt; to load our markdown blog posts into Gatsby's data layer.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;While not the topic of this blog post, the data in your &lt;code&gt;gatsby-config.js&lt;/code&gt;'s &lt;code&gt;siteMetadata&lt;/code&gt; field gets automatically loaded into the data layer. So &lt;code&gt;siteName&lt;/code&gt;, &lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, and &lt;code&gt;keywords&lt;/code&gt; are all accessible throughout your site - this is useful for setting HTML &lt;code&gt;meta&lt;/code&gt; tags for all pages.&lt;/p&gt;

&lt;h4&gt;
  
  
  Accessing your data
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://graphql.org/"&gt;GraphQL&lt;/a&gt; is how you access your data from Gatsby's data layer. There are two ways to query for data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Page queries&lt;/li&gt;
&lt;li&gt;"Building block" components' static query&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you are unfamiliar with GraphQL, I highly recommend you take the time to learn it. GraphQL makes data querying much more efficient than REST endpoints, and maps to any data you need within your data model. If you're coming from REST and need a place to start, we have a &lt;a href="https://dev.to/blog/engineering/graphql-for-rest-developers/"&gt;blog post on consuming GraphQL APIs just for you&lt;/a&gt;. GraphQL uses REST under the hood, after all :)&lt;/p&gt;

&lt;p&gt;Back to Gatsby and its GraphQL API. To start accessing your data, you will need to use the named import &lt;code&gt;graphql&lt;/code&gt; from &lt;code&gt;gatsby&lt;/code&gt; for both page queries and static queries. To start, let's look at a page query for a blog post template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;RehypeReact&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rehype-react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyGatsbyPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="cm"&gt;/* AST renderer we use at Anvil: https://github.com/rehypejs/rehype-react */&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;renderAst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;RehypeReact&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;Compiler&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;By&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blog-content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;renderAst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;htmlAst&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;MyGatsbyPage&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pageQuery&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
    query BlogPostByPath($slug: String!) {
        site {
            siteMetadata {
                siteName
                title
                description
                keywords
            }
        }
        markdownRemark(frontmatter: { path: { eq: $slug } }) {
            htmlAst
            frontmatter {
                date
                title
                summary
                author
                image {
                    publicURL
                    childImageSharp {
                        gatsbyImageData
                    }
                }
            }
        }
    }
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Accessing data via a Gatsby page query, using GraphQL&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Page queries, like the one above, are exported in the page component. Gatsby recognizes the exported const &lt;code&gt;pageQuery&lt;/code&gt; and at build time will execute your query. The resulting data from the query is then passed into your page component (in our case, &lt;code&gt;MyGatsbyPage&lt;/code&gt;) as a prop called &lt;code&gt;data&lt;/code&gt;. You can now access any data from your query directly in your component!&lt;/p&gt;

&lt;p&gt;The above example is &lt;em&gt;supposed&lt;/em&gt; to be simple to show how page queries work... so for understanding this section, just focus on the &lt;code&gt;export const pageQuery&lt;/code&gt; part and how we are able to use the prop &lt;code&gt;data&lt;/code&gt; with data directly from the data layer. The other parts (&lt;code&gt;markdownRemark&lt;/code&gt;, &lt;code&gt;frontmatter&lt;/code&gt;, &lt;code&gt;htmlAst&lt;/code&gt;, and &lt;code&gt;childImageSharp&lt;/code&gt;) are from Gatsby plugins to make blog posts from markdown work and to enable responsive images. We'll talk about plugins in a bit!&lt;/p&gt;

&lt;p&gt;As a note, the syntax I used in getting the variable &lt;code&gt;data&lt;/code&gt; is called &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment"&gt;destructuring&lt;/a&gt;. The equivalent example without destructuring would be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;MyGatsbyPage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;

    &lt;span class="cm"&gt;/* AST renderer we use at Anvil: https://github.com/rehypejs/rehype-react */&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;renderAst&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nx"&gt;RehypeReact&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;createElement&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}).&lt;/span&gt;&lt;span class="nx"&gt;Compiler&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;date&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;By&lt;/span&gt; &lt;span class="nx"&gt;$&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;author&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;p&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;frontmatter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/p&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blog-content&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;renderAst&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;htmlAst&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Accessing the data prop without destructuring&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The other way to access data is in what Gatsby calls 'building block' components. These components aren't anything special; they just aren't page components… which makes them components you reuse anywhere and everywhere possible. Since they aren't page components, Gatsby has provided the &lt;code&gt;StaticQuery&lt;/code&gt; component (old school way, made for class components) and the &lt;code&gt;useStaticQuery&lt;/code&gt; hook (new school way, made for function components). The &lt;code&gt;useStaticQuery&lt;/code&gt; is much cleaner and simpler to use, so let's do an example with it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useStaticQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useStaticQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
    query {
      site {
        siteMetadata {
          title
                    description
        }
      }
    }
  `&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;header&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h1&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;siteMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;title&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h1&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;            &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h3&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;site&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;siteMetadata&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h3&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/header&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nx"&gt;Header&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Accessing data in a non-page component, using the &lt;code&gt;useStaticQuery&lt;/code&gt; hook&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Using this hook isn't much different than the page query, the only difference is the data is retrieved as part of the component itself.&lt;/p&gt;

&lt;p&gt;Now that you know the difference between the two types of queries, which should you use? Page queries are easier to spot. But 'building block' components are a bit trickier. When you create a new component that needs data and is not just presentational, ask yourself where the data is coming from.&lt;/p&gt;

&lt;p&gt;Page queries actually cover most cases because you can pass down the queried data to your reusable components. The only time you should use a static query is if the component should &lt;em&gt;always&lt;/em&gt; use your site's data independently of any page. A good example is your site's title or any site-wide configuration you set. Using static queries this way helps isolate data querying to the spot it's actually needed (in that building block component) and modularize your site (consumers of the component don't need to know data querying is happening).&lt;/p&gt;

&lt;p&gt;Take the &lt;code&gt;Header&lt;/code&gt; component above for example; the header of our site will never change - it will &lt;em&gt;always&lt;/em&gt; have the title and description of our site. It's page independent! As such, we use &lt;code&gt;useStaticQuery&lt;/code&gt; to get the data, and now all consumers of the &lt;code&gt;Header&lt;/code&gt; component don't care about its internals; developers just use the component and it works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Plugins
&lt;/h3&gt;

&lt;p&gt;In the data layer section we configured the &lt;code&gt;gatsby-source-filesystem&lt;/code&gt; plugin. But what are Gatsby plugins even for? There are two core reasons for the plugin system:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Modularity&lt;/em&gt;. Even though our example sources data from the filesystem, many other Gatsby-powered sites don't need that functionality. They either source from a CMS, a database, or don't source data at all.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Unified interface&lt;/em&gt;. Gatsby is an open source web framework made of many other technologies, like React, webpack, and babel. Customizing and optimizing your site yourself is a long process and oftentimes is cognitive overload; plugins provide enhancements to the underlying technology for us and provide an easier interface to customize each plugin via &lt;code&gt;gatsby-config.js&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Gatsby provides official plugins, like &lt;code&gt;gatsby-source-filesystem&lt;/code&gt;, and also has community plugins written by open source developers in the Gatsby community. The rest of this blog post will be covering the plugins you need for optimal image processing.&lt;/p&gt;

&lt;p&gt;One note on plugins, you'll notice I highlighted the data layer's sourcing and transforming of data in the data layer section. That is because those terms are directly related to certain plugins in the Gatsby ecosystem: plugins used to source data into the data layer are named &lt;code&gt;gatsby-source-&amp;lt;whatever_source_here&amp;gt;&lt;/code&gt; and plugins used to transform data while in the data layer are named &lt;code&gt;gatsby-transformer-&amp;lt;whatever_file_format_here&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Examples of source plugins:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.com/plugins/gatsby-source-filesystem/"&gt;&lt;code&gt;gatsby-source-filesystem&lt;/code&gt;&lt;/a&gt; - source data from the filesystem&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.com/plugins/gatsby-source-contentful/"&gt;&lt;code&gt;gatsby-source-contentful&lt;/code&gt;&lt;/a&gt; - source data from the Contentful CMS&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.com/plugins/gatsby-source-pg/"&gt;&lt;code&gt;gatsby-source-pg&lt;/code&gt;&lt;/a&gt; - source data from your PostgreSQL database&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.com/plugins/gatsby-source-graphql/"&gt;&lt;code&gt;gatsby-source-graphql&lt;/code&gt;&lt;/a&gt; - source data from other GraphQL APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Examples of transformer plugins:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.com/plugins/gatsby-transformer-json/"&gt;&lt;code&gt;gatsby-transformer-json&lt;/code&gt;&lt;/a&gt; - transforms .json files into JavaScript objects&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.com/plugins/gatsby-transformer-csv/"&gt;&lt;code&gt;gatsby-transformer-csv&lt;/code&gt;&lt;/a&gt; - transforms .csv files into JavaScript arrays&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.com/plugins/gatsby-transformer-remark/"&gt;&lt;code&gt;gatsby-transformer-remark&lt;/code&gt;&lt;/a&gt; - parses and transforms .md files&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.gatsbyjs.com/plugins/gatsby-transformer-sharp/"&gt;&lt;code&gt;gatsby-transformer-sharp&lt;/code&gt;&lt;/a&gt; - transforms ImageSharp nodes into optimized image objects. More on this soon!&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sharp
&lt;/h2&gt;

&lt;p&gt;Now that we know about Gatsby's data layer and plugin system, let's add image processing to our Super Sophisticated™ site. &lt;a href="https://github.com/lovell/sharp"&gt;Sharp&lt;/a&gt; is a Node.js image processing library that Gatsby uses for its plugins. It resizes and compresses images, as well as converts them to web-optimal formats (WebP and AVIF).&lt;/p&gt;

&lt;p&gt;Since we are sourcing data from the filesystem, we don't need to worry about getting our images into the data layer. We do need to add Sharp image processing, so let's add and configure two new plugins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-plugin-sharp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`blurred`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-transformer-sharp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// any other plugins&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Adding the Sharp plugins in to our &lt;code&gt;gatsby-config.js&lt;/code&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;gatsby-plugin-sharp&lt;/code&gt; adds the low-level Sharp capabilities to our system. You can think of it like adding the &lt;code&gt;sharp&lt;/code&gt; NPM package to our project, but we haven't actually used it yet. This plugin is where you will configure the actual image processing options to your liking; you'll notice that I configured the default &lt;code&gt;placeholder&lt;/code&gt; to be &lt;code&gt;blurred&lt;/code&gt;. I'll touch on that in the next section more when we talk about responsive images.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;gatsby-transformer-sharp&lt;/code&gt; plugin is the Gatsby transformer to allow the images to be usable in Gatsby. After the data is sourced into the data layer, this plugin will leverage Sharp image processing to provide you with optimized images. This is where we actually use the capabilities from &lt;code&gt;gatsby-plugin-sharp&lt;/code&gt; (making &lt;code&gt;gatsby-plugin-sharp&lt;/code&gt; a pseudo peer dependency in NPM terms).&lt;/p&gt;

&lt;h2&gt;
  
  
  Gatsby Image Plugin
&lt;/h2&gt;

&lt;p&gt;The last piece of the Gatsby image processing puzzle is the relatively new &lt;code&gt;gatsby-plugin-image&lt;/code&gt;. After installing and configuring the plugin, it leverages the two Sharp plugins we installed in the previous section and gives us &lt;a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images"&gt;responsive images&lt;/a&gt;. Responsive images solve two problems with image loading on the web: the &lt;a href="https://www.webdesignerdepot.com/2017/04/why-art-direction-is-critical-to-responsive-design/"&gt;art direction problem&lt;/a&gt; and the &lt;a href="https://css-tricks.com/responsive-images-youre-just-changing-resolutions-use-srcset/"&gt;resolution switching problem&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you're curious about these topics, look out for the future blog post on web optimized images. In the meantime, let's see how Gatsby makes including responsive images as easy as importing and using a React component.&lt;/p&gt;

&lt;h3&gt;
  
  
  StaticImage
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;gatsby-plugin-image&lt;/code&gt; gives us two core components to use in our site: &lt;code&gt;StaticImage&lt;/code&gt; and &lt;code&gt;GatsbyImage&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;StaticImage&lt;/code&gt; component has two required props. Both are standard props on HTML &lt;code&gt;img&lt;/code&gt; tags: &lt;code&gt;src&lt;/code&gt; and &lt;code&gt;alt&lt;/code&gt;. Using &lt;code&gt;StaticImage&lt;/code&gt; is for images that never change and are known before build time. This is strictly enforced by this component, as you can only pass an absolute path, a relative path, or a local variable that resolves to a path to the &lt;code&gt;src&lt;/code&gt; parameter. You cannot pass props from other components into &lt;code&gt;src&lt;/code&gt;. Actually, you can't pass any props from other components into any props on this component at all! This is a static image, so absolutely no dynamic data is allowed.&lt;/p&gt;

&lt;p&gt;A good example of an image to be used for &lt;code&gt;StaticImage&lt;/code&gt; is your hero asset, or any design assets throughout your site. They are never going to change (unless you redesign your site), so referencing them directly by path for &lt;code&gt;StaticImage&lt;/code&gt; makes sense over importing them as JavaScript modules.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;StaticImage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-plugin-image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyStaticImage&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;StaticImage&lt;/span&gt;
            &lt;span class="nx"&gt;src&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../static/img/hero90em.png&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
            &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hero Giant&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;StaticImage usage. Both &lt;code&gt;src&lt;/code&gt; and &lt;code&gt;alt&lt;/code&gt; are required&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  GatsbyImage
&lt;/h3&gt;

&lt;p&gt;Tying everything we've covered in this blog post gives us the &lt;code&gt;GatsbyImage&lt;/code&gt; component. This is the component you will use for dynamic images that are determined at build time. The order for the images used by this component are as follows:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sourced into Gatsby's data layer (by &lt;code&gt;gatsby-source-filesystem&lt;/code&gt;, in our example)&lt;/li&gt;
&lt;li&gt;Transformed and optimized (by &lt;code&gt;gatsby-transformer-sharp&lt;/code&gt; and &lt;code&gt;gatsby-plugin-sharp&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Accessed via a GraphQL query (either as a page query or a static query)&lt;/li&gt;
&lt;li&gt;Converted to responsive images (by &lt;code&gt;gatsby-plugin-image&lt;/code&gt; and this component)&lt;/li&gt;
&lt;li&gt;Used in your JSX &amp;amp; generated HTML&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Because &lt;code&gt;GatsbyImage&lt;/code&gt;s use dynamic data from the data layer, we are able to pass in any props we want. This is desirable for setting up a blog because we can create a template for a blog post and then pass in the appropriate content to the template at build time and create as many blog posts as we want.&lt;/p&gt;

&lt;p&gt;There are several &lt;a href="https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-plugin-image/#helper-functions"&gt;helper functions&lt;/a&gt; to use as well, but the main one you will use is &lt;code&gt;getImage&lt;/code&gt;. Since the returned data from the data layer is from &lt;code&gt;gatsby-transformer-sharp&lt;/code&gt;, it will be in a &lt;code&gt;childSharp&lt;/code&gt; object and in sharp format. The &lt;code&gt;getImage&lt;/code&gt; helper will take that object, and return to us the data correctly to be used in &lt;code&gt;GatsbyImage&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Let's see this in action, using an image file named &lt;code&gt;dynamic-test.png&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;useStaticQuery&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;graphql&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;GatsbyImage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getImage&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-plugin-image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;MyGatsbyImage&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useStaticQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;graphql&lt;/span&gt;&lt;span class="s2"&gt;`
          query ImageQuery {
            file(
                    ext: { eq: "png" },
                    name: { eq: "dynamic-test"}
                ) {
                    childImageSharp {
                        gatsbyImageData
                    }
                }
          }
        `&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;GatsbyImage&lt;/span&gt;
      &lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;getImage&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;image&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;childImageSharp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;gatsbyImageData&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;
      &lt;span class="nx"&gt;alt&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Dynamic Test Image&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;We need to query for data to use &lt;code&gt;GatsbyImage&lt;/code&gt;. Using the helper &lt;code&gt;getImage&lt;/code&gt;, we are able to pass the correct data to the component after our GraphQL query against the data layer.&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Shared props &amp;amp; options
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;StaticImage&lt;/code&gt; and &lt;code&gt;GatsbyImage&lt;/code&gt; have different props for setting the image (&lt;code&gt;src&lt;/code&gt; for &lt;code&gt;StaticImage&lt;/code&gt;, and &lt;code&gt;image&lt;/code&gt; for &lt;code&gt;GatsbyImage&lt;/code&gt;), but most of their &lt;a href="https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-plugin-image/#shared-props"&gt;props are shared&lt;/a&gt;. The props for these components are mainly about styling the images, especially as they are loaded.&lt;/p&gt;

&lt;p&gt;Easily confused with props, there are also options for these components. All the options are shared between the two components, but there are &lt;a href="https://www.gatsbyjs.com/docs/reference/built-in-components/gatsby-plugin-image/#image-options"&gt;two differences in how the options get applied&lt;/a&gt; to &lt;code&gt;StaticImage&lt;/code&gt; and &lt;code&gt;GatsbyImage&lt;/code&gt;. Remember the core difference between the two components (one is completely static, one is dynamic) and those differences will make a lot of sense.&lt;/p&gt;

&lt;p&gt;One option I want to highlight is the &lt;code&gt;placeholder&lt;/code&gt; option. This option controls the initial placeholder for the image when the page is first loaded, until the image fully loads. The user should see this for only a second at most (hopefully), and then the full image will replace the placeholder.&lt;/p&gt;

&lt;p&gt;In the Sharp section, I explicitly set this option to &lt;code&gt;blurred&lt;/code&gt;. The default for this option is &lt;code&gt;dominantColor&lt;/code&gt;, which I think is the worst value besides &lt;code&gt;none&lt;/code&gt;. &lt;code&gt;dominantColor&lt;/code&gt; analyzes the image to figure out which color is most prevalent, and then &lt;em&gt;the entire image dimensions&lt;/em&gt; are filled with this color. To me, seeing a giant block of black, red, green, or whatever color is determined is very noticeable. It's even more noticeable when the block disappears and your image is put in - it's jarring, to say the least. This is why I'm a fan of &lt;code&gt;blurred&lt;/code&gt;. Instead, a low-resolution, blurred out version of the real image is used. When the real image is loaded, it feels like a much more natural transition.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;By now, you should have a great understanding of Gatsby's image processing, and more importantly, the data layer and plugin system that underpins the entire Gatsby ecosystem. Even if you don't understand the optimizations applied to your images, you are able to get the most out of them through your knowledge of Gatsby and this incredible framework. If you have any comments, questions, or image optimization tips you'd like to share, we'd love to hear from you at &lt;a href="mailto:developers@useanvil.com"&gt;developers@useanvil.com&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, if you'd like to see the &lt;code&gt;gatsby-config.js&lt;/code&gt; all together for our Super Sophisticated™ example, check it out below. It includes plugins we did not explicitly go over, but are needed to build our technical blog website.&lt;/p&gt;

&lt;p&gt;Let's continue to build the web fast for all ⚡️&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;siteMetadata&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;siteName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Super Sophisticated&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The most sophisticated business&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Reduce costs and unlock growth by transitioning from paper and PDF-based processes to simple and flexible online workflows.&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;website,sophisticated,super,gatsby&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-plugin-resolve-src&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-source-filesystem&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;src/markdown-articles/blog-posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;blog-posts&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-plugin-sharp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;defaults&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`blurred`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-transformer-sharp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-plugin-image&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-transformer-remark&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-remark-autolink-headers&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-remark-images&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-remark-copy-linked-files&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;gatsby-remark-prismjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
        &lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Final &lt;code&gt;gatsby-config.js&lt;/code&gt; for our technical blog site&lt;/em&gt;&lt;/p&gt;

</description>
      <category>gatsby</category>
      <category>graphql</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Consuming GraphQL APIs for REST-minded Developers</title>
      <dc:creator>Anvil Engineering</dc:creator>
      <pubDate>Fri, 14 Jan 2022 20:11:00 +0000</pubDate>
      <link>https://forem.com/useanvil/consuming-graphql-apis-for-rest-minded-developers-l2e</link>
      <guid>https://forem.com/useanvil/consuming-graphql-apis-for-rest-minded-developers-l2e</guid>
      <description>&lt;p&gt;If you've been developing against APIs for more than just a few years, I'm willing to bet that you've encountered and used &lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer"&gt;RESTful-style&lt;/a&gt; APIs. Why am I so confident? Because REST has become the de-facto standard, most commonly used style of API on the web today. Even though REST is great and has become ubiquitous, it's not without a few challenges and shortcomings:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Under-fetching data you need&lt;/li&gt;
&lt;li&gt;Over-fetching data you don't need&lt;/li&gt;
&lt;li&gt;Many endpoints - usually 1 for each resource type&lt;/li&gt;
&lt;li&gt;Related data requires multiple calls&lt;/li&gt;
&lt;li&gt;Difficult discovery and auto-tooling&lt;/li&gt;
&lt;li&gt;...and more&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To solve these and other issues, GraphQL was developed by Facebook starting in 2012. It was originally internal-only, but was open-sourced in 2015 and since then it has gained immense popularity. A &lt;a href="https://nordicapis.com/breaking-down-smartbears-2020-state-of-api-report/"&gt;recent study&lt;/a&gt; indicated that it is used in nearly 20% of all organizations with an API. This may not sound like a lot—especially when compared to REST's roughly 82% usage rate—but &lt;a href="https://2019.stateofjs.com/data-layer/graphql/"&gt;another study&lt;/a&gt; shows that developers' experience with GraphQL grew from around 5% in 2016 to nearly 40% in 2019. That's some solid growth, and Anvil has contributed to those statistics. While we have some RESTful APIs, we rely heavily on GraphQL for the majority of our exposed capabilities.&lt;/p&gt;

&lt;p&gt;Yet despite the significant and rapidly growing share of GraphQL APIs out there, some developers who are used to RESTful APIs have yet to use it, and some are reluctant to try and learn it. I'm here to show you that consuming a GraphQL API is really nothing to be afraid of, and it’s something that any developer can figure out the basics of.&lt;/p&gt;

&lt;h3&gt;
  
  
  GraphQL Background / Primer
&lt;/h3&gt;

&lt;p&gt;First off, if you have no idea what GraphQL is about and what it feels like, I'd like to suggest a few things:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Read &lt;a href="https://www.howtographql.com/basics/0-introduction/"&gt;this article&lt;/a&gt; to help gain a reasonable background on what GraphQL is all about.&lt;/li&gt;
&lt;li&gt;Try playing around with some live queries in &lt;a href="https://lucasconstantino.github.io/graphiql-online/"&gt;this online demo&lt;/a&gt; to get the feel for how things actually work. Take note of how you can traverse the relationship graph of objects from the root object, retrieving nested/related objects of your choice. Also notice how you can request as much or as little information as you want from each of those objects.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Hopefully after familiarizing yourself with some basics of interacting with a GraphQL API, you realize that for simple queries it's very straightforward. Here's a quick cheat sheet on what you need to know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instead of multiple "endpoints" that you might have in a REST API, a GraphQL API has just a single endpoint, but additionally defines and exposes any number of Queries (for read operations) and Mutations (for insert/update operations). These operations are hopefully given helpful, descriptive names like &lt;code&gt;invoices&lt;/code&gt; or &lt;code&gt;updateUser&lt;/code&gt;, etc.&lt;/li&gt;
&lt;li&gt;GraphQL is all about &lt;a href="https://graphql.org/learn/schema/"&gt;Types&lt;/a&gt;, and each operation will normally return an object of a specific Type. These Types include some basic &lt;a href="https://graphql.org/learn/schema/#scalar-types"&gt;Scalars&lt;/a&gt; like &lt;code&gt;Int&lt;/code&gt;, &lt;code&gt;String&lt;/code&gt;, &lt;code&gt;Boolean&lt;/code&gt;, but custom Types built from scalars or even other custom Types can also be defined - think &lt;code&gt;User&lt;/code&gt;, &lt;code&gt;Organization&lt;/code&gt;, &lt;code&gt;Invoice&lt;/code&gt;, etc. These custom Types typically are objects that contain 1 or more &lt;a href="https://graphql.org/learn/schema/#object-types-and-fields"&gt;Fields&lt;/a&gt;, each of which has a Type.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://graphql.org/learn/schema/#object-types-and-fields"&gt;Field&lt;/a&gt; definitions not only require a Type specifier, but they also can have a few modifiers:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;!&lt;/code&gt;: A non-nullable (i.e. "required") value can be indicated with a &lt;code&gt;!&lt;/code&gt;. E.g. &lt;code&gt;name: String!&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[&amp;lt;Type&amp;gt;]&lt;/code&gt;: An array of values can be indicated by surrounding a Type in brackets. E.g. &lt;code&gt;names: [String]&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;These 2 modifiers can be combined arbitrarily, for example to indicate "an array of non-nullable Strings" (e.g. &lt;code&gt;names: [String!]&lt;/code&gt;). Or to indicate "an array of non-nullable Strings, which itself cannot be null" (e.g. &lt;code&gt;names: [String!]!&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;The last big thing to mention is that GraphQL supports &lt;a href="https://graphql.org/learn/schema/#arguments"&gt;Arguments&lt;/a&gt; for Queries (e.g. the &lt;code&gt;invoice&lt;/code&gt; query expects an &lt;code&gt;invoiceId&lt;/code&gt; argument), Mutations (e.g. the &lt;code&gt;createUser&lt;/code&gt; mutation expects &lt;code&gt;name&lt;/code&gt; and &lt;code&gt;email&lt;/code&gt; arguments) and also Fields (e.g. the &lt;code&gt;addresses&lt;/code&gt; field on a &lt;code&gt;User&lt;/code&gt; type may accept a &lt;code&gt;country&lt;/code&gt; argument for filtering).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And with that, while there are definitely more advanced things one can learn about GraphQL, you should be armed with enough knowledge about the &lt;a href="https://spec.graphql.org/"&gt;GraphQL spec&lt;/a&gt; to understand how to use and consume most GraphQL APIs.&lt;/p&gt;

&lt;h3&gt;
  
  
  Request Shape
&lt;/h3&gt;

&lt;p&gt;Hopefully by now you're no longer mystified by interacting with a GraphQL API, and are starting to see some of the advantages of it. All that's left to do now is actually write some code that consumes one! GraphQL is so popular that there are client packages available in &lt;a href="https://graphql.org/code/"&gt;every popular language&lt;/a&gt; like Node, Python, Ruby, Java, Go, and more. Chances are that whatever language you're using to consume REST APIs has a library to make it easy to consume GraphQL APIs.&lt;/p&gt;

&lt;p&gt;If you're unable (or unwilling) to add more dependencies to your code base, or you'd just like to "roll your own" client for whatever reason, I'll show you some examples of how easy it is a bit later on. What I hope you'll realize is that at the end of the day, a GraphQL API call is just a &lt;code&gt;POST&lt;/code&gt; request to the server's GraphQL endpoint with a JSON payload consisting of a few key/values:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;query&lt;/code&gt;: A string containing the query or mutation you'd like to execute.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;variables&lt;/code&gt;: A &lt;a href="https://www.w3schools.com/js/js_json_objects.asp"&gt;JSON object&lt;/a&gt; whose keys match the name of any variables used in your &lt;code&gt;query&lt;/code&gt;, and whose values are the values for the server to use for those variables.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most servers will even let you send those key/values as &lt;a href="https://graphql.org/learn/serving-over-http/#get-request"&gt;query params to a &lt;code&gt;GET&lt;/code&gt; request&lt;/a&gt; if you really want to for some reason.&lt;/p&gt;

&lt;p&gt;The response should come with a &lt;code&gt;200&lt;/code&gt;/&lt;code&gt;OK&lt;/code&gt; status (&lt;strong&gt;&lt;em&gt;even when there are errors&lt;/em&gt;&lt;/strong&gt;), with a &lt;code&gt;content-type&lt;/code&gt; of &lt;code&gt;application/json&lt;/code&gt; and have the following JSON structure:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;errors&lt;/code&gt;: An array that should be present and populated only if there were errors encountered. The elements in the array should provide details about what thing or things went wrong. As noted above, the server response will still be &lt;code&gt;200&lt;/code&gt;/&lt;code&gt;OK&lt;/code&gt; even if there are errors.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;data&lt;/code&gt;: A JSON object containing the result of your query or mutation operation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Sample Code
&lt;/h3&gt;

&lt;p&gt;Hopefully this sounds easy so far, but let's see how it looks in code. Let's say we have a relatively simple &lt;code&gt;User&lt;/code&gt; query that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;User&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;Int&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And let's say that the &lt;code&gt;$id&lt;/code&gt; variable will be the integer &lt;code&gt;42&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The expected response would look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"foo@bar.com"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here are some examples of how to execute this query in different languages - I've left out the authorization header for simplicity:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;curl&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;-X&lt;/span&gt; POST &lt;span class="s1"&gt;'https://example.com/graphql'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-H&lt;/span&gt; &lt;span class="s1"&gt;'Content-Type: application/json'&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="s1"&gt;'{"query":"query User(id: Int!) { user(id: $id) {id email} }", "variables": {"id": 42}}'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;python&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Every project will have a dependency like this if it's making HTTP requests
&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;requests&lt;/span&gt;
&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;

&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="s"&gt;'query'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'query User(id: Int!) { user(id: $id) {id email} }'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="s"&gt;'variables'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;'Content-Type'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;'application/json'&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;'https://example.com/graphql'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;
&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Node&lt;/code&gt;/&lt;code&gt;JavaScript&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Every project will have a dependency like this if it's making HTTP requests&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;isomorphic-fetch&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com/graphql&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Content-Type&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;application/json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;{"query":"query User(id: Int!) { user(id: $id) {id email} }", "variables": {"id": 42}}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;json&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Ruby&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'uri'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'net/http'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'json'&lt;/span&gt;

&lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'http://localhost:3000/graphql'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post_form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'query'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'query {currentUser{id email}}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'variables'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s1"&gt;'id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt; &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;PHP&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'http://localhost:3000/graphql'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'query'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'query {currentUser{id email}}'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'variables'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

&lt;span class="nv"&gt;$options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s1"&gt;'http'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s1"&gt;'header'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'method'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'POST'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s1"&gt;'content'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;json_encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nv"&gt;$context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;stream_context_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$options&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="nv"&gt;$result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;file_get_contents&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;FALSE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Summary
&lt;/h3&gt;

&lt;p&gt;So there you have it! In my opinion, there's nothing mystical or particularly challenging to using GraphQL APIs - they're easy, efficient, and pretty fun/awesome. Admittedly, I kept the examples rather simple, and there are far more complex things that can be done with GraphQL (for example, trying to upload binary files can be a bit tricky), but for many APIs this is more or less all you need to know. So don't be afraid when you hear that an API is GraphQL - it's only some basic REST-like calls under the covers. Happy coding!&lt;/p&gt;

</description>
      <category>graphql</category>
      <category>webdev</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Techniques to optimize react render performance: part 1</title>
      <dc:creator>Anvil Engineering</dc:creator>
      <pubDate>Wed, 15 Dec 2021 20:43:58 +0000</pubDate>
      <link>https://forem.com/useanvil/techniques-to-optimize-react-render-performance-part-1-2ahn</link>
      <guid>https://forem.com/useanvil/techniques-to-optimize-react-render-performance-part-1-2ahn</guid>
      <description>&lt;p&gt;Improving performance is an art. To me, chasing performance issues feels like it flexes the same muscles as debugging. You're wading into the unknown with only a sliver of information. But instead of understanding why it does that one weird thing, you're asking adjacent questions: &lt;em&gt;Where is it slow?&lt;/em&gt; &lt;em&gt;Why is it slow?&lt;/em&gt; Then of course, &lt;em&gt;How can it be improved?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;This post will be the first in a series outlining how I approach improving performance, specifically for laggy UIs built with React. Even though this will mention tools and techniques specific to React, a fair amount of this would transfer to general-purpose optimization work. No matter the environment or tools, I'm trying to answer the same questions.&lt;/p&gt;

&lt;p&gt;So, you have a UI that feels slow. Where do you start? This post will cover two big chunks of the process of optimizing React performance:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tools&lt;/li&gt;
&lt;li&gt;Where is it slow?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a future post, we'll cover the other half of optimization: React pitfalls and techniques to actually improve performance of your UI.&lt;/p&gt;

&lt;p&gt;I'm starting with tooling and the "where" because, like debugging, the hard part is in really understanding what’s going on and what should be improved. I often find that the actual solution to speed up a UI is a couple of small changes. I can't tell you how many times an ill-placed splat or anonymous function passed as a prop has made a UI unusable. Fixing these issues was only possible by understanding which parts of the code needed optimization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools
&lt;/h2&gt;

&lt;p&gt;There are a few browser tools you can use to help you understand where to optimize. Specialized tools aren't the end-all, though. In my experience, they almost never straight-up point out a performance issue. But they can give you a general direction to answer "What is slow?" and tell you how much time something takes.&lt;/p&gt;

&lt;h3&gt;
  
  
  DevTools profiler
&lt;/h3&gt;

&lt;p&gt;Chrome has a profiler in the dev tools' &lt;code&gt;Performance&lt;/code&gt; tab. The profiler can help point out that obvious case where you have a super slow function, or when you are calling a function too many times. Usually it'll show the lowest hanging fruit.&lt;/p&gt;

&lt;p&gt;First, start up a profile by opening up the dev tools and clicking record.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffmn8ir4ynrciqj6y2qkx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffmn8ir4ynrciqj6y2qkx.png" alt="start chrome profiler"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Do your slow action, then click stop. It will show you a summary like this.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7bkwtsf7rvwav6wtuw61.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7bkwtsf7rvwav6wtuw61.png" alt="chrome profiler summary"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To me, the most useful tab is "Bottom-Up". It will show you which functions took the most time. Since we are focused on JavaScript performance in this post, I'll drag my mouse over the yellow chunks of the timeline, which show JavaScript performance concerns, then select the "Bottom-Up" tab:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xsfzqi0osen055jvkzv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2xsfzqi0osen055jvkzv.png" alt="chrome profiler slow function"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Select the Bottom-Up tab in the 2nd level tabs&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Oh hey, a slow function. Lucky us!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Self Time&lt;/strong&gt; will tell you how much time was actually spent in &lt;em&gt;this&lt;/em&gt; function. You can see that &lt;code&gt;slowFunc()&lt;/code&gt; shows the most "Self Time", so it likely does a bunch of additional processing within its function boundary. That is, it's not calling some other slow function, it is slow itself.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Total Time&lt;/strong&gt; tells you how much time was spent, including time calling slow child functions. Basically, if this is high and "Self Time" is low, this function is calling a slow function somewhere down its call tree. You can see the 4th line, &lt;code&gt;render()&lt;/code&gt;, has a high "Total Time", but a low "Self Time". It does very little itself, but calls something slow: &lt;code&gt;slowFunc()&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also dig into the call tree with the carets. By opening &lt;code&gt;slowFunc()&lt;/code&gt;, you can see that it is called by &lt;code&gt;render()&lt;/code&gt;. If multiple functions are calling &lt;code&gt;slowFunc()&lt;/code&gt;, there will be more than one line here.&lt;/p&gt;

&lt;p&gt;For reference, our contrived &lt;code&gt;slowFunc()&lt;/code&gt; example is the following: &lt;code&gt;render()&lt;/code&gt; calls &lt;code&gt;slowFunc()&lt;/code&gt; directly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;slowFunc&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;SlowComponent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;slowFunc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;I'm slow :(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SlowComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;SlowComponent&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="c1"&gt;// 100 more SlowComponent renders&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an extremely simplified case. The obvious solution is to not call &lt;code&gt;slowFunc()&lt;/code&gt; here. But what if it is doing necessary work? The real world is often much messier.&lt;/p&gt;

&lt;h3&gt;
  
  
  JavaScript profiler
&lt;/h3&gt;

&lt;p&gt;Instead of opening the &lt;code&gt;Performance&lt;/code&gt; tab and clicking &lt;code&gt;Record&lt;/code&gt;, you can programmatically generate performance profiles for later viewing. This is useful if you want to capture a very specific part of the code. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The slow thing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nf"&gt;doTheSlowThing&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;profileEnd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The slow thing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It works similarly to the "Performance" tab, but In Chrome these show up in a different part of the dev tools: &lt;strong&gt;...&lt;/strong&gt; -&amp;gt; &lt;strong&gt;More tools&lt;/strong&gt; -&amp;gt; &lt;strong&gt;JavaScript Profiler&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56vtbnhae3kcx7l70bti.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F56vtbnhae3kcx7l70bti.png" alt="finding console profiler in chrome"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;How to access the JavaScript profiler&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And it shows your generated profiles:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgyiqwnyowj9ze73dzph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjgyiqwnyowj9ze73dzph.png" alt="javascript profile in chrome"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Our slowFunc profile in the JavaScript profiler&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  React profiler
&lt;/h3&gt;

&lt;p&gt;There is yet another profiler, one specifically for React. &lt;a href="https://chrome.google.com/webstore/detail/react-developer-tools/fmkadmapgofadopljbjfkapdkoienihi" rel="noopener noreferrer"&gt;React developer tools&lt;/a&gt; is a Chrome browser extension written by Facebook.&lt;/p&gt;

&lt;p&gt;Once it's installed, you will get a new tab. Just like the JavaScript profiler, you can record profiles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftzd0ru8fp87h344edn69.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftzd0ru8fp87h344edn69.png" alt="react developer tools profiler in chrome"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;React developer tools profiler in chrome&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Click record, do your slow action, click stop, and you'll get a breakdown of which components rendered and how much time they took.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5agcs4ik4jhmfgqu6bi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz5agcs4ik4jhmfgqu6bi.jpg" alt="react developer tools flame graph"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;React developer tools flame graph&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The profiler breaks down your profile into "commits"; see the chart in the top right of your profile. A "commit" is when React actually applies your rendered components to the DOM. Note that a commit may contain multiple render calls for a given component! In the above screenshot, it's possible Container has been re-rendered 10 times.&lt;/p&gt;

&lt;p&gt;Click on the tallest peak in the commit chart and you will see the slowest renders.&lt;/p&gt;

&lt;p&gt;This profiler has its own concept of Self Time and Total Time shown in each horizontal bar. For example, in &lt;code&gt;1ms of 100ms&lt;/code&gt;, &lt;code&gt;1ms&lt;/code&gt; is the self time; the time that was spent rendering this component, and &lt;code&gt;100ms&lt;/code&gt; is the total time; the time spent rendering itself and all its children.&lt;/p&gt;

&lt;p&gt;You can see I have a lot of components rendering each time I do my slow action. Each one of them takes only a few milliseconds, but it adds up!&lt;/p&gt;
&lt;h3&gt;
  
  
  console.log()
&lt;/h3&gt;

&lt;p&gt;Let's be honest, logging is probably the most widely used (and dare I say, useful) debugging tool ever invented. It might feel low-tech, but well-placed logging can play a central role in performance optimization. It can be a super fast way to check parts of the code, which we'll get into later in this post. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nf"&gt;doSlowOperation&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Time to do slow operation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;start&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example is a little basic, but it becomes more useful when your start and stop points are asynchronous. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;handleStartSlowOperation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startPerf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nf"&gt;kickOffSlow&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;handleSlowOperationDone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Time to do slow operation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startPerf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Where is it slow?
&lt;/h2&gt;

&lt;p&gt;Let's dig into how to actually find where a laggy UI is slow. I spend a fair amount of time trying to understand where it is slow, as it makes the fixing part significantly easier.&lt;/p&gt;

&lt;p&gt;I start by picking an operation that represents the slow condition. Say load up your UI with a lot of data, then type into that slow input box, or click that slow button. The more quickly repeatable the scenario, the better. Can you repeatedly type into the slow input box and have it feel slow? That's the best scenario.&lt;/p&gt;

&lt;p&gt;My examples will be based on an optimization in Anvil's webform builder. For context, our webform builder is a piece of our &lt;a href="https://dev.to/products/workflows/"&gt;Workflows product&lt;/a&gt;. Clients create custom sharable webforms in the builder by adding and modifying input fields. Clients can use the webforms they build to collect data from their users. Once the user has filled out the webform, our clients can use the data from the webform to fill PDFs and gather signatures.&lt;/p&gt;

&lt;p&gt;We recently optimized rendering when there were a lot of fields on a webform page. e.g. our client creates a webform page with 100 input fields.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feufstebrm52bxtp1qoed.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feufstebrm52bxtp1qoed.png" alt="webform builder"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Anvil's webform builder&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;In our example case, it will be typing a single character into the label field in the left panel. When you change this label value, it will change the selected input field's label in the right panel. There was a noticeable lag when changing a field's label on a webform with many fields.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdfi9dtxupgcl957y6aj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbdfi9dtxupgcl957y6aj.jpg" alt="webform builder label"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Changing an input field's label can feel laggy&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;With my slow operation chosen, I get to tracking down the slowest parts of the code within that operation. You might be thinking, "I mean, it's slow when I type into the slow input box". But &lt;em&gt;where&lt;/em&gt; where is it slow? That one keystroke might trigger hundreds of components to re-render or several expensive operations to run, maybe even a number of times.&lt;/p&gt;

&lt;p&gt;The first goal is to isolate what is slow, down to some function(s) or part of the DOM tree.&lt;/p&gt;
&lt;h2&gt;
  
  
  Profiling
&lt;/h2&gt;

&lt;p&gt;The profiling tools mentioned above will be the most help in this "Where" stage of optimization. I follow mostly the same process each time I am tracking down inefficiencies in a slow UI.&lt;/p&gt;

&lt;p&gt;First, I use the DevTools profiler mentioned above. Usually it can help point out any obvious slowdowns.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1.&lt;/strong&gt; If a function in your codebase shows a high "Self Time", that is a good candidate for optimization. It's possible it's getting called a ton, or it's just plain inefficient.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpmkbef0spgnjl25sbh7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqpmkbef0spgnjl25sbh7.png" alt="chrome profiler slow function"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Note that the Self Time is high here&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2.&lt;/strong&gt; If a non-React 3rd party library function shows a high "Self Time", likely something is calling it too often. For example, I added this snippet to the our webform &lt;code&gt;Field&lt;/code&gt; component's render function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;uniq&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see &lt;code&gt;lodash&lt;/code&gt; functions at the top of the list:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4nn5ph1pu4otzuf0p00n.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4nn5ph1pu4otzuf0p00n.png" alt="chrome profiler 3rd party"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Something is calling a library function too often&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The trick here is to drill down into the call tree for each of these items and figure out exactly where in your code base this is being called, how often, etc. It's easy to blame a library function for being slow itself, but in my experience the issue is almost always with how it's being used in our own codebase.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3.&lt;/strong&gt; If the profiler shows mostly React library functions at the top of the "Bottom-Up" list, then some component is slow to render, or is being rendered too many times.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx48nzsyzlzzafwpna2nu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx48nzsyzlzzafwpna2nu.png" alt="chrome profiler slow function"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;All react all the way down&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you see this, it's time to dig into the React profiler. Here is the same action in the react profiler:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqu7i5ku7nzgkxxtgksbu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqu7i5ku7nzgkxxtgksbu.png" alt="react slow function"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Dig into the React profiler&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;You can see the slow render is made up of a ton of other component renders. Each of these renders takes up only a few milliseconds, but it adds up to a lag.&lt;/p&gt;

&lt;p&gt;The above React profile is from the webform editor example; it looks like every keystroke is causing a re-render of all fields, even for fields whose label isn't being updated.&lt;/p&gt;

&lt;p&gt;In my example case, I now have a basic direction: look into the component that is rendering all those fields.&lt;/p&gt;
&lt;h2&gt;
  
  
  Establish a baseline
&lt;/h2&gt;

&lt;p&gt;The next thing I like to do after having some direction from the profiling tools is to figure out how much time my specific action is taking now.&lt;/p&gt;

&lt;p&gt;I've found relying on the profiles for this info isn't so precise. Profiling can also impact the performance of the action you're taking. I want to see a number that is pretty consistent run-to-run and keep the action's real world feel. Instead of profiling, I like to add logging around the slow action. Having a consistent number run to run can show you how much it improves as you change code.&lt;/p&gt;

&lt;p&gt;It can be challenging to exactly wrap your action in React. When dealing with rendering performance, it often involves using the &lt;code&gt;componentDidUpdate&lt;/code&gt; func. In my case, it will look something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Editor&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;handleKeystroke&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;onChangeLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;componentDidUpdate&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;lastChange&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;lastChange&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;fields&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;lastChange&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;lastChange&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Keystroke millis&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;startTime&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;This doesn't need to be pretty code, it's temporary&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Pressing a keystroke in my example, I can now see how much time is being spent between pressing the key and rendering.&lt;/p&gt;

&lt;p&gt;This is my baseline: around 1000ms. You can see here that it's actually being rendered &lt;em&gt;twice&lt;/em&gt; on a change, not ideal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cdc1972t1913uqkkz7l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5cdc1972t1913uqkkz7l.png" alt="baseline from logging"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;My baseline for my slow keystroke operation&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Delete
&lt;/h2&gt;

&lt;p&gt;At this point, after profiling and creating a baseline, it's possible you have a really good idea of exactly what is slow. If so, that is awesome, and you can probably stop to improve the slow parts.&lt;/p&gt;

&lt;p&gt;In complex code bases, however, things might not be very straightforward. It may not be clear which part of the render function is slow, what is causing all the re-renders, or which components shouldn't re-render. If you're looking at, say, a slow data-transformation function, it helps to know exactly which loop or operation is causing the pain.&lt;/p&gt;

&lt;p&gt;A lot of times, once I have a baseline, I employ another extremely high-tech technique to narrow the path further: &lt;strong&gt;deleting code&lt;/strong&gt;. I'm trying to answer: How fast &lt;em&gt;could it be&lt;/em&gt;? Where &lt;em&gt;exactly&lt;/em&gt; will make the biggest impact?&lt;/p&gt;

&lt;p&gt;In the case of my example, the react profiler shows a lot of renders for each field.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktub03g4af9gur77x9sb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fktub03g4af9gur77x9sb.png" alt="react  slow function"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Each input field is being re-rendered on a change to one field&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here, rendering could possibly be improved by either re-rendering fewer &lt;code&gt;Field&lt;/code&gt; components, or optimizing the &lt;code&gt;render&lt;/code&gt; method in each &lt;code&gt;Field&lt;/code&gt; component. Intuitively, it feels like the best option is just to render fewer components here, but we won't really know until we try and note the change in performance.&lt;/p&gt;

&lt;p&gt;The process is very much the scientific method: have hypotheses, then quickly test them. The UI doesn't even need to be totally functional during this process; this just gives you an idea of where you should spend your time.&lt;/p&gt;

&lt;p&gt;For our example: how long does the action take when we do basically &lt;em&gt;nothing&lt;/em&gt; in each &lt;code&gt;Field&lt;/code&gt; component's &lt;code&gt;render&lt;/code&gt; func? We still render all field components, but each does the absolute minimum: only render an empty &lt;code&gt;div&lt;/code&gt; in the &lt;code&gt;Field&lt;/code&gt; render function. How much does that impact the total time?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The parent renders 100 Fields that are just divs&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An order of magnitude improvement, great!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgzzswffzrle990h8b5ef.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgzzswffzrle990h8b5ef.png" alt="logging only rendering the div"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now, is the issue the rendering of the children itself, or building the props? We can test this by still rendering all fields, building the props to render children, but only rendering the &lt;code&gt;div&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Field&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Is props setup slow?&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fieldInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;buildFieldInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;The parent renders 100 Fields that build props, then render divs&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Back close to 1000ms, not great. It seems the actual rendering is less of an issue and now we know building the props could be a place to dig in.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd043lgd9w9v8aq2xi5y2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd043lgd9w9v8aq2xi5y2.png" alt="logging rendering div and props"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's look into only rendering a single component on change. We can first return &lt;code&gt;false&lt;/code&gt; from &lt;a href="https://reactjs.org/docs/react-component.html#shouldcomponentupdate" rel="noopener noreferrer"&gt;&lt;code&gt;shouldComponentUpdate&lt;/code&gt;&lt;/a&gt;. &lt;code&gt;shouldComponentUpdate&lt;/code&gt; is a React lifecycle function that allows you to control when something re-renders. Returning &lt;code&gt;false&lt;/code&gt; from it will tell React to render the component only once (initially), then never again. This will tell us how much it takes to render the parent on a label change.&lt;/p&gt;

&lt;p&gt;I'll dig more into &lt;code&gt;shouldComponentUpdate&lt;/code&gt; in the next post in this series.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;shouldComponentUpdate &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fieldInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;buildFieldInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TheFieldComponents&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;fieldInfo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;)
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;None of the 100 Fields re-render on a label change&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Ok, it's reasonably fast.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkcgsm8mby0fb6f0q3yf9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkcgsm8mby0fb6f0q3yf9.png" alt="logging rendering false"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next, I can add a dirty check to &lt;a href="https://reactjs.org/docs/react-component.html#shouldcomponentupdate" rel="noopener noreferrer"&gt;&lt;code&gt;shouldComponentUpdate&lt;/code&gt;&lt;/a&gt;. This check might not be totally correct, but we can simulate what it looks like to only render the changed field. Note that we are doing a full render in the &lt;code&gt;Field&lt;/code&gt; component's &lt;code&gt;render&lt;/code&gt; func, instead of just rendering a &lt;code&gt;div&lt;/code&gt; like in other examples.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Field&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Component&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;shouldComponentUpdate &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nextProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;nextProps&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;label&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fieldInfo&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;buildFieldInfo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TheFieldComponents&lt;/span&gt; &lt;span class="p"&gt;{...&lt;/span&gt;&lt;span class="nx"&gt;fieldInfo&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="sr"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="err"&gt;)
&lt;/span&gt;  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Only the changed Field re-renders on a label change&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Fully rendering only the changed field, even though it is less-than-efficient when building props, is about 105ms.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiv0ob3j3zi6cd223dl7v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiv0ob3j3zi6cd223dl7v.png" alt="logging rendering only changed field"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the React profiler, we can see my change only renders the affected fields. Note all the greyed out components under &lt;code&gt;styled.div&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3l62sjsiidx6tibyp8h8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3l62sjsiidx6tibyp8h8.png" alt="logging rendering only changed field"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;The greyed out components did not render&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Analysis
&lt;/h2&gt;

&lt;p&gt;After profiling and strategically deleting code in my example, I have direction as to where I should spend my time.&lt;/p&gt;

&lt;p&gt;Remember, we were typing a single keystroke to change the label for a single field in a large list of fields.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjlugiytjoz4zvct22af.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpjlugiytjoz4zvct22af.jpg" alt="example editor label edit"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Our example: type a character into the label field here&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The experimentation has given me a pretty good idea of the shape of performance behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;On changing a label with a single keystroke, it's rendering all input &lt;code&gt;Field&lt;/code&gt; components in the webform &lt;em&gt;twice&lt;/em&gt;. Does it need to?&lt;/li&gt;
&lt;li&gt;It's rendering all input &lt;code&gt;Field&lt;/code&gt; components on changes that do not necessarily affect all fields.&lt;/li&gt;
&lt;li&gt;It is possible to be fast rendering all fields, but building the props to render a single &lt;code&gt;Field&lt;/code&gt; component is a bottleneck. This doesn't seem to be a huge problem when only one field changes, but it could be a big deal for changes that do affect all fields, or initial render.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Since typing a single keystroke was the initial problem, my approach would be to first get excessive re-rendering under control. Clean up the double renders, and only render the changed &lt;code&gt;Field&lt;/code&gt; component. Then if there was time, I would dig into fixing props-building for each &lt;code&gt;Field&lt;/code&gt; render.&lt;/p&gt;

&lt;p&gt;Going through the exercise of understanding what is slow has also given me some ballpark numbers.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I now know I can reasonably shoot for ~80-100ms for a change that renders a single field; the parent component takes up about 70ms.&lt;/li&gt;
&lt;li&gt;Rendering all fields in ~100ms isn't out of the question. If I can make building props for a single field more efficient, I can likely get close.&lt;/li&gt;
&lt;li&gt;Typically when typing, animating an element on a user action, or other things that run 'in band' of user input, &lt;a href="https://developers.google.com/web/fundamentals/performance/rendering#60fps_and_device_refresh_rates" rel="noopener noreferrer"&gt;you need to finish all work within a ~16ms window&lt;/a&gt; (60 frames per second) to avoid the user feeling a lag. It appears that fitting into this 16ms is out of reach for our example keystroke.

&lt;ul&gt;
&lt;li&gt;The work we are doing in the example doesn't necessarily need to happen on every keystroke. There are techniques like &lt;a href="https://css-tricks.com/debouncing-throttling-explained-examples/" rel="noopener noreferrer"&gt;debouncing&lt;/a&gt;, which will keep user input feeling fast, then does the work once the user is finished typing. I will dig into debouncing and other techniques that can help us solve this in the next post.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Next up: improving performance
&lt;/h2&gt;

&lt;p&gt;Now you have some tooling and approaches for tracking down the slow parts of your code. In the next post, we'll cover React pitfalls, understanding React re-renders, then techniques to actually fix performance issues in your UIs.&lt;/p&gt;

&lt;p&gt;Have feedback on this post? Or are you developing something cool with PDFs or paperwork automation? Let us know at &lt;a href="mailto:developers@useanvil.com"&gt;developers@useanvil.com&lt;/a&gt;. We’d love to hear from you!&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Introduction to the Twelve-Factor App Part 2</title>
      <dc:creator>Anvil Engineering</dc:creator>
      <pubDate>Wed, 08 Dec 2021 21:14:25 +0000</pubDate>
      <link>https://forem.com/useanvil/introduction-to-the-twelve-factor-app-part-2-icm</link>
      <guid>https://forem.com/useanvil/introduction-to-the-twelve-factor-app-part-2-icm</guid>
      <description>&lt;h1&gt;
  
  
  12 Factor App Blog Post Part 2
&lt;/h1&gt;

&lt;p&gt;Summary: Make your toy web apps more robust and manageable by following the Twelve-Factor App methodology.&lt;/p&gt;

&lt;p&gt;This is the second part in a series of posts detailing the &lt;a href="https://12factor.net/"&gt;12 Factor App&lt;/a&gt;. In the last post we looked at:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Your codebase and made it deployable across different environments&lt;/li&gt;
&lt;li&gt;Dependencies and why they’re important in reproducibility&lt;/li&gt;
&lt;li&gt;Configuration files and how to make them useful across different environments&lt;/li&gt;
&lt;li&gt;Backing services, what they are and how decoupling gives your app more flexibility&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you need a refresher or aren’t familiar with the above already, take a look at &lt;a href="https://www.useanvil.com/blog/engineering/introduction-twelve-factor-app/"&gt;the last post&lt;/a&gt;. Many of the earlier concepts are used as building blocks for the concepts in this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  V. Build, release, run
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Strictly separate build and run stages - &lt;a href="https://12factor.net/build-release-run"&gt;https://12factor.net/build-release-run&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Many of the previous sections finally start coming together here. This may be one of the more time consuming sections or steps, but also the one that will improve your development and release cycles tremendously. These steps are also what people usually refer to as Continuous Integration/Continuous Deployment, or CI/CD. Let’s step through from the start.&lt;/p&gt;

&lt;h4&gt;
  
  
  Build:
&lt;/h4&gt;

&lt;p&gt;In the build step, the goal is to get all code and assets into a usable state at the run step. The end product can differ depending on whether you’re building for development or for production. In a development environment, for example, we could skip optimizations such as compressing files and compiling frontend assets (HTML/CSS/JS) into bundles that would normally live in a CDN.&lt;/p&gt;

&lt;p&gt;In general, the build step can look like the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pin your release on a specific commit or tag, if using git (Factor I). 
This keeps everything at a known starting point.&lt;/li&gt;
&lt;li&gt;Start compiling your code.
This depends on the codebase, but in general, this would be:

&lt;ul&gt;
&lt;li&gt;Gather all the app’s dependencies (Factor II) via &lt;code&gt;npm&lt;/code&gt;, &lt;code&gt;PyPI&lt;/code&gt;, git clones, etc.&lt;/li&gt;
&lt;li&gt;Compile code where needed. This could mean using a bundler like &lt;code&gt;webpack&lt;/code&gt;, or compiling binaries and libraries like Java .jar files.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Log all build processes running.&lt;/li&gt;
&lt;li&gt;Build process should have a mechanism to keep track of attempted builds -- whether or not they were successful.&lt;/li&gt;
&lt;li&gt;If any of the above fails to complete, stop the entire build-release-run process and send notifications or some sort of message to the developer about the failure.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Release:
&lt;/h4&gt;

&lt;p&gt;In the release step, the main product of the release step is to have your compiled and built code ready to run, publish, or use for the end-user in some way.&lt;/p&gt;

&lt;p&gt;The release process can look like the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Apply config specific to this build’s environment (Factor III).&lt;/li&gt;
&lt;li&gt;For example, a development environment can point to a database running on a cheap server instance, while a production version would point to a much more robust version on Amazon RDS with backups enabled.&lt;/li&gt;
&lt;li&gt;Run your tests! This would include unit, integration, and end-to-end tests. These tests would run against the compiled build and with the proper config applied. If any tests fail, we could immediately cancel any further actions and send out notifications/messages about the failure.&lt;/li&gt;
&lt;li&gt;Any other preparations you need before getting to the run phase.&lt;/li&gt;
&lt;li&gt;If using Docker, this is when you would create an image of all the parts of your application that you want deployed. This image is a snapshot of the application code where you know all tests have passed and the build process ran successfully.&lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Run:
&lt;/h4&gt;

&lt;p&gt;At this point, all the previous steps should have given us high confidence that your application will work as expected. We’ve compiled and prepared all code and assets, ensuring that the application is set up correctly and does not have any build-time problems. We’ve tested the application itself with run-time tests, and maybe even end-to-end tests. Now all we have to do is just deploy the thing.&lt;/p&gt;

&lt;p&gt;The Run step should be fairly straightforward. We’ll be assuming you’re using Docker, or some other containerization tool:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Upload your Docker image(s) from the release step to your code’s final running destination.&lt;/li&gt;
&lt;li&gt;Run your application.&lt;/li&gt;
&lt;li&gt;Notify/message any other external services that your application is up and running.&lt;/li&gt;
&lt;li&gt;If scaling to multiple instances, there are infrastructure considerations that need to be made. You would need a load balancer like &lt;a href="http://nginx.org/en/docs/http/load_balancing.html"&gt;nginx&lt;/a&gt; or &lt;a href="http://www.haproxy.org/"&gt;HAProxy&lt;/a&gt;. Some cloud services also handle this automatically like Amazon ECS, so double check with your provider docs as well. At the higher end of complexity, much of this can also be handled with Kubernetes, but that in itself would require more than a few blog posts to introduce.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The build-release-run workflow is very well-supported on platforms like GitHub and GitLab with GitHub Actions and GitLab CI/CD, respectively. You can also customize your own build process with tools like Jenkins and CircleCI. When using those services, the build and release steps are covered, but the run step will require a container hosting service such as Amazon ECS. There are also services that encompass all the steps such as Heroku (which developed this 12 Factor methodology).&lt;/p&gt;

&lt;p&gt;At this point, we actually have a running app. We could stop here, but we have millions of users to take care of and the application needs to scale easily!&lt;/p&gt;

&lt;h2&gt;
  
  
  VI. Processes
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Execute the app as one or more stateless processes&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This section is mainly how to think about your application processes in the context of scaling. At its simplest case, we can think of a single-purpose application that resizes images. This application would get image data, resize it, and finally upload it to a cloud storage service like Amazon S3.&lt;/p&gt;

&lt;p&gt;For this application, we have no shared state from other processes. We can even imagine 10s or 100s of instances of these running independently in parallel. They all don’t require any additional context data nor do they need to share data. They only need an input (image data) and they return an output (successful upload to S3).&lt;/p&gt;

&lt;p&gt;What’s the key aspect to processes?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Processes are stateless&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is, they don't expect data in memory or on disk will exist permanently. The easiest way to think about this is to ask: If the app were to be completely torn down and redeployed from a Docker image, would it be a catastrophic failure?&lt;/p&gt;

&lt;p&gt;In a twelve-factor app, all the states that we need to persist (database, cloud storage, session data, etc.) are saved in backing services (Factor IV) that our app uses. These backing services are defined in our app’s config (Factor III) which has been applied in the release step of our build-release-run process (Factor V). The app itself should be highly recoverable if it goes down, and at the opposite end, the app should easily scale up to more instances.&lt;/p&gt;

&lt;p&gt;This architecture will play a key role in a few of the next sections.&lt;/p&gt;

&lt;h2&gt;
  
  
  To be continued
&lt;/h2&gt;

&lt;p&gt;This post covered sections V-VI of the Twelve-Factor App methodology. Hopefully, this has shown the interconnectedness of all the factors and how smaller efforts in your application architecture can build up to something that can scale and have more resilience.&lt;br&gt;
Here at Anvil we follow many of these concepts in our development process and we believe that sharing our experiences helps everyone create awesome products. If you’re developing something cool with PDFs or paperwork automation, let us know at &lt;a href="mailto:developers@useanvil.com"&gt;developers@useanvil.com&lt;/a&gt;. We’d love to hear from you.&lt;/p&gt;

</description>
      <category>html</category>
      <category>css</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
