<?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: Rangle.io</title>
    <description>The latest articles on Forem by Rangle.io (@rangle).</description>
    <link>https://forem.com/rangle</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%2Forganization%2Fprofile_image%2F1613%2F1d64c37e-f961-419f-bbdd-aa236d58f0fc.jpg</url>
      <title>Forem: Rangle.io</title>
      <link>https://forem.com/rangle</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/rangle"/>
    <language>en</language>
    <item>
      <title>Van Gogh, InVision Design System Manager and a new NPM package</title>
      <dc:creator>cdepaul</dc:creator>
      <pubDate>Mon, 20 Apr 2020 19:55:18 +0000</pubDate>
      <link>https://forem.com/rangle/van-gogh-invision-design-system-manager-and-a-new-npm-package-5hm1</link>
      <guid>https://forem.com/rangle/van-gogh-invision-design-system-manager-and-a-new-npm-package-5hm1</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;“Great things are not done by impulse, but by a series of small things&lt;br&gt;
brought together. And great things are not accidental, but must&lt;br&gt;
certainly be willed.” — Vincent van Gogh&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Last month, Rangle became an InVision Partner and the developers at Rangle leapt at the opportunity to play around with &lt;a href="https://www.invisionapp.com/design-system-manager"&gt;InVision’s Design System Manager (DSM)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After building a sample project, I created &lt;a href="https://www.npmjs.com/package/invision-dsm-utils"&gt;invision-dsm-utils&lt;/a&gt;, a Node.js package to support front-end developers with:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Downloading&lt;/strong&gt; InVision DSM design tokens into their projects, and&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transforming&lt;/strong&gt; those design tokens into JavaScript objects that meet the &lt;a href="https://styled-system.com/theme-specification/"&gt;Styled System Theme Specification&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this article, I’ll take you through the use cases for the scripts and how you can integrate this library into your development process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample Project
&lt;/h2&gt;

&lt;p&gt;As a developer in Amsterdam, I have been looking for an excuse to work on a side-project that could incorporate Vincent van Gogh — one of the Netherland’s most famous exports — in some way. With InVision DSM in mind, I came up with a small app idea that could be designed in Sketch, uploaded to InVision DSM, and developed in React.&lt;/p&gt;

&lt;p&gt;I called this project, &lt;strong&gt;WhereVanGogh&lt;/strong&gt;: An app that provides the museum location of publicly available van Gogh works of art.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample Design
&lt;/h2&gt;

&lt;p&gt;Here is the design I made for a &lt;em&gt;Painting&lt;/em&gt; page, developed in Sketch and uploaded to InVision DSM. Note, the images have a public-domain license from museums like Rijkmuseum&lt;a href="https://www.rijksmuseum.nl/en/photoservice"&gt;enter link description here&lt;/a&gt; and &lt;a href="https://www.metmuseum.org/about-the-met/policies-and-documents/image-resources"&gt;The Metropolitan Museum of Art&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--V2Tq8e4x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rzw0tektivocaj1lfipi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--V2Tq8e4x--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/rzw0tektivocaj1lfipi.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating design tokens into code base
&lt;/h2&gt;

&lt;p&gt;Designing the page layout in Sketch in a manner that would integrate with InVision DSM was straight forward and well supported by InVision’s excellent documentation (see below).&lt;/p&gt;

&lt;p&gt;When it came time to develop my React components, I knew I wanted to:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Utilize the design tokens provided by InVision DSM&lt;/li&gt;
&lt;li&gt;Build the components using styled-components and styled-system&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Out of the box, achieving this would require some manual effort; and that’s not fun for anyone.&lt;/p&gt;

&lt;p&gt;Specifically, the two manual interventions were:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Integrating the design tokens into the code base:&lt;/strong&gt; The DSM provides you with nine URLs to different design token file types, leaving it up to you to decide how to integrate them into your project (i.e. download and distribute them in your bundle).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Transforming the design token schema into a Styled System theme:&lt;/strong&gt; The design token files use a schema that is not the same as the &lt;a href="https://styled-system.com/theme-specification/"&gt;styled-system theme schema,&lt;/a&gt; so manual mapping from one schema to the other is required.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Developing some handy Node scripts
&lt;/h2&gt;

&lt;p&gt;I sought to solve this problem through a couple of Node.js scripts that Rangle has now released with an MIT license and has made available on the NPM registry. The package is called invision-dsm-utils and it currently contains two scripts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Download:&lt;/strong&gt; Download design token files from InVision DSM &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Transform:&lt;/strong&gt; Transform those design tokens into a JavaScript object that meets  the Styled System Theme Specification&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--dev&lt;/span&gt; invision-dsm-utils
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Download design tokens in JSON
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;invision-dsm-utils download json ./src
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Set-up configuration file .invisiondsmutilsrc
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
    dsmExportUrl: string,
    key: string
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Transform JSON into JavaScript object that meets the Styled System Theme Specification
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;invision-dsm-utils transform ./src/style-data.json ./src/theme.dsm.js
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Use scripts in development flow
&lt;/h3&gt;

&lt;p&gt;In my React app, I added these scripts into my package.json as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
 &lt;span class="s2"&gt;"scripts"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"tokens:download"&lt;/span&gt;: &lt;span class="s2"&gt;"invision-dsm-utils download json ./src"&lt;/span&gt;,
    &lt;span class="s2"&gt;"tokens:transform"&lt;/span&gt;: &lt;span class="s2"&gt;"invision-dsm-utils transform ./src/style-data.json ./src/theme.dsm.js"&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can be even more creative with this by triggering these scripts on a &lt;code&gt;postinstall&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Use theme in App
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&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;Component&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="p"&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;ThemeProvider&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;styled-components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;themeDSM&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;./src/theme.dsm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// You could add additional values to themeDSM by&lt;/span&gt;
&lt;span class="c1"&gt;// extending the object&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&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;themeDSM&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="na"&gt;space&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;128&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;512&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;App&lt;/span&gt; &lt;span class="kd"&gt;extends&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ThemeProvider&lt;/span&gt; &lt;span class="na"&gt;theme=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Example&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ThemeProvider&lt;/span&gt;&lt;span class="p"&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="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;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Contribute to package
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/rangle/invision-dsm-utlities"&gt;invision-dsm-utils&lt;/a&gt; is an open source project and we encourage you to submit pull requests to improve and extend this library for your InVision DSM needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  About Rangle and InVision partnership
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://rangle.io/blog/rangle-becomes-invision-partner/"&gt;Rangle and InVision are proud to announce a strategic partnership&lt;/a&gt;, enabling Rangle to advise InVision’s clients on successful approaches to Design Systems and Design Operations. This new offering will cover a wide range of topics, including building and maintaining a design system using InVision Design System Manager, ensuring wide adoption, and methods to improve collaboration between designers and developers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommended InVision DSM documentation
&lt;/h2&gt;

&lt;p&gt;InVision has done an exceptional job creating documentation and content for InVision Design System Manager. As a first time user of their system, I used the following resources to get my project up and running.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.invisionapp.com/design-system-manager/learn"&gt;Explore the Possibilities of InVision DSM&lt;/a&gt; [Video] &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://support.invisionapp.com/hc/en-us/articles/115005685166-Intro-to-DSM"&gt;Intro to DSM&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://support.invisionapp.com/hc/en-us/articles/207773013-Using-Craft-by-InVision"&gt;Using Craft by InVision&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.invisionapp.com/inside-design/dsm-design-tokens/"&gt;A step-by-step guide to using design tokens in InVision DSM&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.invisionapp.com/hc/en-us/articles/360029167532-DSM-in-Inspect"&gt;DSM in Inspect&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://support.invisionapp.com/hc/en-us/sections/360004449791-Design-System-Manager-DSM-"&gt;Design System Manager Knowledge Base&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Styled Components, Styled Systems and How They Work</title>
      <dc:creator>cdepaul</dc:creator>
      <pubDate>Thu, 12 Dec 2019 15:48:55 +0000</pubDate>
      <link>https://forem.com/rangle/styled-components-styled-systems-and-how-they-work-28km</link>
      <guid>https://forem.com/rangle/styled-components-styled-systems-and-how-they-work-28km</guid>
      <description>&lt;p&gt;Sometimes the libraries that we use daily can seem a little bit like magic. By taking the time to understand the fundamental JavaScript features that make these libraries possible, we become better equipped to improve our use of those libraries, applying their functionality in unique and relevant ways.&lt;/p&gt;

&lt;p&gt;In React, there are two libraries that work together to make the creation of presentational components very simple: styled-components and styled-system.&lt;/p&gt;

&lt;p&gt;Here is an example of these libraries working together, courtesy of the &lt;a href="https://styled-system.com/"&gt;styled-system documentation&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&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;styled-components&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;color&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;styled-system&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;Box&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;`
  &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="s2"&gt;
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This code created a React component named Box that receives the props color and bg.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#fff"&lt;/span&gt; &lt;span class="na"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"tomato"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
  Tomato
&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In this article I am going to cover:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Generating React Components with Tagged Templates&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Implementing a simple version of Styled Components&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Diving into how styled-components and styled-systems actually operate together&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Template Literals
&lt;/h2&gt;

&lt;p&gt;In order to understand how styled-components and styled-systems work, it's best to first understand where these libraries get their power from: Template Literals.&lt;/p&gt;

&lt;p&gt;The most common use-case of Template Literals is string concatenation.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Template Literal&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`I am a template literal, because I am enclosed by the back-tick`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Template Literal with placeholder&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expressions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dynamic values&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;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`I can contain &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;expressions&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Template Literals are clean, they are effective and they have been so well adopted for string concatenation that some of us (e.g. me) don’t even care how this syntax works, or realize that its functionality can be expanded upon.&lt;/p&gt;

&lt;h2&gt;
  
  
  Template Literals and the preceding function
&lt;/h2&gt;

&lt;p&gt;When we implement Template Literals, something unintuitive happens: The contents of the Template Literal (e.g. the text and placeholders) are passed to a function.&lt;/p&gt;

&lt;p&gt;Which function? In the two examples above, a &lt;em&gt;default function&lt;/em&gt; with the job of concatenating the text and placeholders into a single string.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;expressions&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;dynamic values&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;example&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`I can contain &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;expressions&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;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="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// &amp;gt;&amp;gt; I can contain dynamic values&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But Template Literals are not confined to performing only string concatenations. JavaScript lets us use our own custom functions to do whatever we want with the text and placeholders within the Template Literal. This type of function is called a &lt;em&gt;Tag&lt;/em&gt; and to use it, you simply reference the function name — the Tag — in front of the Template Literal. Doing this results in the creation of a Tagged Template.&lt;/p&gt;

&lt;p&gt;For example, here is a simple function that does not accept any parameters and prints a static message to the console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;printStaticMessage&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="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;My static message&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;We can invoke this function in two ways: As a traditional function call and as a Tagged Template.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="nx"&gt;printStaticMessage&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;  &lt;span class="c1"&gt;// &amp;gt;&amp;gt;&amp;gt; My static message&lt;/span&gt;
&lt;span class="nx"&gt;printStaticMessage&lt;/span&gt;&lt;span class="s2"&gt;``&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;  &lt;span class="c1"&gt;// &amp;gt;&amp;gt;&amp;gt; My static message&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice that each invocation generated the same result. So, we can conclude that Tagged Templates are just an alternative way to invoke a function.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using the Template Literal as Arguments for the Tag
&lt;/h2&gt;

&lt;p&gt;A more useful Tagged Template would utilize the text and placeholders within the Template Literal. Let’s create a Tag that prints out its arguments.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;printArguments&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&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="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(...&lt;/span&gt;&lt;span class="nx"&gt;args&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;var1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my&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;var2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="nx"&gt;printArguments&lt;/span&gt;&lt;span class="s2"&gt;`This is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;var1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; custom &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;var2&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="c1"&gt;// &lt;/span&gt;
&lt;span class="c1"&gt;//   ["This is "," custom ","!"],&lt;/span&gt;
&lt;span class="c1"&gt;//   "my",&lt;/span&gt;
&lt;span class="c1"&gt;//   "message"&lt;/span&gt;
&lt;span class="c1"&gt;//&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The first argument is an array of strings that represent the text in the Template Literal, separated into elements based on the location of the placeholders.&lt;/p&gt;

&lt;p&gt;The remaining &lt;em&gt;n&lt;/em&gt; arguments are strings with the value of each placeholder, ordered based on when they are defined in the Template Literal.&lt;/p&gt;

&lt;p&gt;Knowing that these are the arguments that Tags receive, we can guess what the implementation of the default Template Literals concatenation function looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;defaultFunction&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stringArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;values&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="nx"&gt;stringArray&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;i&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="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;str&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;acc&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;str&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="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;var1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;my&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;var2&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;message&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;example&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;defaultFunction&lt;/span&gt;&lt;span class="s2"&gt;`This is &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;var1&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; custom &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;var2&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;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="nx"&gt;example&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// &amp;gt;&amp;gt;&amp;gt; This is my custom message!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Passing functions into the Tagged Template
&lt;/h2&gt;

&lt;p&gt;Since the Tag is simply receiving the Template Literal placeholders as argument variables, those variables can contain any JavaScript object, like a number, string or function. Here is an non-useful example where we pass a function in the Template Literal placeholder and execute it in the Tag.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;executeFirstPlaceholder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;textArray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;placeholder&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;placeholder&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;executeFirstPlaceholder&lt;/span&gt;&lt;span class="s2"&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="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;first placeholder&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;span class="p"&gt;;&lt;/span&gt; 

&lt;span class="c1"&gt;// &amp;gt;&amp;gt;&amp;gt; first placeholder&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Returning functions from a Tagged Template
&lt;/h2&gt;

&lt;p&gt;Like any other function in JavaScript, a Tagged Template can return objects, strings, numbers, and, of course, functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;multiply&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;multiple&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;num&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
  &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;num&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nb"&gt;parseInt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;multiple&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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;double&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;multiply&lt;/span&gt;&lt;span class="s2"&gt;`2`&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;double&lt;/span&gt;&lt;span class="s2"&gt;`4`&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="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;  &lt;span class="c1"&gt;// &amp;gt;&amp;gt;&amp;gt; 8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Making the leap to React
&lt;/h2&gt;

&lt;p&gt;React’s “function components” are very simply JavaScript functions that can be rendered into the DOM. Here is an example of a Tagged Template returning a React function component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;withGreeting&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;greeting&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;name&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;greeting&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;, &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;!&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Greet&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;withGreeting&lt;/span&gt;&lt;span class="s2"&gt;`Greetings`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Render component&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Greet&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Chris"&lt;/span&gt; &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Renders in DOM&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Greetings, Chris&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is the crux for how Styled Components generate React components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Styled Components
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Utilising tagged template literals (a recent addition to JavaScript) and the power of CSS, styled-components allows you to write actual CSS code to style your components. It also removes the mapping between components and styles — using components as a low-level styling construct could not be easier!&lt;/em&gt;&lt;br&gt;
 &lt;a href="https://www.styled-components.com"&gt;https://www.styled-components.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Styled Components use Tagged Templates to return React components.&lt;/p&gt;

&lt;p&gt;In the following example, styled.h1 is used to create a simple React component containing a &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; HTML tag, display using the CSS styles specified within the Template Literal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&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;styled-components&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;Title&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;h1&lt;/span&gt;&lt;span class="s2"&gt;`color: blue;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Render&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Regular Title&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Title&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Renders to DOM&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"color: blue;"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Regular Title&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The styled object contains keys named after common HTML tags — like H1, H2, and div. These keys reference a function that can be used as the Tag in a Tagged Template.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple implementation of styled.h1
&lt;/h2&gt;

&lt;p&gt;Let’s try to make a simple implementation of styled.h1. At it's simplest, the styled.h1 function receives the CSS styles in the back-ticks and transforms them into a style object that it attaches to the underlying element (e.g. h1).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;styledH1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="nx"&gt;styles&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="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;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styles&lt;/span&gt;
                  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;;&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;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
                  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c1"&gt;// Function courtesy of mck89 on StackOverflow&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;convertToCamelCase&lt;/span&gt; &lt;span class="o"&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="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;replace&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-z&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="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;up&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;up&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;toUpperCase&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="nx"&gt;lines&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;acc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;line&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;lineParsed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;line&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;:&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;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;convertToCamelCase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;lineParsed&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&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;val&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;lineParsed&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;acc&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="nx"&gt;val&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;style&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&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;H1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;styledH1&lt;/span&gt;&lt;span class="s2"&gt;`
  color: red;
  font-size: 18px;
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Render&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;H1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Renders in DOM&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt; &lt;span class="na"&gt;style&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"color: red; font-size: 18px;"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;At this point, the style we are passing to the function is hard coded and fixed; not able to dynamically change, based on the prop values the component receives.&lt;/p&gt;

&lt;p&gt;Let’s look at how the ability to pass functions into our tagged templates can enable things to become more dynamic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using functions to access Props in Template Literals and Styled Components
&lt;/h2&gt;

&lt;p&gt;As discussed we discussed, a function passed to a Template Literal placeholder can be executed. Styled Components utilize this feature to generate dynamic styles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&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;styled-components&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;Button&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;`
  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;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="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;primary&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="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&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;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;StyledComponentsDemo&lt;/span&gt; &lt;span class="kd"&gt;extends&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="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Primary&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Secondary&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt; &lt;span class="na"&gt;primary&lt;/span&gt; 
                &lt;span class="na"&gt;onSubmit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&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;handleSubmit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Submit
        &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&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;When the Styled Component is rendered, each function in the Template Literal is passed the component’s props and those props can be used to impact the presentation of the component.&lt;/p&gt;

&lt;p&gt;Note: not all props passed to a Styled Component need to impact the presentation (e.g. onSubmit); they could also be used only by the underlying HTML element.&lt;/p&gt;

&lt;h2&gt;
  
  
  Styling regular, custom components
&lt;/h2&gt;

&lt;p&gt;Styled Components allow you to style any custom component that you’ve created. First, the custom component must receive the prop className and pass it to the underlying DOM element. Once that is done, pass the custom component to the styled function and invoke it as a Tagged Template to receive a new Styled Component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&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;styled-components&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;Button&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;className&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;className&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;button&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;ButtonBlue&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="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;`color: blue`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// Render&lt;/span&gt;
&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ButtonBlue&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Blue Button&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ButtonBlue&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Styling the Styled Components
&lt;/h2&gt;

&lt;p&gt;Styled Components uses the CSS preprocessor &lt;a href="https://stylis.js.org/"&gt;stylis&lt;/a&gt;, supporting SCSS-like syntax for automatically nesting styles.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Thing&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;`
  color: black;

  :hover {
    color: blue;
  }
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Within SCSS syntax, &amp;amp; references the current component. You can also reference other components like you would reference any other type of selector (e.g. .class or #id) by simply referencing ${OtherComponentName} , but only if it is a Styled Component.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&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;styled-components&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;Item&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: red;
`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Container&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;`
  &amp;amp; &amp;gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; {
    font-size: 2rem;
  }
`&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;StyledComponentsDemo&lt;/span&gt; &lt;span class="kd"&gt;extends&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Container&lt;/span&gt;&lt;span class="p"&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;As you can see, we have the ability to not only specify the styles in our components, but also the ability to add some dynamic functionality. Building on this, we are able to better accommodate some common use cases such as adding themes to our applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Themes
&lt;/h2&gt;

&lt;p&gt;Theming is accomplished by exporting the ThemeProvider component, passing an object to its theme prop, and wrapping the entire app in the ThemeProvider component. This will give every Styled Component access to the theme object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ThemeProvider&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;styled-components&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;Item&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="p"&gt;)&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;theme&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;primary&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
`&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&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="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;primary&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;red&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="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;StyledComponentsDemo&lt;/span&gt; &lt;span class="kd"&gt;extends&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ThemeProvider&lt;/span&gt; &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Item 1&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Item&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ThemeProvider&lt;/span&gt;&lt;span class="p"&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;Components that are &lt;em&gt;not&lt;/em&gt; Styled Components can also access theme by using the withTheme function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&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;withTheme&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;styled-components&lt;/span&gt;&lt;span class="dl"&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;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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;&lt;span class="si"&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;theme&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;primary&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;p&lt;/span&gt;&lt;span class="p"&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;withTheme&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;MyComponent&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Styled System
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;Styled System is a collection of utility functions that add style props to your React components and allows you to control styles based on a global theme object with typographic scales, colors, and layout properties.&lt;/em&gt;&lt;br&gt;
 &lt;a href="https://styled-system.com"&gt;https://styled-system.com&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you created a Button component from Styled Components and you want it to receive foreground and background color props, you can use the styled-system utility function color and pass it as a placeholder function in the Template Literal to enable these props.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;styled&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ThemeProvider&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;styled-components&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&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;color&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;styled-system&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;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;primary&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="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Box&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;`
  &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="s2"&gt;
`&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nx"&gt;StyledSystemDemo&lt;/span&gt; &lt;span class="kd"&gt;extends&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="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ThemeProvider&lt;/span&gt; &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"#fff"&lt;/span&gt; &lt;span class="na"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"tomato"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Tomato&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
          &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt; &lt;span class="na"&gt;color&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"white"&lt;/span&gt; &lt;span class="na"&gt;bg&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"primary"&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Tomato&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;ThemeProvider&lt;/span&gt;&lt;span class="p"&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;Note: The name of the generated props are all outlined in the &lt;a href="https://styled-system.com/api/"&gt;styled system API&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If there is a theme available, the utility function will try to match the prop value to the theme before using the value as the raw value (e.g. #fff).&lt;/p&gt;

&lt;h2&gt;
  
  
  Structuring Theme objects
&lt;/h2&gt;

&lt;p&gt;The structure of the theme object and styled-system are tightly coupled. The structure follows a Work-in-Progress specification called &lt;a href="https://system-ui.com/theme/"&gt;System UI Theme Specification&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For instance, the fontSizes and colors keys follow this specification, and their values (arrays or objects) also follow this specification.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;theme&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="na"&gt;fontSizes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;32&lt;/span&gt;
   &lt;span class="p"&gt;]&lt;/span&gt;
   &lt;span class="nx"&gt;fontSizes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fontSizes&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
   &lt;span class="na"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;blue&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#07c&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;green&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;#0fa&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;With the above theme, the fontSize prop on a component could receive the index value of the array, or the alias body.&lt;/p&gt;

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

&lt;p&gt;Let’s look at how styled-system implements the utility function color. Remember that a utility function is called like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&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;`
   &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="s2"&gt;
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This is what the function looks like.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// &amp;lt;https://github.com/styled-system/styled-system/blob/v2.3.6/src/styles.js&amp;gt;&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;color&lt;/span&gt; &lt;span class="o"&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="p"&gt;({&lt;/span&gt;
  &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;textColor&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="nx"&gt;bgColor&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Which is akin to writing this in the Template Literal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&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;`
   &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="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;textColor&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="nx"&gt;bgColor&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="s2"&gt;
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The textColor and bgColor functions will return style objects that are spread within the function. These functions look like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// &amp;lt;https://github.com/styled-system/styled-system/blob/v2.3.6/src/styles.js&amp;gt;&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;textColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;responsiveStyle&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;color&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;colors&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// theme key&lt;/span&gt;
&lt;span class="p"&gt;})&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;bgColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;responsiveStyle&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;bg&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;cssProperty&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;backgroundColor&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;colors&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;The responsiveStyle function handles all the breakpoints, fallbacks and prop naming. Below, I simplified the styled-system code for demonstrative purposes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="c1"&gt;// &amp;lt;https://github.com/styled-system/styled-system/blob/v2.3.6/src/util.js&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// I simplified this for demonstrative purposes&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;responsiveStyle&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;prop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;cssProperty&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="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;fn&lt;/span&gt; &lt;span class="o"&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="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;cssProperty&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;cssProperty&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;prop&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;n&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;prop&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;theme&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;theme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;cssProperty&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;theme&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="nx"&gt;n&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="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fn&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Which can be represented to look something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Button&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;`
   {
     &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="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="nx"&gt;props&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;colors&lt;/span&gt;&lt;span class="dl"&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;color&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="s2"&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="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;backgroundColor&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;theme&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;colors&lt;/span&gt;&lt;span class="dl"&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;bg&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="s2"&gt;
   }
`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Breakpoints and responsive themes
&lt;/h2&gt;

&lt;p&gt;For responsive themes, styled-system lets you establish breakpoints in the theme and then lets you pass an array as a prop with different values for each breakpoint. styled-system takes a mobile first approach, so the first index will always be the smallest breakpoint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Box&lt;/span&gt;
  &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 100% below the smallest breakpoint (all viewports)&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 50% from the next breakpoint and up&lt;/span&gt;
    &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 25% from the next breakpoint and up&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="c1"&gt;// theme.js&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;breakpoints&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;40em&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;52em&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;64em&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;80em&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="nx"&gt;breakpoints&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



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

&lt;p&gt;I was inspired to see how the developers of styled-components and styled-system employed the extended functionality of Template Literals and Tagged Templates to provide users with an intuitive way for adding SCSS to React components.&lt;/p&gt;

&lt;p&gt;Have you seen any interesting uses of common functionality in your work recently? Please share!&lt;/p&gt;

&lt;h2&gt;
  
  
  Sources
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://styled-system.com/"&gt;Styled System&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.styled-components.com/"&gt;Styled Components&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://mxstbr.blog/2016/11/styled-components-magic-explained/"&gt;The magic behind 💅 styled-components&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals"&gt;MDN Web Docs: Template Literals&lt;/a&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>design</category>
      <category>css</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Are Your Unit Tests Failing for the Expected Reasons?</title>
      <dc:creator>Evan Schultz (he/him)</dc:creator>
      <pubDate>Wed, 11 Dec 2019 13:16:56 +0000</pubDate>
      <link>https://forem.com/rangle/are-your-unit-tests-failing-for-the-expected-reasons-4n26</link>
      <guid>https://forem.com/rangle/are-your-unit-tests-failing-for-the-expected-reasons-4n26</guid>
      <description>&lt;p&gt;Unit tests can be an invaluable tool in the developers toolbox. You don't need to be a strict TDD purist to make unit testing worthwhile. Once you get into the flow of writing tests, it can be rather satisfying to watch the Nyan Cat Reporter go across your screen as the number of tests passing increase.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fbluc7iqlr7nccee36fvu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fbluc7iqlr7nccee36fvu.png" alt="Nyan Cat Test Runner" width="492" height="98"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As with any other tool though, it can be misused, and not always provide the benefit that you want or expect.&lt;/p&gt;

&lt;p&gt;The other day I was doing some code clean up, and came across a test that started to make me ask questions instead of having them answered.&lt;/p&gt;

&lt;p&gt;Some of the questions that a unit test should be answering:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is it testing?&lt;/li&gt;
&lt;li&gt;What is it doing?&lt;/li&gt;
&lt;li&gt;What is expected behavior?&lt;/li&gt;
&lt;li&gt;What is the actual behavior?&lt;/li&gt;
&lt;li&gt;Does it pass or fail for the expected reasons?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The test that made me go 'hrmm?' looked something like this:&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;/// .... mock removed for now&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should call /location/calculate-distance correctly&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="o"&gt;=&amp;gt;&lt;/span&gt;
   &lt;span class="nx"&gt;locationApi&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;calculateDistance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&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;expect&lt;/span&gt;&lt;span class="p"&gt;(&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;distance&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ok&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reading this unit test, it's not really clear what is actually being tested. The it block is saying that it should call &lt;code&gt;/location/calculate-distance&lt;/code&gt; correctly, but the expect at the bottom is looking at the response.&lt;/p&gt;

&lt;p&gt;Currently this test is passing, but it's not passing for a reason that the test states it should be. Yes, there is something responding, but response.distance being ok has nothing to do with the behavior we wanting to verify.&lt;/p&gt;

&lt;p&gt;This application was using &lt;a href="https://github.com/matthew-andrews/isomorphic-fetch" rel="noopener noreferrer"&gt;ismorphic-fetch&lt;/a&gt; and &lt;a href="https://www.npmjs.com/package/fetch-mock" rel="noopener noreferrer"&gt;fetch-mock&lt;/a&gt; to mock out HTTP requests. The mock for this test looks 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="nf"&gt;before&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;fetchMock&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;url&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="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;url&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="nx"&gt;LOCATION_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;calculate-distance?&amp;amp;lat1=10&amp;amp;long1=20&amp;amp;lat2=30&amp;amp;long2=40&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="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;method&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&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;body&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;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;distance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
      &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&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="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;This starts to give a bit more insight, and after digging around that was going on in &lt;code&gt;locationApi.calculateDistance&lt;/code&gt; - it seems like this test is wanting to verify that for a given set of parameters, the URL is formed up correctly to query the API to calculate the distance.&lt;/p&gt;

&lt;p&gt;When the test runs, it currently passes. If it fails though, am I getting useful information? If I tweak the location code in how it forms the URL, the errors that get reported look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1) api/location should call /location/calculate-distance correctly:
     Error: only absolute urls are supported
      at node_modules/node-fetch/index.js:54:10
      at new Fetch (node_modules/node-fetch/index.js:49:9)
      at Fetch (node_modules/node-fetch/index.js:37:10)
      at module.exports (node_modules/isomorphic-fetch/fetch-npm-node.js:8:19)
      at FetchMock.fetchMock (node_modules/fetch-mock/src/fetch-mock.js:265:17)
      at exports.default (src/api/helpers/composer-request.js:14:12)
      at Object.exports.getTaxEstimate (src/api/location-api.js:8:10)
      at Context.&amp;lt;anonymous&amp;gt; (src/api/location-api.test.js:27:13)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And hidden away at the top of the unit tests running and easy to miss, is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;api/location
unmatched call to /location!calculate-distance?lat1=10&amp;amp;long1=20&amp;amp;lat2=30&amp;amp;long2=40
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This isn't terribly useful information. The error that is getting reported doesn't tell me anything about what the expected and actual results were.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Error: only absolute urls are supported&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This is an error thrown by fetch-mock before our expect statements have even been hit. There is a hint at the top of the unit test reports where fetch-mock will complain about an unmatched call.&lt;/p&gt;

&lt;p&gt;This message is easy to miss, and it also requires the person reading the unit test results to understand a bit of how fetch-mock works get pointed in the right direction.&lt;/p&gt;

&lt;p&gt;For a seemingly simple unit test, it asks more questions than it answers.&lt;/p&gt;

&lt;p&gt;A more accurate description of this test 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="nf"&gt;describe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fetch-mock behavior&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should return the object I told it to if no error is thrown&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="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;If we were the authors of &lt;a href="https://www.npmjs.com/package/fetch-mock" rel="noopener noreferrer"&gt;fetch-mock&lt;/a&gt;, that could possibly be a useful test. But, we are wanting to write unit tests for the system we are building, not for the mocking frameworks we are using.&lt;/p&gt;

&lt;p&gt;The fact that &lt;code&gt;expect(res.distance).to.equal('ok');&lt;/code&gt; is more of a coincidence than the behavior you want to test.&lt;/p&gt;

&lt;p&gt;What can we do to make it clear what the intended purpose of this test is, and that it provides meaningful errors when it fails?&lt;/p&gt;

&lt;p&gt;Let's revisit the questions we asked at the start, and clean up the test to start answering them.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is it testing?
&lt;/h2&gt;

&lt;p&gt;When the &lt;code&gt;calculateDistance&lt;/code&gt; is called, then an API is called with a specific URL and query parameters. The response object is inconsequential here. Let's adjust the unit test to start being more descriptive and accurate.&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should call calculate-distance with correct query parameters&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="o"&gt;=&amp;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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The 'it' sentence starts to describe what we are doing without needing to read the test body.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is it doing?
&lt;/h2&gt;

&lt;p&gt;The initial test wasn't that bad at answering this one, it's calling the &lt;code&gt;locationApi.calculateDistance&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should call calculate-distance with correct query parameters&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="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="nx"&gt;locationApi&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;calculateDistance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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;// ..&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;
  
  
  What is the expected / actual behavior
&lt;/h2&gt;

&lt;p&gt;This is where the previous test started to fail at answering these questions. &lt;/p&gt;

&lt;p&gt;We don't care if the response object has a distance of 'ok', we want to verify the URL that is being hit.&lt;/p&gt;

&lt;p&gt;In answering this question, we can state what the expected and actual results are.&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="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should call calculate-distance with correct query parameters&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="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;EXPECTED_URL&lt;/span&gt; &lt;span class="o"&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;LOCATION_ENDPOINT&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/calculate-distance?lat1=10&amp;amp;long1=20&amp;amp;lat2=30&amp;amp;long2=40`&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;locationApi&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;calculateDistance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&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;ACTUAL_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetchMock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lastUrl&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;EXPECTED_URL&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;to&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ACTUAL_URL&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;Now when reading the unit test, the expected reasons for passing/failing are more obvious. The thing that I am asserting is reflective of the behavior that I want.&lt;/p&gt;

&lt;p&gt;However, if the test fails, the output still isn't very useful and still complains about: &lt;code&gt;Error: only absolute urls are supported&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This leads to answering the final question:&lt;/p&gt;

&lt;h2&gt;
  
  
  Does it pass or fail for the expected reasons?
&lt;/h2&gt;

&lt;p&gt;Currently fetch-mock is throwing an error before we even hit our expect statement, so we can't guarantee that things are passing or failing for the reasons we expect.&lt;/p&gt;

&lt;p&gt;Adjusting our mock is pretty straightforward. Instead of having the mock be very specific for a URL, I am adjusting it to match just about anything that begins with a slash.&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="nf"&gt;before&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;fetchMock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mock&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="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="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ok&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
     &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&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="p"&gt;}));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we run our test and if it fails, the error that gets reported is now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;1) should call calculate-distance with correct query parameters:

      AssertionError: expected '/location!calculate-distance?lat1=10&amp;amp;long1=20&amp;amp;lat2=30&amp;amp;long2=40' to equal '/location/calculate-distance?lat1=10&amp;amp;long1=20&amp;amp;lat2=30&amp;amp;long2=40'
      + expected - actual

      -/location!calculate-distance?lat1=10&amp;amp;long1=20&amp;amp;lat2=30&amp;amp;long2=40
      +/location!calculate-distance?lat1=10&amp;amp;long1=20&amp;amp;lat2=30&amp;amp;long2=40

      at src/api/location-api.test.js:21:29
      at process._tickCallback (internal/process/next_tick.js:103:7)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With a few minor changes to the unit test and the mock, the test is starting to answer questions, instead of making us ask them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The mock has been simplified and is easier to understand.&lt;/li&gt;
&lt;li&gt;The expect statement makes it clear the behavior that we are testing.&lt;/li&gt;
&lt;li&gt;The test fails for the correct reason - actual does not meet expected behavior.&lt;/li&gt;
&lt;li&gt;When the test fails, it is descriptive to what the error is.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Next time you're writing a unit test or reviewing others, maybe double check to ensure that they are passing or failing for the reasons that you expect.&lt;/p&gt;

&lt;p&gt;If reading a unit test makes you ask questions, then it could be a sign that you need to clean them up to make them more useful.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;initially posted on the &lt;a href="https://rangle.io/blog/are-your-unit-tests-failing-for-the-expected-reasons" rel="noopener noreferrer"&gt;rangle.io blog&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>testing</category>
      <category>tdd</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Improving your mental model of useEffect</title>
      <dc:creator>Evan Schultz (he/him)</dc:creator>
      <pubDate>Wed, 11 Dec 2019 12:55:15 +0000</pubDate>
      <link>https://forem.com/rangle/improving-your-mental-model-of-useeffect-lbm</link>
      <guid>https://forem.com/rangle/improving-your-mental-model-of-useeffect-lbm</guid>
      <description>&lt;p&gt;Hooks landed in React a few months ago, and there has been a lot of excitement around them in terms of figuring out how to best use them, best practices, and how they map to current concepts in React and the lifecycle.&lt;/p&gt;

&lt;p&gt;Many React developers are familiar with the React Component lifeCycle, and hooks like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/docs/react-component.html#componentdidmount" rel="noopener noreferrer"&gt;componentDidMount&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/docs/react-component.html#componentdidupdate" rel="noopener noreferrer"&gt;componentDidUpdate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/docs/react-component.html#shouldcomponentupdate" rel="noopener noreferrer"&gt;shouldComponentUpdate&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;etc.&lt;/p&gt;

&lt;p&gt;When trying to understand the &lt;code&gt;useEffect&lt;/code&gt; hook, it's natural to want to map it to the lifecycle methods we already know. At first glance, &lt;code&gt;useEffect&lt;/code&gt; seems to be like a combination of &lt;code&gt;componentDidMount&lt;/code&gt; and &lt;code&gt;componentDidUpdate&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;While this can be a useful way of looking at it at first, it may not be the most accurate.&lt;/p&gt;

&lt;p&gt;Instead of thinking in terms of 'what do I want to do when I mount, or when I update', it's more useful to ask:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;What values does this effect depend on?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To better understand where the idea of &lt;code&gt;useEffect = componentDidMount + componentDidUpdate&lt;/code&gt; comes from, we will first look at a typical class-based component that is doing some data fetching.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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="nx"&gt;SearchComponent&lt;/span&gt; &lt;span class="kd"&gt;extends&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;constructor&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;super&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="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="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;results&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="nf"&gt;componentDidMount&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="nf"&gt;query&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;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;componentDidUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;prevProps&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&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;prevProps&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;props&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&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;id&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;query&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;&lt;span class="na"&gt;isLoading&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="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/some/url/&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="s2"&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&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="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;results&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;results&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;When the component first mounts, we fetch data for the id that has been passed down as a prop. When the component updates, many things other than the id prop changing can cause this method to run, so we want to ensure that id has actually changed - or some poor server is going to get a DDoS attack with a bunch of API calls that we don't need.&lt;/p&gt;

&lt;p&gt;While the lifecycle hooks of &lt;code&gt;componentDidMount&lt;/code&gt; and &lt;code&gt;componentDidUpdate&lt;/code&gt; with class-based components are common places to make a request based on a property, the fact that the component is mounting or updating is not really the thing we are concerned with.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we are actually concerned with?
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;"what data does the query depend on?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before looking at how to handle this with &lt;code&gt;useEffect&lt;/code&gt;, lets quickly review the &lt;a href="https://reactjs.org/docs/hooks-reference.html#useeffect" rel="noopener noreferrer"&gt;API of useEffect&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Accepts a function&lt;/li&gt;
&lt;li&gt;If it returns a function, it will do cleanup when the component is unmounted&lt;/li&gt;
&lt;li&gt;Has an optional 2nd argument to pass in the data it depends on&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One of the key things to keep in mind is the importance of that second argument, the &lt;a href="https://reactjs.org/docs/hooks-effect.html" rel="noopener noreferrer"&gt;React Docs&lt;/a&gt; go into this in detail, but a summary is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If we leave it blank - it will run on every single render.&lt;/li&gt;
&lt;li&gt;If we pass in an empty array - it will execute only when the component mounts, and not on any updates&lt;/li&gt;
&lt;li&gt;If we pass in a value - it will execute when any of those values change&lt;/li&gt;
&lt;li&gt;If you are using the &lt;a href="https://www.npmjs.com/package/eslint-plugin-react-hooks" rel="noopener noreferrer"&gt;react-hooks eslint plugin&lt;/a&gt; (and you should) - not providing the dependencies to your useEffect will give you warnings.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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="nx"&gt;SomeComponent&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setResults&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;
  &lt;span class="nf"&gt;useEffect&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/some/url/&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="s2"&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;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the class-based version, making API calls feels very imperative - when this method is called, I want to check if/how a value has changed, and if it has changed - I want to call a method.&lt;/p&gt;

&lt;p&gt;If the component is being created or updated often isn't the thing the matters. What we actually care about is "has the values that I care about changed?".&lt;/p&gt;

&lt;p&gt;Before hooks were introduced, &lt;code&gt;componentDidMount&lt;/code&gt; and &lt;code&gt;componentDidUpdate&lt;/code&gt; were the best tools for the job at the time.&lt;br&gt;
With the hook based version, we are able to express this intent in a more declarative way: "I want to fetch data when the id changes"&lt;/p&gt;
&lt;h1&gt;
  
  
  How do we identify what the effect depends on?
&lt;/h1&gt;

&lt;p&gt;The eslint plugin can guide you in the right direction, but the short version is: "is there a variable that impacts how we run the effect?" If so, add it to the dependencies.&lt;/p&gt;

&lt;p&gt;To demonstrate this, let's add an extra query parameter to our search:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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="nx"&gt;SomeComponent&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;filter&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;let&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setResults&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/some/url/&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="s2"&gt;?filter=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filter&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Even though we have added filter to the fetch query string, we have not added it to the dependencies of &lt;code&gt;useEffect&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;As we update the filter, we won't be calling the API on any of the other updates, and it will only run when the id has changed.&lt;/p&gt;

&lt;p&gt;Fixing this can be simple enough - add the filter to the list of dependencies for the &lt;code&gt;useEffect&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&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="nx"&gt;SomeComponent&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;filter&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;let&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;results&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setResults&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;([]);&lt;/span&gt;

  &lt;span class="nf"&gt;useEffect&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;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/some/url/&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="s2"&gt;?filter=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filter&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&lt;/span&gt;&lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;setResults&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;r&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="nx"&gt;filter&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;As you can see, to properly use &lt;code&gt;useEffect&lt;/code&gt;, in this case, we don't care if the component is mounting, or updating, or where it is in the life cycle. &lt;/p&gt;

&lt;p&gt;What we do care about is what data does this effect depend on.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;useEffect&lt;/code&gt; is a very useful tool to add to our toolbox when working with React, but it can also be one of the more difficult hooks to fully understand.&lt;/p&gt;

&lt;p&gt;Hopefully, this post can help clarify things a little bit better, but if you are curious for a deeper dive, be sure to check out Dan Abramovs' post, &lt;a href="https://overreacted.io/a-complete-guide-to-useeffect/" rel="noopener noreferrer"&gt;A Complete Guide to useEffect&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;&lt;em&gt;this article was initially posted on the &lt;a href="https://rangle.io/blog/improving-your-mental-model-of-useeffect" rel="noopener noreferrer"&gt;rangle.io blog&lt;/a&gt; and &lt;a href="https://medium.com/rangle-io/improving-your-mental-model-of-useeffect-c27ea1e2a5a3" rel="noopener noreferrer"&gt;medium&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Running Jenkins and Persisting state locally using Docker</title>
      <dc:creator>Rangle.io </dc:creator>
      <pubDate>Tue, 10 Dec 2019 17:44:55 +0000</pubDate>
      <link>https://forem.com/rangle/running-jenkins-and-persisting-state-locally-using-docker-2ndl</link>
      <guid>https://forem.com/rangle/running-jenkins-and-persisting-state-locally-using-docker-2ndl</guid>
      <description>&lt;p&gt;Jenkins is one of the most popular Continuous Integration and Delivery Servers today, so it's only natural that you're probably interested in learning more about it. When starting out, you'll need to first run it on your local machine. However, the problem with that is the Jenkins configuration files will then live directly on your machine. A better solution is to run it as a Docker container, here are some of the reasons why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  All of your Jenkins &lt;strong&gt;configuration files&lt;/strong&gt; live inside the container rather than the host machine. Knowing that all the files you need are inside the container, you can eliminate the issue of accidentally mixing your files with Jenkins configuration files.&lt;/li&gt;
&lt;li&gt;  Docker instances are easier to manage if you are interested in running Jenkins on &lt;em&gt;multiple platforms&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  You can easily create and destroy the Jenkins server and remove all the Jenkins data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another benefit of using containers is persisting the state of your Jenkins server using Docker volumes. Why do this?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You get to keep all your projects and configurations even after restarting your computer (local machine)&lt;/li&gt;
&lt;li&gt;  You don't need to run the whole Jenkins setup again&lt;/li&gt;
&lt;li&gt;  You can remove your container instance and still able to recover the state of your Jenkins server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that in mind, I'll show you how you can start configuring Jenkins and persisting state on your local machine. Let's get started!&lt;/p&gt;

&lt;h3&gt;
  
  
  Jenkins setup
&lt;/h3&gt;

&lt;p&gt;Before we get started, you'll need to install Docker on your machine. If you're not sure how you can refer to this &lt;a href="https://docs.docker.com/install/"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After installing Docker, download the latest stable Jenkins image by running:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker image pull jenkins/jenkins:lts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kYZoVFLx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2AepLT8pmFrAT-JUfb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kYZoVFLx--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2AepLT8pmFrAT-JUfb.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Persisting Jenkins Data
&lt;/h3&gt;

&lt;p&gt;You can create a volume by running the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker volume create [YOUR VOLUME]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Volumes are used to make sure that you don't lose your Jenkins data. If you are using the &lt;code&gt;-v&lt;/code&gt; flag on container creation ( &lt;code&gt;docker container run&lt;/code&gt;), feel free to skip this step since Docker will automatically create the volume for you.&lt;/p&gt;

&lt;p&gt;Run the container by attaching the volume and assigning the targeted port. In this example, we'll also run it in detached mode. Here is the command to run your Docker container:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container run -d \ -p [YOUR PORT]:8080 \ -v [YOUR VOLUME]:/var/jenkins_home \ --name jenkins-local \ jenkins/jenkins:lts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you were wondering what the arguments stand for, here is what each means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  -d: detached mode&lt;/li&gt;
&lt;li&gt;  -v: attach volume&lt;/li&gt;
&lt;li&gt;  -p: assign port target&lt;/li&gt;
&lt;li&gt;  -name: name of the container&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And now, we're ready to take a look at an example of how you could run this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container run -d -p 8082:8080 \ -v jenkinsvol1:/var/jenkins_home \ --name jenkins-local \ jenkins/jenkins:lts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After running the command, you should be able to see the code to be used for the next step on your setup.&lt;/p&gt;

&lt;p&gt;In the command we ran, &lt;code&gt;/var/jenkins_home&lt;/code&gt; is the path to where the Jenkins state is stored on our container instance. The most important argument we pass when it comes to data persistence in this example is the &lt;code&gt;-v **[YOUR VOLUME]**:/var/jenkins_home&lt;/code&gt;. This argument is what helps Docker link the volume to the file inside the container. To learn more about Docker volumes, you can check out the &lt;a href="https://docs.docker.com/storage/volumes/"&gt;official documentation&lt;/a&gt;. If you're not familiar with Docker, you can start with this helpful docker blog series, &lt;a href="https://rangle.io/blog/learning-docker-command-line-interface/"&gt;Learning Docker - The Command Line Interface&lt;/a&gt;. You'll notice that I am using port &lt;code&gt;8082&lt;/code&gt; instead of the default &lt;code&gt;8080&lt;/code&gt;. The reason, other than demonstrating that you can use other ports, is that port &lt;code&gt;8080&lt;/code&gt; is used by some web frameworks.&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;docker ps&lt;/code&gt;, you should see your docker container running&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--utHDOyok--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2APNBlv9bjSstxPS9L.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--utHDOyok--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2APNBlv9bjSstxPS9L.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After confirming that your container is running, go to &lt;code&gt;localhost:[YOUR PORT]&lt;/code&gt; ( &lt;code&gt;localhost:8082&lt;/code&gt; on my example) on your browser and you should see this page:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BEcZw5vP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2ALJ6aicrm6-krZ1GZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BEcZw5vP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2ALJ6aicrm6-krZ1GZ.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a part of the Jenkins setup, we need to view the password inside the container instance. In order to do this, we need to use the &lt;code&gt;CONTAINER ID&lt;/code&gt; (or the name) and run &lt;code&gt;docker exec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is the full command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container exec \ [CONTAINER ID or NAME] \ sh -c "cat /var/jenkins_home/secrets/initialAdminPassword"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;After running the command, you should see the code. Copy the code and paste it on the webpage to unlock Jenkins. After unlocking, click on &lt;strong&gt;Install suggested plugins&lt;/strong&gt; on the &lt;strong&gt;Customize Jenkins&lt;/strong&gt; page.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--oFRTgLZ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2AbD6MGyYUp_qWEtj8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--oFRTgLZ8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2AbD6MGyYUp_qWEtj8.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait until the installation is complete and then you can proceed in creating your first admin user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s---aEvasrA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2ALLEhUtzeBjjnWwrK.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s---aEvasrA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2ALLEhUtzeBjjnWwrK.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After creating the admin user, setup the Instance configuration. Since you are only using Jenkins locally, leave the URL to your &lt;code&gt;localhost&lt;/code&gt; URL. Click on &lt;strong&gt;Save and Finish&lt;/strong&gt; to start using Jenkins.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--j0UK6TsJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2AhqVjL0JInO0d0M0q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--j0UK6TsJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2AhqVjL0JInO0d0M0q.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Confirming Jenkins state is persisted
&lt;/h3&gt;

&lt;p&gt;Once you get to the Jenkins home page, create a new job.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--k4ItSEoI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2Ad87mzGgB88gKhdo9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--k4ItSEoI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2Ad87mzGgB88gKhdo9.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Name the job &lt;strong&gt;Test&lt;/strong&gt; and set it to be a &lt;strong&gt;Freestyle project&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cq9Ttn5u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2Af-241x3RfgtU2mn5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cq9Ttn5u--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2Af-241x3RfgtU2mn5.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Leave everything as default and add a new &lt;strong&gt;Shell Execution&lt;/strong&gt; under &lt;strong&gt;Build.&lt;/strong&gt; Add this as the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "Working"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Save the job and click on &lt;strong&gt;Build Now&lt;/strong&gt; to start running the job.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Coks_EQ6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2Ag1rgJyIrwi1tBrg2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Coks_EQ6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2Ag1rgJyIrwi1tBrg2.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the &lt;strong&gt;Build Status (blue ball)&lt;/strong&gt; under &lt;strong&gt;Build History (left sidebar)&lt;/strong&gt; to view the console output. You should see that our command ran with no problems.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E1BMTzWz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2A47jvDSl-KxN77Xiu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E1BMTzWz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2A47jvDSl-KxN77Xiu.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Recovering Jenkins
&lt;/h3&gt;

&lt;p&gt;After confirming that the job runs, we want to make sure that we can recover our &lt;strong&gt;Jenkins&lt;/strong&gt; configuration if needed. In Jenkins, all of the configuration is stored in &lt;code&gt;/var/jenkins_home/&lt;/code&gt; by default. Remember that we are using docker volume to store information about our &lt;strong&gt;Jenkins&lt;/strong&gt; instance.&lt;/p&gt;

&lt;p&gt;In order to check if the persistence works correctly, let's destroy our current docker container and see if we can log in as an admin and view our job build history.&lt;/p&gt;

&lt;p&gt;First, run &lt;code&gt;docker container kill [CONTAINER ID]&lt;/code&gt; to stop the instance. After doing so, run &lt;code&gt;docker container rm [CONTAINER ID]&lt;/code&gt; to completely remove the container instance.&lt;/p&gt;

&lt;p&gt;Visit &lt;code&gt;localhost:[YOUR PORT]&lt;/code&gt; ( &lt;code&gt;localhost:8082&lt;/code&gt; on my example) to confirm that the Jenkins instance is not running anymore. You should see something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gWWMyoY9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2AzgmD5pfu9waTaIqi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gWWMyoY9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2AzgmD5pfu9waTaIqi.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the same command we used to create the container instance in order to recover the Jenkins instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker container run -d -p 8082:8080 \ -v jenkinsvol1:/var/jenkins_home \ --name jenkinslocal \ jenkins/jenkins:lts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You should get a new &lt;code&gt;CONTAINER ID&lt;/code&gt; after running the command. Visit &lt;code&gt;localhost:[YOUR PORT]&lt;/code&gt; ( &lt;code&gt;localhost:8082&lt;/code&gt; on my example). You should see the login page. Login with the admin credentials you set during Jenkins initialization.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zVKvfnxA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2A-g9yFfi0ZV9IEjDr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zVKvfnxA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2A-g9yFfi0ZV9IEjDr.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After logging in, you should see the &lt;strong&gt;job&lt;/strong&gt; you created and view the console output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--E_L9QNdv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2APSP8DwF9YXA5vAGN.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--E_L9QNdv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/1600/0%2APSP8DwF9YXA5vAGN.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  In summary
&lt;/h3&gt;

&lt;p&gt;I hope you can now see why Docker is the best way to start learning or at least playing around with Jenkins. You can easily run a Jenkins instance as a Docker container and persist your Jenkins server state using Docker Volumes. In case you need to restart or recover your Jenkins instance, all of the state is stored inside the Docker Volume. If you want to read more about Jenkins, Docker and DevOps, check out our other blogs, &lt;a href="https://rangle.io/blog/tag/devops/"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>jenkins</category>
      <category>docker</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Docker for Frontend Devs: Custom Docker Images for Development</title>
      <dc:creator>Rangle.io </dc:creator>
      <pubDate>Fri, 06 Dec 2019 21:16:04 +0000</pubDate>
      <link>https://forem.com/rangle/docker-for-frontend-devs-custom-docker-images-for-development-1afc</link>
      <guid>https://forem.com/rangle/docker-for-frontend-devs-custom-docker-images-for-development-1afc</guid>
      <description>&lt;p&gt;By: &lt;a href="https://medium.com/@martindevnow"&gt;Benjamin Martin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's take a moment to consider what is important for local development. For me, I want to make sure all my developers are using the same dependencies, and I don't want to worry about what versions they have installed. No more "but it works on my machine" excuses. At the same time, I want to make sure we retain the conveniences of HMR (Hot Module Replacement) so that developers don't need to constantly refresh the application to see their changes reflected. We don't want to lose fast feedback.&lt;/p&gt;

&lt;p&gt;In this article, we'll look at how we can setup Docker for a boilerplate VueJS app with custom &lt;code&gt;Dockerfile&lt;/code&gt;s from which our images and containers will be built and how we gain efficiencies from these.&lt;/p&gt;

&lt;p&gt;In case you missed the first part in this series, &lt;a href="https://blog.rangle.io/learning-docker-command-line-interface/"&gt;check here to learn more about the command line interface&lt;/a&gt; that Docker ships with. We need to use the commands from that article in this section. If you are already familiar with Docker CLI, please continue to follow along.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite: Create our project
&lt;/h2&gt;

&lt;p&gt;This is of course a Docker article, so please ensure you have Docker installed. You can follow &lt;a href="https://docs.docker.com/install/"&gt;the official install instructions for Docker here&lt;/a&gt;. Since I'm using Vue, I've used the VueCLI to spin up a quick workspace with &lt;code&gt;vue create docker-demo&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The configuration I selected (seen below) will be relevant to do E2E testing and unit testing which will become part of our CI/CD pipeline.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1_9l7UV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/nhLaIrK.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1_9l7UV8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/nhLaIrK.gif" alt="Vue CLI Create Project" title="Vue CLI Create Demo Project"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once everything is installed, &lt;code&gt;cd&lt;/code&gt; into our new project folder, open an IDE and let's dig in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Docker Image for Development
&lt;/h2&gt;

&lt;p&gt;If you've played with Docker but not built your own image, you probably know we specify an image when we execute our &lt;code&gt;docker run&lt;/code&gt; command. Those images are pulled from Docker Hub or some other remote repository (if that image is not found locally). In our case though, we want to build a custom image.&lt;/p&gt;

&lt;p&gt;In the root of our project, create a file named &lt;code&gt;Dockerfile.dev&lt;/code&gt;. This will be our development image. In that file, copy the following code into it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Base Image
FROM node:9.11.1

ENV NODE_ENV=development
ENV PORT=8080

WORKDIR /usr/src/app
COPY package*.json /usr/src/app/
RUN cd /usr/src/app &amp;amp;&amp;amp; CI=true npm install

EXPOSE 8080
CMD ["npm", "run", "serve"]

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ok... but what does all this do? Let's dig into it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dockerfile Commands and Keywords
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;FROM&lt;/code&gt; specifies the preexisting image on which to build our custom image. Since we are running a node application, we've chosen one of their official Docker images.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;FROM node:9.11.1 means our application image will start with the node v 9.11.1 image&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;ENV&lt;/code&gt; sets environment variables&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;ENV PORT=8080&lt;/code&gt; sets the environment variable &lt;code&gt;PORT&lt;/code&gt; for later use&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ENV NODE_ENV=development&lt;/code&gt; sets the environment variable &lt;code&gt;NODE_ENV&lt;/code&gt; for use within our app&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;WORKDIR&lt;/code&gt; sets the working directory within the container&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;WORKDIR /usr/src/app&lt;/code&gt; defines &lt;code&gt;/usr/src/app/&lt;/code&gt; as our working directory within the docker image&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;COPY&lt;/code&gt; copies new files, directories or remote files into the container/image&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;COPY package*.json /usr/src/app/&lt;/code&gt; copies our &lt;code&gt;package.json&lt;/code&gt; and &lt;code&gt;package-lock.json&lt;/code&gt; into our working directory&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;RUN&lt;/code&gt; executes a command in a new layer on top of the current image and commits it. When you run the build, you will see a hash representing each layer of our final image&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;RUN cd /usr/src/app/ &amp;amp;&amp;amp; CI=true npm install&lt;/code&gt; changes the working directory to where the &lt;code&gt;package.json&lt;/code&gt; is and installs all our dependencies to this folder within the image. This makes it so that the image holds frozen copies of the dependencies. Our Docker image, not our host machine, is responsible for our dependencies&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;EXPOSE&lt;/code&gt; allows us to access a port on the container from our host machine&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;EXPOSE 8080&lt;/code&gt; matches the port on which our app is running, inside the container and allows us to access our app from our host machine&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;code&gt;CMD&lt;/code&gt; provides the default initialization command to run when our container is created, like a startup script&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;CMD ["npm", "run", "serve"]&lt;/code&gt; sets this as our default command when we start our container. This is not run when building the image, it only defines what command should be run when the container starts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I know you're anxious to get this running, but hold your horses. Let's look &lt;em&gt;closer&lt;/em&gt; at our &lt;code&gt;Dockerfile.dev&lt;/code&gt; and understand &lt;em&gt;why&lt;/em&gt; we did what we did.&lt;/p&gt;

&lt;h3&gt;
  
  
  Dockerfile Structure Recommendations
&lt;/h3&gt;

&lt;p&gt;So, &lt;em&gt;Where's my app?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Right. We didn't use the &lt;code&gt;COPY&lt;/code&gt; command to copy our full workspace. Had we done so, we'd need to run &lt;code&gt;docker build&lt;/code&gt; and &lt;code&gt;docker run&lt;/code&gt; for every code change. We don't want to do this over and over for development. We can be more efficient&lt;/p&gt;

&lt;h4&gt;
  
  
  Caching Dependencies
&lt;/h4&gt;

&lt;p&gt;We are taking advantage of how Docker layers the images. As Docker builds our image, you'll see a hash for each layer as it is completed. What's more is that Docker also caches these layers. If Docker can see that nothing has changed on that layer from a previous build (and previous layers are also identical) then Docker will use a cached version of that layer, saving you and your developers precious time! When a layer changes, any cached layers on top of it are invalidated and will be rebuilt.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Therefore, if there is no change to our &lt;code&gt;package.json&lt;/code&gt; or the &lt;code&gt;package-lock.json&lt;/code&gt; then our entire image is cacheable and doesn't need to be rebuilt!&lt;/em&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Priority
&lt;/h4&gt;

&lt;p&gt;This is also why you want to have other &lt;code&gt;Dockerfile&lt;/code&gt; commands that change less frequently near the top of our file. As soon as one layer of our cache is invalidated, for example, if you change &lt;code&gt;ENV PORT=8080&lt;/code&gt; to another port, that cached layer and every cached layer after it is invalidated and Docker will have to rebuild those layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the Custom Docker Image
&lt;/h3&gt;

&lt;p&gt;Now, build the image with this command: &lt;code&gt;docker build --tag docker_demo:latest --file Dockerfile.dev .&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eT9q_bFl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/CNXqCg5.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eT9q_bFl--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/CNXqCg5.gif" alt="Docker Build from custom Dockerfile" title="Using Docker to Build a Custom Dockerfile"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Using &lt;code&gt;--tag&lt;/code&gt; in the &lt;code&gt;docker build&lt;/code&gt; command allows us to easily reference this image from our &lt;code&gt;docker run&lt;/code&gt; command&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;.&lt;/code&gt; at the end of the &lt;code&gt;docker build&lt;/code&gt; command references the context where our custom &lt;code&gt;Dockerfile&lt;/code&gt; can be found. So, this command should be run from the root of our project directory&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can run it with &lt;code&gt;docker run docker_demo:latest&lt;/code&gt;, but unfortunately, we have more work to do to get it working quickly and easily from the command line.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running our Container: Quality of Life Improvements
&lt;/h3&gt;

&lt;p&gt;We're going to be executing our &lt;code&gt;docker run&lt;/code&gt; command daily, if not more frequently. However, if we simply execute the &lt;code&gt;docker run docker_demo:latest&lt;/code&gt; command, Docker will create a &lt;em&gt;new&lt;/em&gt; container each time. Docker won't stop the old container unless you do so explicitly. This is very useful in many cases, but since we've hardcoded the host port, we'll run into port collisions on our host machine.&lt;/p&gt;

&lt;p&gt;In order for us to easily stop and remove our old containers, we should name them so we can easily refer to them later. Additionally, I want the running container to be removed if I cancel the running process.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm -it\
--name docker_demo_container\
docker_demo:latest

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gf7Yqd7J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/1oHnXTH.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gf7Yqd7J--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/1oHnXTH.gif" alt="Running the Docker Image we Built" title="Running a Docker container of a Custom Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  What was added?
&lt;/h4&gt;

&lt;p&gt;We added a &lt;code&gt;--name&lt;/code&gt; field to the end of our run command. This allows us to reference the container without looking up the hash. Now, we can easily stop our container by name.&lt;/p&gt;

&lt;p&gt;We also added the &lt;code&gt;--rm&lt;/code&gt; and &lt;code&gt;-it&lt;/code&gt; flags to our &lt;code&gt;docker run&lt;/code&gt; command. The &lt;code&gt;--rm&lt;/code&gt; flag tells Docker to remove the container if and when it is stopped. The &lt;code&gt;-it&lt;/code&gt; flag keeps the terminal live and interactive once the container is started.&lt;/p&gt;

&lt;h4&gt;
  
  
  Mounting Host Directories
&lt;/h4&gt;

&lt;p&gt;Let's go back to our &lt;code&gt;docker run&lt;/code&gt; command and let's find a way to mount our workspace directory to a folder within our container. We can do this by adding a mount point to our container in the &lt;code&gt;docker run&lt;/code&gt; command. This will tell Docker that we want to create an active link between our host machine's folder (&lt;code&gt;src&lt;/code&gt;) and the Docker container folder (&lt;code&gt;dst&lt;/code&gt;). Our new command should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm -it\
--name docker_demo_container\
--mount type=bind,src=`pwd`,dst=/usr/src/app\
docker_demo:latest

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;But this could conflict with our host machine's &lt;code&gt;node_modules&lt;/code&gt; folder since we're mounting our entire &lt;code&gt;pwd&lt;/code&gt; to our app's location in the image (in case one of our developers accidentally runs &lt;code&gt;npm install&lt;/code&gt; on their host machine). So, let's add a volume to ensure we preserve the &lt;code&gt;node_modules&lt;/code&gt; that exists within our container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm -it\
--name docker_demo_container\
--mount type=bind,src=`pwd`,dst=/usr/src/app\
--volume /usr/src/app/node_modules\
docker_demo:latest

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h4&gt;
  
  
  Accessing Ports Inside the Container
&lt;/h4&gt;

&lt;p&gt;If you tried the above command (and you're running a VueJS app), you should see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt; App running at:
  - Local:   http://localhost:8080/

  It seems you are running Vue CLI inside a container.
  Access the dev server via http://localhost:&amp;lt;your container's external mapped port&amp;gt;/

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Docker is giving you a hint that we need to expose a port from our container and publish it on our host machine. We do this by adding the &lt;code&gt;--publish&lt;/code&gt; flag to our run command. (We already have the &lt;code&gt;EXPOSE&lt;/code&gt; command in our &lt;code&gt;Dockerfile.dev&lt;/code&gt;)&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;--publish &amp;lt;host-port&amp;gt;:&amp;lt;container-port&amp;gt;&lt;/code&gt; tells Docker that traffic to the host machine (i.e. via localhost) on port &lt;code&gt;&amp;lt;host-port&amp;gt;&lt;/code&gt; should be directed towards the container at the &lt;code&gt;&amp;lt;container-port&amp;gt;&lt;/code&gt; that you define.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;docker run&lt;/code&gt; in One Command
&lt;/h3&gt;

&lt;p&gt;Let's take a look at our final run command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --rm -it\
--name docker_demo_container\
--publish 4200:8080\
--mount type=bind,src=`pwd`,dst=/usr/src/app\
--volume /usr/src/app/node_modules\
docker_demo:latest

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HkeDxQCg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/B4ROV1R.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HkeDxQCg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/B4ROV1R.gif" alt="Running the Docker Image we Built Success" title="Successfully Running a Docker container of a Custom Image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Running the above command will finally allow us to access our app via &lt;a href="http://localhost:4200/"&gt;http://localhost:4200&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing it out
&lt;/h3&gt;

&lt;p&gt;Let's build a fresh copy and run it. If you try changing one of our file's templates, you'll see everything is still functioning as it should be.&lt;/p&gt;

&lt;p&gt;But speaking of testing, what about unit tests? Well, once our container is running, we can open a new terminal and &lt;code&gt;docker exec&lt;/code&gt; a command to run in our container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker exec -it docker_demo_container npm run test:unit

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--p7zXf0vy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/2l7BDya.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--p7zXf0vy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://i.imgur.com/2l7BDya.gif" alt="Running Unit Tests through Docker" title="Running Unit Tests in Docker Container"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above command will create an interactive terminal connection with our container &lt;code&gt;docker_demo_container&lt;/code&gt; and execute the command &lt;code&gt;npm run test:unit&lt;/code&gt; in it, allowing us to run unit tests for our app.&lt;/p&gt;

&lt;h2&gt;
  
  
  In Closing
&lt;/h2&gt;

&lt;p&gt;We now have a way to build our development images and run them locally while maintaining the conveniences of Hot Module Replacement to keep our development workflow efficient. Our developers don't need to worry about dependencies on their host machine colliding with those in the image. No more "but it works on my machine" excuses. And, we also have a command we can easily run to execute our unit tests.&lt;/p&gt;

&lt;p&gt;If you find anything I missed or want to chat more about Docker, please reach out to me!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>javascript</category>
      <category>vue</category>
    </item>
    <item>
      <title>Connecting Stripe events to the AWS EventBridge</title>
      <dc:creator>Rangle.io </dc:creator>
      <pubDate>Wed, 20 Nov 2019 15:28:39 +0000</pubDate>
      <link>https://forem.com/rangle/connecting-stripe-events-to-the-aws-eventbridge-3o58</link>
      <guid>https://forem.com/rangle/connecting-stripe-events-to-the-aws-eventbridge-3o58</guid>
      <description>&lt;p&gt;&lt;a href="https://stripe.com"&gt;Stripe&lt;/a&gt; is a great platform for running an online business, especially on account of the developer-centric API that makes it easy to collect payments,  set up subscriptions and more.&lt;/p&gt;

&lt;p&gt;Many of these APIs result in Stripe generating one or more events that you can subscribe to via a webhook. These events could represent a successful payment, or perhaps a new subscriber to your SaaS platform. In total, there are well over 100 different types of events that you can subscribe to, so how can we build a loosely-coupled cloud-native event-driven architecture to handle these events? How can we make this serverless?&lt;/p&gt;

&lt;p&gt;It's easy, we'll use AWS EventBridge.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why AWS EventBridge?
&lt;/h3&gt;

&lt;p&gt;For those of you just learning about AWS EventBridge, it is a serverless event bus supporting event-driven architectures, released July 2019. An event bus is a central location where business events can be published and routing rules can be configured to send those events to downstream functions or services that operate on them. By using an event bus as an intermediate layer, this decouples services from needing direct knowledge of how to communicate with each other, which allows development teams to build and operate independently.&lt;/p&gt;

&lt;p&gt;One reason, among many, why AWS EventBridge should be considered is the cost. With AWS EventBridge, you have a fully managed cloud-native event bus, requiring no effort to set up and no servers to pay for - and it costs a very reasonable $1 per million events. Latency is typically about half a second. By going with a fully managed solution, you're saving your team from spending time on 'undifferentiated heavy lifting' associated with infrastructure, giving them more time to focus on delivering customer value.&lt;/p&gt;

&lt;h3&gt;
  
  
  The solution
&lt;/h3&gt;

&lt;p&gt;We'll show here how we can set up AWS EventBridge so that it can begin ingesting events from Stripe. As part of that ingestion, we'll check that the event is truly from Stripe by verifying the signature on the event. Let's get started. &lt;/p&gt;

&lt;p&gt;Using an an open-source project we created called &lt;a href="&amp;lt;https://github.com/rangle/stripe-eventbridge&amp;gt;"&gt;stripe-eventbridge&lt;/a&gt;,  you can quickly  set up the plumbing to connect Stripe events to AWS EventBridge via a Lambda function that will then validate the authenticity of incoming events (so that downstream functions won't have to). This allows for the events that are published on the event bridge to be routed to various downstream functions through simple routing rules which we show at the end of the post.&lt;/p&gt;

&lt;p&gt;With this deployed, you can set up many downstream Lambda functions to handle the wide array of events generated by Stripe and configure the routing to these event handlers with AWS EventBridge based on the Stripe event type. All of this without having to worry about event signatures, since events are only placed on the EventBridge if they pass validation.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/rangle/stripe-eventbridge"&gt;stripe-eventbridge&lt;/a&gt; project creates an endpoint that you configure in the Stripe Dashboard as the destination for the webhook events. When an event arrives, the endpoint will invoke a Lambda that we provide which has these responsibilities:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;to validate that the event has a valid signature (i.e. that it was generated by Stripe)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;to place validated events (only) on the AWS EventBridge&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;to notify an SNS topic if an event fails to validate (e.g. due to an invalid signature)&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Solution overview&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rangle/stripe-eventbridge"&gt;stripe-eventbridge&lt;/a&gt; uses the&lt;a href="https://serverless.com/"&gt;  Serverless Framework&lt;/a&gt; to generate the infrastructure in the AWS section of the diagram above. The&lt;a href="https://serverless.com/"&gt;  Serverless Framework&lt;/a&gt; allows us to automatically create and deploy the CloudFormation stacks needed to realize the above configuration. The stacks can be deployed via sls deploy and rolled back via sls remove using the command line client.&lt;/p&gt;

&lt;h3&gt;
  
  
  Serverless components in stripe-eventbridge
&lt;/h3&gt;

&lt;p&gt;Let's walk through what &lt;a href="https://github.com/rangle/stripe-eventbridge"&gt;stripe-eventbridge&lt;/a&gt; creates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;A Lambda - this function validates incoming events, and if they are from Stripe (i.e. signed correctly) then they are relayed to the AWS EventBridge where downstream services can read from them.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An API Gateway endpoint - this is the webhook endpoint that the Lambda above is listening to for new events.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An AWS SecretManager secret - this secret is created with an empty value, and you populate this with the signing key assigned to your webhook endpoint in the Stripe Dashboard&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;An SNS topic - if the webhook fails validation or processing, then a notification is sent to a topic called stripe-webhook-event-failed-to-validate. You can configure subscriptions to this topic, so that you are emailed (for example) whenever an event fails processing.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you'd like to get started, you can visit the GitHub project here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/rangle/stripe-eventbridge"&gt;https://github.com/rangle/stripe-eventbridge&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Routing by event type
&lt;/h3&gt;

&lt;p&gt;Now that you have events being published to the EventBridge, you can configure routing based on the event type using Rule patterns like this. The detail-type values are exactly the values of the underlying Stripe events - you can see a full list here:&lt;a href="https://stripe.com/docs/api/events/types"&gt;  https://stripe.com/docs/api/events/types&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{

  "detail-type": [

    "payment_intent.succeeded"

  ],

  "source": [

    "Stripe"

  ]

}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Alternately, if you are creating your event handlers using the Serverless Framework, then you can declare the same routing in your infrastructure code (this is really good practice) in your serverless.yml as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
    handler: handler.myLambdaFunction

    events:

      - eventBridge:

          pattern:

            source:

              - Stripe

            detail-type:

              - payment_intent.succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  And that's all!
&lt;/h3&gt;

&lt;p&gt;I hope you have found this valuable. Stay tuned, we'll be exploring more with Serverless in upcoming posts.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>eventbridge</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Running Jenkins and Persisting state locally using Docker</title>
      <dc:creator>Rangle.io </dc:creator>
      <pubDate>Fri, 15 Nov 2019 20:42:15 +0000</pubDate>
      <link>https://forem.com/rangle/running-jenkins-and-persisting-state-locally-using-docker-49d7</link>
      <guid>https://forem.com/rangle/running-jenkins-and-persisting-state-locally-using-docker-49d7</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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2Fjenkins_16_9.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2Fjenkins_16_9.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Jenkins is one of the most popular Continuous Integration and Delivery Servers today, so it's only natural that you're probably interested in learning more about it. When starting out, you'll need to first run it on your local machine. However, the problem with that is the Jenkins configuration files will then live directly on your machine. A better solution is to run it as a Docker container, here are some of the reasons why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  All of your Jenkins &lt;strong&gt;configuration files&lt;/strong&gt; live inside the container rather than the host machine. Knowing that all the files you need are inside the container, you can eliminate the issue of accidentally mixing your files with Jenkins configuration files.&lt;/li&gt;
&lt;li&gt;  Docker instances are easier to manage if you are interested in running Jenkins on &lt;em&gt;multiple platforms&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;  You can easily create and destroy the Jenkins server and remove all the Jenkins data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another benefit of using containers is persisting the state of your Jenkins server using Docker volumes. Why do this?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  You get to keep all your projects and configurations even after restarting your computer (local machine)&lt;/li&gt;
&lt;li&gt;  You don't need to run the whole Jenkins setup again&lt;/li&gt;
&lt;li&gt;  You can remove your container instance and still able to recover the state of your Jenkins server&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With that in mind, I'll show you how you can start configuring Jenkins and persisting state on your local machine. Let's get started!&lt;/p&gt;

&lt;h1&gt;
  
  
  Jenkins setup
&lt;/h1&gt;

&lt;p&gt;Before we get started, you'll need to install Docker on your machine. If you're not sure how you can refer to this &lt;a href="https://docs.docker.com/install/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After installing Docker, download the latest stable Jenkins image by running:&lt;/p&gt;

&lt;p&gt;You should 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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.10.10-PM.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.10.10-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Persisting Jenkins Data
&lt;/h2&gt;

&lt;p&gt;You can create a volume by running the command below:&lt;br&gt;
&lt;code&gt;docker volume create [YOUR VOLUME]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Volumes are used to make sure that you don't lose your Jenkins data. If you are using the &lt;code&gt;-v&lt;/code&gt; flag on container creation (&lt;code&gt;docker container run&lt;/code&gt;), feel free to skip this step since Docker will automatically create the volume for you.&lt;/p&gt;

&lt;p&gt;Run the container by attaching the volume and assigning the targeted port. In this example, we'll also run it in detached mode. Here is the command to run your Docker container:&lt;br&gt;
&lt;code&gt;docker container run -d \ -p [YOUR PORT]:8080 \ -v [YOUR VOLUME]:/var/jenkins_home \ --name jenkins-local \ jenkins/jenkins:lts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;If you were wondering what the arguments stand for, here is what each means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  -d: detached mode&lt;/li&gt;
&lt;li&gt;  -v: attach volume&lt;/li&gt;
&lt;li&gt;  -p: assign port target&lt;/li&gt;
&lt;li&gt;  ---name: name of the container&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And now, we're ready to take a look at an example of how you could run this command:&lt;br&gt;
&lt;code&gt;docker container run -d -p 8082:8080 \ -v jenkinsvol1:/var/jenkins_home \ --name jenkins-local \ jenkins/jenkins:lts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After running the command, you should be able to see the code to be used for the next step on your setup.&lt;/p&gt;

&lt;p&gt;In the command we ran, &lt;code&gt;/var/jenkins_home&lt;/code&gt; is the path to where the Jenkins state is stored on our container instance. The most important argument we pass when it comes to data persistence in this example is the &lt;code&gt;-v **[YOUR VOLUME]**:/var/jenkins_home&lt;/code&gt;. This argument is what helps Docker link the volume to the file inside the container. To learn more about Docker volumes, you can check out the &lt;a href="https://docs.docker.com/storage/volumes/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;. If you're not familiar with Docker, you can start with this helpful docker blog series, &lt;a href="https://rangle.io/blog/learning-docker-command-line-interface/" rel="noopener noreferrer"&gt;Learning Docker - The Command Line Interface&lt;/a&gt;. You'll notice that I am using port &lt;code&gt;8082&lt;/code&gt; instead of the default &lt;code&gt;8080&lt;/code&gt;. The reason, other than demonstrating that you can use other ports, is that port &lt;code&gt;8080&lt;/code&gt; is used by some web frameworks.&lt;/p&gt;

&lt;p&gt;If you run &lt;code&gt;docker ps&lt;/code&gt;, you should see your docker container running&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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.15.00-PM.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.15.00-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After confirming that your container is running, go to &lt;code&gt;localhost:[YOUR PORT]&lt;/code&gt; (&lt;code&gt;localhost:8082&lt;/code&gt; on my example) on your browser and you should see this page:&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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.15.58-PM.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.15.58-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a part of the Jenkins setup, we need to view the password inside the container instance. In order to do this, we need to use the &lt;code&gt;CONTAINER ID&lt;/code&gt; (or the name) and run &lt;code&gt;docker exec&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Here is the full command:&lt;br&gt;
&lt;code&gt;docker container exec \ [CONTAINER ID or NAME] \ sh -c "cat /var/jenkins_home/secrets/initialAdminPassword"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After running the command, you should see the code. Copy the code and paste it on the webpage to unlock Jenkins. After unlocking, click on &lt;strong&gt;Install suggested plugins&lt;/strong&gt; on the &lt;strong&gt;Customize Jenkins&lt;/strong&gt; page.&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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.16.38-PM.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.16.38-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Wait until the installation is complete and then you can proceed in creating your first admin user.&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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.17.14-PM.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.17.14-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After creating the admin user, setup the Instance configuration. Since you are only using Jenkins locally, leave the URL to your &lt;code&gt;localhost&lt;/code&gt; URL. Click on &lt;strong&gt;Save and Finish&lt;/strong&gt; to start using Jenkins.&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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.17.49-PM.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.17.49-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Confirming Jenkins state is persisted
&lt;/h2&gt;

&lt;p&gt;Once you get to the Jenkins home page, create a new job.&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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.18.27-PM.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.18.27-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Name the job &lt;strong&gt;Test&lt;/strong&gt; and set it to be a &lt;strong&gt;Freestyle project&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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.18.55-PM.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.18.55-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Leave everything as default and add a new &lt;strong&gt;Shell Execution&lt;/strong&gt; under &lt;strong&gt;Build.&lt;/strong&gt; Add this as the command:&lt;br&gt;
&lt;code&gt;echo "Working"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Save the job and click on &lt;strong&gt;Build Now&lt;/strong&gt; to start running the job.&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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.19.45-PM.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.19.45-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Click on the &lt;strong&gt;Build Status (blue ball)&lt;/strong&gt; under &lt;strong&gt;Build History (left sidebar)&lt;/strong&gt; to view the console output. You should see that our command ran with no problems.&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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.20.26-PM.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.20.26-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Recovering Jenkins
&lt;/h2&gt;

&lt;p&gt;After confirming that the job runs, we want to make sure that we can recover our &lt;strong&gt;Jenkins&lt;/strong&gt; configuration if needed. In Jenkins, all of the configuration is stored in &lt;code&gt;/var/jenkins_home/&lt;/code&gt; by default. Remember that we are using docker volume to store information about our &lt;strong&gt;Jenkins&lt;/strong&gt; instance.&lt;/p&gt;

&lt;p&gt;In order to check if the persistence works correctly, let's destroy our current docker container and see if we can log in as an admin and view our job build history.&lt;/p&gt;

&lt;p&gt;First, run &lt;code&gt;docker container kill [CONTAINER ID]&lt;/code&gt; to stop the instance. After doing so, run &lt;code&gt;docker container rm [CONTAINER ID]&lt;/code&gt; to completely remove the container instance.&lt;/p&gt;

&lt;p&gt;Visit &lt;code&gt;localhost:[YOUR PORT]&lt;/code&gt; (&lt;code&gt;localhost:8082&lt;/code&gt; on my example) to confirm that the Jenkins instance is not running anymore. You should 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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.20.57-PM.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.20.57-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Run the same command we used to create the container instance in order to recover the Jenkins instance.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;docker container run -d -p 8082:8080 \ -v jenkinsvol1:/var/jenkins_home \ --name jenkinslocal \ jenkins/jenkins:lts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You should get a new &lt;code&gt;CONTAINER ID&lt;/code&gt; after running the command. Visit  &lt;code&gt;localhost:[YOUR PORT]&lt;/code&gt; (&lt;code&gt;localhost:8082&lt;/code&gt; on my example). You should see the login page. Login with the admin credentials you set during Jenkins initialization.&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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.21.33-PM.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.21.33-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After logging in, you should see the &lt;strong&gt;job&lt;/strong&gt; you created and view the console output.&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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.22.13-PM.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%2Frangleio.ghost.io%2Fcontent%2Fimages%2F2019%2F11%2FScreen-Shot-2019-11-14-at-1.22.13-PM.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  In summary
&lt;/h2&gt;

&lt;p&gt;I hope you can now see why Docker is the best way to start learning or at least playing around with Jenkins. You can easily run a Jenkins instance as a Docker container and persist your Jenkins server state using Docker Volumes. In case you need to restart or recover your Jenkins instance, all of the state is stored inside the Docker Volume. If you want to read more about Jenkins, Docker and DevOps, check out our other blogs, &lt;a href="https://rangle.io/blog/tag/devops/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>ci</category>
      <category>webdev</category>
    </item>
    <item>
      <title>CD with Docker and Feature Branch Testing
</title>
      <dc:creator>Rangle.io </dc:creator>
      <pubDate>Fri, 25 Oct 2019 17:28:06 +0000</pubDate>
      <link>https://forem.com/rangle/cd-with-docker-and-feature-branch-testing-110h</link>
      <guid>https://forem.com/rangle/cd-with-docker-and-feature-branch-testing-110h</guid>
      <description>&lt;p&gt;&lt;a href="https://medium.com/@martindevnow" rel="noopener noreferrer"&gt;By: Ben Martin&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you've been following along with my Docker series (you can find &lt;a href="https://rangle.io/blog/docker-full-circle-continuous-integration-ci-with-cypress" rel="noopener noreferrer"&gt;my latest article about Continuous Integration (CI) here&lt;/a&gt;) then you must be pretty happy to have your CI pipeline solving &lt;strong&gt;all&lt;/strong&gt; the world's problems. Your developers are pretty content, but we know there's more we could do. And, I mean, isn't developer happiness the &lt;em&gt;real&lt;/em&gt; reason you're reading a DevOps article?&lt;/p&gt;

&lt;p&gt;In this article, I'll outline how you can take the CI pipeline one step further to address the Continuous Deployment (CD) aspect of CICD. More specifically, we'll address how one would configure &lt;strong&gt;feature branch specific&lt;/strong&gt; deployments of our app in order to quickly and easily manually test their features, even on mobile devices, before merging their feature branch PR to the develop branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisite Knowledge
&lt;/h2&gt;

&lt;p&gt;If you haven't been following along with &lt;a href="https://rangle.io/blog/author/ben-martin" rel="noopener noreferrer"&gt;my previous articles&lt;/a&gt;, to get the most out of this article, you should first have a Dockerized application. If you also have a CircleCI pipeline configured, that's a huge head start! We will be building off that. In our hypothetical situation, we're using an AWS EC2 instance from the free tier in AWS. If you're new to AWS, this could easily be replaced by other technologies. One would only need a server to deploy to. In the past, I used a $5 Digital Ocean droplet to accomplish the same effect, but it's up to you to determine where you want to deploy.&lt;/p&gt;

&lt;p&gt;Here's what you'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An AWS Account with an EC2 instance configured to expose ports 22, 80 and 443 and an SSH key for CircleCI to use&lt;/li&gt;
&lt;li&gt;Source code of Dockerized App hosted on GitHub&lt;/li&gt;
&lt;li&gt;Docker Hub (or some other Docker image repository you can publish to)&lt;/li&gt;
&lt;li&gt;CircleCI connected to your app's GitHub repo and your Docker Hub repo&lt;/li&gt;
&lt;li&gt;Domain name pointing to your server&lt;/li&gt;
&lt;li&gt;Wildcard TLS Certificate for the above domain name&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Details for most of the above, aside from anything deployment related, can be found in &lt;a href="https://rangle.io/blog/docker-full-circle-continuous-integration-ci-with-cypress" rel="noopener noreferrer"&gt;my previous article.&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  The Goal: Fast Feedback
&lt;/h2&gt;

&lt;p&gt;As a huge proponent of Agile development methodologies, fast feedback is critical for success, and the higher fidelity the feedback, the better! Unit tests and end-to-end tests all have their place. But, having human eyes review UI changes running in a production-like environment in the browser helps us identify bugs before they become an issue that could impact other teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why should I bother?
&lt;/h3&gt;

&lt;p&gt;In my case, I was working on a project recently where I was developing an Angular application to be consumed through a mobile device. The app required use of the mobile device's camera and accelerometer for the features I was developing. Thus, I wanted to be able to quickly test these features with my actual phone while I was still working out the implementation details.&lt;/p&gt;

&lt;p&gt;Sounds simple enough, I just needed to deploy my code somewhere I could access from my device. But this process needed to be automated.&lt;/p&gt;

&lt;p&gt;I decided to leverage my existing CI pipeline and extend it to do Continuous Deployments (CD). My CI pipeline was already configured to run my unit tests and end-to-end tests, but I wanted to also deploy my code to a server that I could access from my phone for manual testing.&lt;/p&gt;

&lt;p&gt;Here are some key considerations for extending this CI/CD pipeline. &lt;/p&gt;

&lt;h2&gt;
  
  
  Feature Branch Environments
&lt;/h2&gt;

&lt;p&gt;If you've worked on an enterprise webapp, you may be familiar with terms like &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;int(egration)&lt;/code&gt; and &lt;code&gt;staging&lt;/code&gt;. Typically, these are environments where different states of our application reside. Each of these environments are meant to host various states of your app, whether that be the branch actively under development, your next release or the last release that you're still supporting with bug fixes.&lt;/p&gt;

&lt;p&gt;What often gets lost in the mix is our &lt;code&gt;feature&lt;/code&gt; branches. When our developers pick up a ticket, they may want to actively test their code on a suite of devices to ensure cross device and cross browser compatibility. Plus, having this requirement for our developers acts as an additional safeguard for preventing bugs from getting into the &lt;code&gt;develop&lt;/code&gt; branch of our code.&lt;/p&gt;

&lt;p&gt;If you have ever asked your boss for &lt;em&gt;branch specific environments&lt;/em&gt;, you may well have been scoffed at claiming &lt;em&gt;"there's no room in the budget"&lt;/em&gt;. Well, what if I told you that through the power of Docker and the free tier on AWS (or an existing server you may have running), you can have branch-specific environments beyond &lt;code&gt;dev&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt; and &lt;code&gt;staging&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker To The Rescue!
&lt;/h2&gt;

&lt;p&gt;Docker is the perfect tool for solving this issue for several reasons. In order to see why, consider what would be difficult about running multiple copies of our app on the same environment. Well, even if we imagine a static site there's a lot to cover off. When we deploy our app, what folder do we deploy it to? How do we handle port collisions? Asset loading with relative URLs? How do we notify nginx of the new route/site? There's a lot of configuration and mess that goes into doing it directly on the host machine that we can delegate to Docker to handle for us.&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%2Fi.imgur.com%2FtUPdXRo.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%2Fi.imgur.com%2FtUPdXRo.png" alt="Docker Setup on AWS with Nginx"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the end, we'll have a long lived reverse nginx proxy running in a container on our host machine. This container will listen to Docker for other containers we run. Using environment variables in the &lt;code&gt;docker run&lt;/code&gt; command, we will be able to tell this nginx proxy to update the configuration to point dynamic subdomains to our feature branch specific containers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Docker with nginx
&lt;/h3&gt;

&lt;p&gt;Most of the heavy lifting is done by the nginx proxy container. I found &lt;a href="https://github.com/jwilder/nginx-proxy" rel="noopener noreferrer"&gt;an excellent dockerized nginx proxy on GitHub&lt;/a&gt; to aid in this process. What is useful about this Docker image is that once you have it running, it will listen to your other &lt;code&gt;docker&lt;/code&gt; commands that are run on the host machine, in particular your &lt;code&gt;docker run&lt;/code&gt; command. In particular, it will look for environment variables attached to your &lt;code&gt;docker run&lt;/code&gt; command to interpret how to update the internal configuration and point it to your app container that is being started. &lt;/p&gt;

&lt;p&gt;This reverse proxy image should be running in a container on your server. This container's role is to listen to other Docker commands that you run and automatically update the nginx configuration within this reverse proxy container.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passing Inputs to your Docker Run
&lt;/h2&gt;

&lt;p&gt;Once you have the nginx proxy running in a Docker container, you can leverage your CI pipeline (like CircleCI) to get the environment variables needed to pass to your server in the &lt;code&gt;docker run&lt;/code&gt; command. Just make sure that CircleCI is authorized to access your server via SSH. A secure way to do this is using SSH keys. Generate a key and &lt;a href="https://circleci.com/docs/2.0/add-ssh-key/" rel="noopener noreferrer"&gt;provide the private key to CircleCI&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then, add the public key to the &lt;code&gt;~/.ssh/authorized_keys&lt;/code&gt; of your server. From there, make a bash script to manage your branch-specific containers. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://circleci.com/docs/2.0/env-vars/" rel="noopener noreferrer"&gt;CircleCI exposes a number of environment variables&lt;/a&gt; to your pipeline that you can use in your jobs to pass to your bash script.&lt;/p&gt;

&lt;p&gt;In my case, I used CircleCI to run &lt;code&gt;scp&lt;/code&gt; to copy a deployment script to the testing server. Once the bash file is there, it would be executed with the arguments to tell it what sub-domain to use for this container. I used a sanitized version of the branch name. For example, &lt;code&gt;feature/ABC-42-my-feature&lt;/code&gt; becomes &lt;code&gt;feature_abc-42-my-feature.myexampledomain.com&lt;/code&gt; That subdomain would also be the alias for the container, allowing my script to stop a running container with outdated code when new commits are made to that particular branch.&lt;/p&gt;

&lt;p&gt;Here's an example of the run command from my deployment script that provides the environment variables (&lt;code&gt;VIRTUAL_HOST&lt;/code&gt;, &lt;code&gt;VIRTUAL_PROTO&lt;/code&gt; and &lt;code&gt;VIRTUAL_PORT&lt;/code&gt;) expected by the reverse nginx proxy container. The nginx container is listening to the Docker process on your host machine. When it sees a &lt;code&gt;docker run&lt;/code&gt; command, it is also looking for those three environment variables. If it sees them in the command, it will update the nginx configuration to point the virtual host to the container that is being run. This is the command that will be run on the host machine to deploy. These environment variables are defined in the CI pipeline.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run --expose 443 -e VIRTUAL_HOST=${URL_SUBDOMAIN}.myexampledomain.com -e VIRTUAL_PROTO=https -e VIRTUAL_PORT=443 -d --rm=true --name ${CONTAINER_NAME} ${DOCKER_IMAGE}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The environment variables I am using here are set inside my bash script to ensure I pull the correct image, apply the right name to the container and assign the URL, port and protocol. Putting it together, we can add a "job" to our CircleCI configuration aliased as &lt;code&gt;deploy&lt;/code&gt;. This deploy job would look something like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;scp deploy-${IMAGE_NAME}.sh ${PROD_SERVER_USER}@${PROD_SERVER_HOST}:/root/
ssh -o StrictHostKeyChecking=no ${PROD_SERVER_USER}@${PROD_SERVER_HOST} "/bin/bash /root/deploy-${IMAGE_NAME}.sh $IMAGE_NAME:$TAG ${URL_SUBDOMAIN}"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: &lt;code&gt;PROD_SERVER_USER&lt;/code&gt; and &lt;code&gt;PROD_SERVER_HOST&lt;/code&gt; are set in the &lt;code&gt;.circleci/config.yml&lt;/code&gt; file&lt;/p&gt;

&lt;p&gt;Note: &lt;code&gt;$IMAGE_NAME:$TAG&lt;/code&gt; and  &lt;code&gt;${URL_SUBDOMAIN}&lt;/code&gt; are passed as arguments to the deploy script and are used in our &lt;code&gt;docker run&lt;/code&gt; command above.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the bash file, it is important to make sure there isn't already a container running with the same name. It should first be stopped and removed. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: In my case, because I was using HTTPS in order to gain access to the mobile device's camera, I needed to setup TLS with a wildcard domain so that I could add subdomains on the fly and still have TLS support.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Results
&lt;/h2&gt;

&lt;p&gt;Now, anytime this repository receives updates to one of the feature branches, that code (assuming it passes all the steps defined in our CICD pipeline prior to deployment) will be deployed to our testing server, on a custom subdomain.&lt;/p&gt;

&lt;p&gt;In my project, I took the branch name, sanitized it by removing any special characters, and used that as my subdomain. So, when I push commits to my branch called &lt;code&gt;feature/mobile-view&lt;/code&gt;, I could see my changes by visiting this subdomain: &lt;a href="https://feature_mobile-view.myexampledomain.com" rel="noopener noreferrer"&gt;https://feature_mobile-view.myexampledomain.com&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;The value here being that in order for your developers to see code they're working on in a production-like environment, they only need to push their feature branch to the remote repository. Even if their code is incomplete, they can quickly prototype and test features that would be otherwise difficult to do so in a local environment, like mobile device features, etc. &lt;/p&gt;

&lt;h2&gt;
  
  
  Further Improvements
&lt;/h2&gt;

&lt;p&gt;We got what we wanted, but that doesn't mean it's perfect. There are many ways we could continue to polish this solution. Let's look at a few.&lt;/p&gt;

&lt;h3&gt;
  
  
  HTTPS
&lt;/h3&gt;

&lt;p&gt;Although we didn't dig into it here, it is convenient to add a wildcard TLS certificate to the server you are running. You can also look at &lt;a href="https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion" rel="noopener noreferrer"&gt;https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion&lt;/a&gt; to see how people have combined a separate container to automatically generate the certificates for the Docker containers being spun up. Similar to the image we used for the proxy, this one would also listen to your &lt;code&gt;docker run&lt;/code&gt; commands for environment variables to automate this process.&lt;/p&gt;

&lt;p&gt;In the project that inspired this setup, I needed HTTPS support to access the device's camera and accelerometer, so, given that this was a fun little side project, manually uploading a single wildcard certificate was sufficient for me.&lt;/p&gt;

&lt;p&gt;Another alternative is to put this solution behind an application load balancer (ALB) through AWS. Do pay attention to which services are compatible with the free tier of new AWS accounts. Otherwise be warned that there will be costs involved in fleshing out the solution further.&lt;/p&gt;

&lt;h3&gt;
  
  
  nginx Restarting
&lt;/h3&gt;

&lt;p&gt;In case the nginx proxy container ever crashed, you'd want to define what your restart policy is. A simple addition, is to add &lt;code&gt;--restart unless-stopped&lt;/code&gt; to the &lt;code&gt;docker run&lt;/code&gt; command for your nginx reverse proxy. But you also need to think about if the server restarts. There are many tools that one could use to manage starting containers on boot. Even just systemd to turn it into a service would meet these requirements. &lt;/p&gt;

&lt;h3&gt;
  
  
  Deployment Script
&lt;/h3&gt;

&lt;p&gt;This was something that resided in the code repository so that CircleCI would have access to it when it pulled the code from the repo. Alternatively, this could also reside on the deployment server instead. There will be pros and cons regardless. Discuss with your team which approach works best for you.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS EC2 Configuration
&lt;/h3&gt;

&lt;p&gt;There is a lot that could be said here from security to resource management and configuration automation. Some things you want to remember is always start with the fewest permissions and add more as needed. If you're using EC2, leverage the user script for your AWS instance to ensure your server is fully configured and has all the services running to ensure the nginx-proxy stays online. Write cron scripts to automatically remove containers that have been online for longer than "X" days. If there is a new commit to a particular branch, that container would be refreshed. Old containers would likely represent feature branches that have been merged. &lt;/p&gt;

&lt;p&gt;Speaking of which...&lt;/p&gt;

&lt;h3&gt;
  
  
  GitHub Webhooks
&lt;/h3&gt;

&lt;p&gt;Configuring webhooks to ping your server when a branch gets merged or deleted would be another way to ensure you don't have too many inactive containers on your server.&lt;/p&gt;

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

&lt;p&gt;Hopefully this gives you an idea of what needs to be considered when updating your CICD pipeline to support feature branch specific environments and how easy it can be. Just remember the goal: fast feedback. &lt;/p&gt;

&lt;p&gt;I am confident that if you implement a solution similar to that described above, your developers will let you know how much they love it, ranting and raving about how great it is. Just be careful. When they eventually move to a new project, they might just realize how much you've spoiled them ;)&lt;/p&gt;

</description>
      <category>devops</category>
      <category>docker</category>
      <category>aws</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
