<?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>DEV Community: Rafael Nunes</title>
    <description>The latest articles on DEV Community by Rafael Nunes (@peaonunes).</description>
    <link>https://dev.to/peaonunes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F160426%2F4f840e90-65e6-482b-9538-e9e834cd2577.jpeg</url>
      <title>DEV Community: Rafael Nunes</title>
      <link>https://dev.to/peaonunes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/peaonunes"/>
    <language>en</language>
    <item>
      <title>Improving Time To First Byte and Web Vitals</title>
      <dc:creator>Rafael Nunes</dc:creator>
      <pubDate>Tue, 07 Sep 2021 00:47:11 +0000</pubDate>
      <link>https://dev.to/peaonunes/improving-time-to-first-byte-and-web-vitals-44hc</link>
      <guid>https://dev.to/peaonunes/improving-time-to-first-byte-and-web-vitals-44hc</guid>
      <description>&lt;p&gt;In this post we will cover quite a few different concepts I recently explored that influence the page speed, how they relate to Core Web Vitals and how to improve them!&lt;/p&gt;

&lt;p&gt;Let's start by agreeing on some terminologies and concepts that will be often referred on this post!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Time To First Byte (TTFB)&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TTFB measures the duration from the user or client making an HTTP request to the first byte of the page being received by the client's browser.&lt;br&gt;
&lt;a href="https://en.wikipedia.org/wiki/Time_to_first_byte" rel="noopener noreferrer"&gt;https://en.wikipedia.org/wiki/Time_to_first_byte&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This measure is used to indicate the responsiveness of the resource, our websites, our servers and so forth. This is often displayed in milliseconds (ms) in the tools, and the &lt;a href="https://dictionary.cambridge.org/dictionary/english/rule-of-thumb" rel="noopener noreferrer"&gt;rule of thumb&lt;/a&gt; recommended by &lt;a href="https://developers.google.com/speed/docs/insights/Server#overview" rel="noopener noreferrer"&gt;several players in the industry&lt;/a&gt; is  &lt;code&gt;200ms&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;This concept alone is important enough to look for improvements that will impact our customer's experience. However, it becomes better when we correlate it with another customer-focused metric, the Largest Contentful Paint.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Web Vitals&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://web.dev/vitals/" rel="noopener noreferrer"&gt;Core Web Vitals (CWV)&lt;/a&gt; initiated is meant to help us quantify the experience of our sites and find improvements that will result in a better customer experience. Besides providing metrics to look after and improve, these factors are now considered a &lt;a href="https://developers.google.com/search/blog/2020/11/timing-for-page-experience" rel="noopener noreferrer"&gt;ranking signal for the Google Search algorithm&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From the CWV metrics, we will be focusing on Largest Contentful Paint (LCP). If you are interested in knowing more about these metrics, check the &lt;a href="https://web.dev/vitals/" rel="noopener noreferrer"&gt;Web Vitals&lt;/a&gt; page.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;LCP metric reports the render time of the largest image or text block visible within the viewport relative to when the page started loading.&lt;br&gt;
&lt;a href="https://web.dev/lcp/" rel="noopener noreferrer"&gt;https://web.dev/lcp/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;The time it takes to render our website's largest image or text block depends on how fast we deliver our pages and how fast they download any additional assets that make it.&lt;/p&gt;

&lt;p&gt;So knowing that TTFB measures the responsiveness of our websites, then the LCP is probably the most important metric we can influence from those of CWV. And that is why we are going to focus on improving TTFB in this post.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5y5ki7242xbfiawgxsck.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5y5ki7242xbfiawgxsck.png" alt="spotify page has text as its LCP"&gt;&lt;/a&gt; &lt;em&gt;The element associated with LCP on &lt;a href="http://spotify.com" rel="noopener noreferrer"&gt;spotify.com&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Now we know what these concepts are and how to interpret them, let's see how to measure them!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Measuring where the time is spent&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before jumping on ways to improve metrics, we need to understand the current state of our applications and where the bottlenecks are.&lt;/p&gt;

&lt;p&gt;Knowing how to measure changes is the most important step to get confidence out of our initiatives.&lt;/p&gt;

&lt;p&gt;It is possible to track TTFB on;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Devtools, &lt;a href="https://developer.chrome.com/docs/devtools/network/reference/#timing-preview" rel="noopener noreferrer"&gt;on previewing time breakdown&lt;/a&gt; that highlights the value for every resource requested by the browser, including the website itself. That is present in every modern browser.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://curl.se/" rel="noopener noreferrer"&gt;cURL&lt;/a&gt;, on your terminal, can tell you the TTFB of any request. &lt;a href="https://www.notion.so/1f5fbdbdd89551ba7925abe2645f92b5" rel="noopener noreferrer"&gt;There are plenty of gists on how to do it&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Using other tools/sites like Bytecheck or KeyCDN.&lt;/li&gt;
&lt;li&gt;Application Performance Monitoring (APMs) can also help us track this from within our clients (CSR) and servers (SSR).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are also a few ways you can track LCP;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developers.google.com/web/tools/lighthouse/" rel="noopener noreferrer"&gt;Lighthouse&lt;/a&gt; is available on Chrome or as a standalone app on &lt;a href="http://wed.dev" rel="noopener noreferrer"&gt;wed.dev&lt;/a&gt; and generates a report about Performance that tells you the LCP of the page inspected.&lt;/li&gt;
&lt;li&gt;Other websites like &lt;a href="https://webpagetest.org" rel="noopener noreferrer"&gt;WebPageTest&lt;/a&gt; will review your website and provide useful and detailed reports on areas of improvement.&lt;/li&gt;
&lt;li&gt;Some tools, like &lt;a href="https://calibreapp.com/" rel="noopener noreferrer"&gt;Calibre&lt;/a&gt;, help us automate and track progress over time.&lt;/li&gt;
&lt;li&gt;Application Performance Monitoring (APMs) can also help us track this from our clients and servers #2!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The problem can be anywhere in between our routing infrastructure to the application code! Thankfully these tools help us understand better where the issues lay.&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%2Fmedia.giphy.com%2Fmedia%2F3hQ0hZDo4QhR6%2Fgiphy.gif%3Fcid%3Decf05e47buhro8mqx0wqxg9kv2l8kup48twql9eorz3l9gl3%26rid%3Dgiphy.gif%26ct%3Dg" 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%2Fmedia.giphy.com%2Fmedia%2F3hQ0hZDo4QhR6%2Fgiphy.gif%3Fcid%3Decf05e47buhro8mqx0wqxg9kv2l8kup48twql9eorz3l9gl3%26rid%3Dgiphy.gif%26ct%3Dg" alt="https://media.giphy.com/media/3hQ0hZDo4QhR6/giphy.gif?cid=ecf05e47buhro8mqx0wqxg9kv2l8kup48twql9eorz3l9gl3&amp;amp;rid=giphy.gif&amp;amp;ct=g"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My advice here is to start small and start early. Pick the tool we are currently more familiar with, or the one we find easier to start and then move on until we reached its limits!&lt;/p&gt;

&lt;p&gt;Let's talk improvements now!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improving TTFB for websites&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/Content_delivery_network" rel="noopener noreferrer"&gt;CDNs&lt;/a&gt; are an excellent way to speed up the responsiveness of your pages, assets, etc. That is especially true when serving assets that do not change so often or rarely change. We should aim to have CDN caches on top of our fonts, images, data payloads, and entire pages (when possible).&lt;/p&gt;

&lt;p&gt;This directly impacts several customer experience factors, more evident on LCP, as the customer will be downloading our pages much faster than if they had to reach the server.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frl1e4r6pmxklggnhkh84.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frl1e4r6pmxklggnhkh84.png" alt="earth photo by nasa"&gt;&lt;/a&gt; &lt;em&gt;Photo by NASA on Unsplash&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Next is the data source closer to the server and the server closer to the customer!&lt;/p&gt;

&lt;p&gt;Caching strategies are ineffective when the requests are unique or too distributed to a point CDNs will not get many hits. This scenario increases the importance of;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Having our server as close to the customer as possible, distributing our sites globally when possible.&lt;/li&gt;
&lt;li&gt;Having our data stores as close as possible to the servers. If our pages fetch data from databases or APIs to render (&lt;a href="https://developers.google.com/web/updates/2019/02/rendering-on-the-web" rel="noopener noreferrer"&gt;CSR or SSR&lt;/a&gt;), then let's ensure these resources are in the same region as our servers. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Both of these strategies avoid round-trips between regions and avoid adding a lot of latency to the requests.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improving TTFB of the assets in your websites&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Occasionally we can also observe a good time spent on the "pre-transfer" phase. The DNS resolution/Handshake/SSL is part of the initial setup of a request lifecycle, and they can take a considered portion of the time of the request.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furbci4ffxw5hthqnqfte.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Furbci4ffxw5hthqnqfte.png" alt="breakdown of http, tcp, ssl phases in a request"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Web request time breakdown considering HTTP + TCP + TLS as per &lt;a href="https://blog.cloudflare.com/a-question-of-timing/" rel="noopener noreferrer"&gt;Timing web requests&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Anecdotally I often observe around 200ms spent on this phase on various sites and their respective resources.&lt;/p&gt;

&lt;p&gt;The following &lt;code&gt;rel&lt;/code&gt; values for the &lt;code&gt;link&lt;/code&gt; tags are good ways to speed up your TTFB on our websites.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Performance/dns-prefetch" rel="noopener noreferrer"&gt;DNS prefetching&lt;/a&gt;; adding this rel to a link tag pointing to the domain you will download the resource will make the browser attempt resolving the domain before that resource is requested on the page. Effectively saving time when you actually need the resource. Example; &lt;code&gt;&amp;lt;link rel="dns-prefetch" href="[https://fonts.googleapis.com/](https://fonts.googleapis.com/)"&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preconnect" rel="noopener noreferrer"&gt;Preconnect&lt;/a&gt;; adding this rel to a link tag results  in the DNS resolution, and also the TCP handshake, connection establishment (on HTTPS). Example; &lt;code&gt;&amp;lt;link rel="preconnect" href="[https://fonts.googleapis.com/](https://fonts.googleapis.com/)" crossorigin&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload" rel="noopener noreferrer"&gt;Preload&lt;/a&gt;; adding this rel to a link tag results in the browser fetching the asset while looking at that tag in the &lt;code&gt;head&lt;/code&gt; of our documents. This will make the resources available sooner and avoid blocking or delaying the rendering! Example&lt;code&gt;&amp;lt;link rel="preload" href="style.css" as="style"&amp;gt;&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;⚠️ Utilising DNS-prefetch or preconnect against the same website domain is ineffective because that would already be resolved and cached by the browser. So target other domains! &lt;/p&gt;

&lt;p&gt;⚠️ Because these are all tags included in the head of our documents, if we are already preloading assets under a DNS, we are less likely to have the compounding effect of using preload+prefetch+preconnect.&lt;/p&gt;

&lt;p&gt;⚠️ Do not preload too many assets; otherwise, we can make things worse than before! Any preloaded asset will compete for bandwidth with other resources of ours pages.&lt;/p&gt;

&lt;p&gt;💡 Consider using both preconnect and prefetching together so while one will save time on the resolution, the other will save time on the handshake.&lt;/p&gt;

&lt;p&gt;💡 Consider using preload for assets above the fold only to optimise LCP, for example, hero images or fonts. Additionally, consider using prefetch and preconnect for resources that live in other domains and will be requested later in the page lifecycle.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Improving TTFB on server&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Reviewing the connections between the servers and other data sources (databases, APIs, ...) is important because the pre-transfer phase can take a long time there too!&lt;/p&gt;

&lt;p&gt;This can positively impact all requests on the servers and not only initial page loads.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkd34by5tlhjzz80b5ev.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkd34by5tlhjzz80b5ev.png" alt="breakdown of requests between client, server and external sources"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Request breakdown when fetching extra resources from a data source on the server&lt;/p&gt;

&lt;p&gt;The most impactful advice regarding TTFB is to utilise &lt;a href="https://en.wikipedia.org/wiki/HTTP_persistent_connection" rel="noopener noreferrer"&gt;keep-alive&lt;/a&gt; when possible.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep-alive is a property of an HTTP connection that maintains a connection alive after being established and used for the first time. Subsequent requests to the same destination will reuse that connection as opposed to creating new ones every time.&lt;/li&gt;
&lt;li&gt;This is commonly supported by HTTP clients in the vast majority of frameworks and languages. For instance, in Node.js, we could do it by doing &lt;code&gt;const agent = new https.Agent({ keepAlive: true });&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I hope we can see now how we can save time spent on pre-transfer protocols on &lt;strong&gt;every request **&lt;/strong&gt;when utilising this.&lt;/p&gt;

&lt;p&gt;⚠️ Worth pointing out that maintaining keep-alive connections on the server can impact load balancing and memory consumption, so &lt;a href="https://www.quora.com/Are-there-any-disadvantages-of-enabling-Keep-Alive-on-WebServer" rel="noopener noreferrer"&gt;there are valid reasons to keep it disabled&lt;/a&gt;. It requires testing!&lt;/p&gt;

&lt;p&gt;When using &lt;a href="https://en.wikipedia.org/wiki/HTTP/2" rel="noopener noreferrer"&gt;HTTP/2&lt;/a&gt;, this will probably be handled for us when utilizing their clients, and it is even more powerful.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The impact&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;TL: DR; The higher your TTFB, the higher the LCP will be! However, I could not find a linear correlation between TTFB and LCP in my endeavours on page performance. For instance, in some experiments, I noticed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A small delay in the request time, &lt;code&gt;50ms&lt;/code&gt; to &lt;code&gt;200ms&lt;/code&gt;, did not clearly affect the LCP.&lt;/li&gt;
&lt;li&gt;A longer delay, &lt;code&gt;1s&lt;/code&gt; to &lt;code&gt;2s&lt;/code&gt;, correlated to an increase of the LCP time, but not by the same values, maybe from &lt;code&gt;0.5&lt;/code&gt; to &lt;code&gt;1&lt;/code&gt; second?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My personal conclusion is that chasing up improvements of &lt;code&gt;&amp;lt; 200ms&lt;/code&gt; is less likely to improve LCP scores individually, but if that is an improvement on the TTFB of your website, then it is awesome!&lt;/p&gt;

&lt;p&gt;The point is not to get fixated on the metrics! Depending on your website and infrastructure, different initiatives can yield many different results!&lt;/p&gt;

&lt;p&gt;Ensuring we review our websites and APIs from &lt;a href="https://en.wikipedia.org/wiki/First_principle" rel="noopener noreferrer"&gt;first principles&lt;/a&gt; is important to identify potential improvements and deliver better customer experiences!&lt;/p&gt;

&lt;p&gt;I hope this was useful, and I see you next time 👋&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Related readings&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Time_to_first_byte" rel="noopener noreferrer"&gt;Time To First Byte&lt;/a&gt;, &lt;a href="https://developers.google.com/speed/docs/insights/Server#overview" rel="noopener noreferrer"&gt;Improve server response time&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/vitals/" rel="noopener noreferrer"&gt;Core Web Vitals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/search/blog/2020/11/timing-for-page-experience" rel="noopener noreferrer"&gt;Timing for bringing page experience to Google Search&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://web.dev/lcp/" rel="noopener noreferrer"&gt;Largest Contentful Paint (LCP)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.chrome.com/docs/devtools/network/reference/#timing-preview" rel="noopener noreferrer"&gt;Previewing time breakdown&lt;/a&gt;, &lt;a href="https://curl.se/" rel="noopener noreferrer"&gt;cURL&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.cloudflare.com/a-question-of-timing/" rel="noopener noreferrer"&gt;Timing web requests&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Content_delivery_network" rel="noopener noreferrer"&gt;Content Delivery Network&lt;/a&gt;, &lt;a href="https://developers.google.com/web/updates/2019/02/rendering-on-the-web" rel="noopener noreferrer"&gt;Page Rendering&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://developer.mozilla.org/en-US/docs/Web/Performance/dns-prefetch" rel="noopener noreferrer"&gt;Using NS-Prefetch&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preconnect" rel="noopener noreferrer"&gt;Using preconnect&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Link_types/preload" rel="noopener noreferrer"&gt;Link preload&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/HTTP_persistent_connection" rel="noopener noreferrer"&gt;HTTP Keep-alive&lt;/a&gt;, &lt;a href="https://www.quora.com/Are-there-any-disadvantages-of-enabling-Keep-Alive-on-WebServer" rel="noopener noreferrer"&gt;Disadvantages of keep-alive&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>cache</category>
      <category>performance</category>
      <category>ttfb</category>
      <category>web</category>
    </item>
    <item>
      <title>How to store raw values with Rails.cache</title>
      <dc:creator>Rafael Nunes</dc:creator>
      <pubDate>Mon, 25 Jan 2021 10:36:56 +0000</pubDate>
      <link>https://dev.to/peaonunes/how-to-store-raw-values-with-rails-cache-1c59</link>
      <guid>https://dev.to/peaonunes/how-to-store-raw-values-with-rails-cache-1c59</guid>
      <description>&lt;p&gt;I was using the Rails cache and Redis and I quickly overflew the memory storage so I went on a small quest to better understand the Rails cache implementation. I thought it worths writing a bit about it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TLDR; use your cache client directly or pass the raw option as true to the Rails.cache methods.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Rails provides a comprehensive and easy to use interface for caching, that is the &lt;a href="https://guides.rubyonrails.org/caching_with_rails.html#cache-stores" rel="noopener noreferrer"&gt;Cache-Store&lt;/a&gt;. It provides a common interface to any of the standard cache implementations that Rails provides out of the box, from the in-memory cache to file, &lt;a href="https://www.memcached.org/" rel="noopener noreferrer"&gt;Memcached&lt;/a&gt; and &lt;a href="https://redis.io/" rel="noopener noreferrer"&gt;Redis&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The cache implementation is very convenient because that allows us to store from &lt;code&gt;HTML&lt;/code&gt; partials to &lt;code&gt;Models&lt;/code&gt; and complex classes. The best part is that it abstracts the whole serialization so you always end up with workable entities without needing to worry about a thing.&lt;/p&gt;

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

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Game id: 1, name: "Pokemon", created_at: "2021-01-14 12:10:59.872271000 +0000", updated_at: "2021-01-14 12:10:59.872271000 +0000"&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'pokemon'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;game&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"OK"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'pokemon'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Game id: 1, name: "Pokemon", created_at: "2021-01-14 12:10:59.872271000 +0000", updated_at: "2021-01-14 12:10:59.872271000 +0000"&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;pokemon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"Pokemon"&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;In the example above we load a record from the &lt;code&gt;Games&lt;/code&gt; table then we cache that entity using the &lt;code&gt;Rails.cache.write&lt;/code&gt; method. When retrieving the cache entry with its key we end up with the same model class we were using before, and we can even call its methods and attributes as expected. That's super cool, isn't it!? But how does Rails do it?&lt;/p&gt;

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

&lt;span class="c1"&gt;# https://github.com/rails/rails/blob/291a3d2ef29a3842d1156ada7526f4ee60dd2b59/activesupport/lib/active_support/cache.rb#L598-L600&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;serialize_entry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vi"&gt;@coder&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dump&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;The answer is in the snippet above from the cache-store implementation, and what the &lt;code&gt;@coder&lt;/code&gt; instance holds, it holds an instance of the &lt;a href="https://ruby-doc.org/core-3.0.0/Marshal.html" rel="noopener noreferrer"&gt;&lt;code&gt;Marshal&lt;/code&gt;&lt;/a&gt; library.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The marshaling library converts collections of Ruby objects into a byte stream, allowing them to be stored outside the currently active script. This data may subsequently be read and the original objects reconstituted.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Before reading or writing any record the cache-store will serialize the entry by default, and it will use the &lt;code&gt;Marshal&lt;/code&gt; library to do so. In that way, the magic is done for us and we can read and write any Ruby object 🥳!&lt;/p&gt;




&lt;h2&gt;
  
  
  Simple objects storage cost
&lt;/h2&gt;

&lt;p&gt;Let’s now set this learning for a moment and analyze another example. Imagine we want to store a boolean.&lt;/p&gt;

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

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"OK"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cache&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="s1"&gt;'yes'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;Rails is able to store it and retrieve without any issues.&lt;/p&gt;

&lt;p&gt;That said, we would expect the value stored in the cache to be stringified version of the boolean, right? To confirm that let’s connect directly to the storage and inspect the values there.&lt;/p&gt;

&lt;p&gt;— In my case, I’m using Redis as the cache so I just instantiate a new instance of its client to connect directly to it.&lt;/p&gt;

&lt;p&gt;After getting the &lt;code&gt;yes&lt;/code&gt; value it is clear than we have much more than “true”.&lt;/p&gt;




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

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Redis client v4.1.4 for redis://127.0.0.0:6379/0&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;u0004&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;bo: ActiveSupport::Cache::Entry&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;t:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;v@valueT:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;r@version0:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;u0010@created_atf&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;u00161609929749.567886:&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;u0010@expires_at0"&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;What ends up being stored is the serialized version of an &lt;a href="https://github.com/rails/rails/blob/291a3d2ef29a3842d1156ada7526f4ee60dd2b59/activesupport/lib/active_support/cache.rb#L792" rel="noopener noreferrer"&gt;ActiveSupport::Cache::Entry&lt;/a&gt; instance. The Entry class is an abstraction that implements expiration, compression and versioning of any cache record. Through this class, Rails can implement these features independently from the actual storage used behind it.&lt;/p&gt;

&lt;p&gt;The cache entry class encapsulates whatever value we store in the cache by default. Leveraging the &lt;code&gt;Marshal&lt;/code&gt; lib the Rails cache is capable of storing any simple/complex object while offering the cache features. That is great!&lt;/p&gt;

&lt;p&gt;In our previous example, the serialized version of the cache entry is a String of &lt;code&gt;100 chars&lt;/code&gt; instead to of a &lt;code&gt;4 chars&lt;/code&gt; String — true. That is an extra &lt;code&gt;96 chars&lt;/code&gt; for storing the same information.&lt;/p&gt;

&lt;p&gt;While for the most cases that is totally fine, what if you really need to care about the amount of the stored data?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fagnvvp47kg6h2rundwcc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fagnvvp47kg6h2rundwcc.png" alt="drawing of setting and getting cache value"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To understand the impact of these extra chars let’s elaborate more on our example.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;short detour: &lt;a href="https://github.com/redis/redis" rel="noopener noreferrer"&gt;Redis is implemented in C&lt;/a&gt;  and it probably needs a few extra bytes to maintain our String value which is an array of chars underneath. But let’s not consider it since that’s the same extra bytes to all String values.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Knowing we need &lt;code&gt;1B&lt;/code&gt; to store &lt;code&gt;1 char&lt;/code&gt;, in C, we can conclude we would need &lt;code&gt;100B&lt;/code&gt; to store the serialized version of Entry cache store.&lt;/p&gt;

&lt;p&gt;Now for &lt;code&gt;1 million&lt;/code&gt; records with the value true we would need &lt;code&gt;100MB&lt;/code&gt; (1M * 100B). This example is “simple” and &lt;code&gt;100MB&lt;/code&gt; may not sound a lot but if you need to store a little bit more than a boolean, if you are using the in-memory store, or if you have limited space in &lt;code&gt;Redis&lt;/code&gt; that can start hurting.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Alternatives
&lt;/h2&gt;

&lt;p&gt;The direct alternative I could think about was to use the &lt;code&gt;Redis&lt;/code&gt; client directly instead of using the &lt;code&gt;Rails.cache&lt;/code&gt; abstraction.&lt;/p&gt;

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

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'no'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"OK"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'no'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"false"&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;It should work as expected and we are no longer utilizing the extra space for that value 🙌🏽. We are left then with the job to parse that object back to a boolean value.&lt;/p&gt;

&lt;p&gt;Another alternative that I found after looking at the Redis cache store implementation on GitHub was to pass down the &lt;code&gt;raw&lt;/code&gt; option.&lt;/p&gt;

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

&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;raw: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"OK"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"yes"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'yes'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;raw: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;This option is only mentioned in the &lt;code&gt;Memcached&lt;/code&gt; part of the docs, but that is at least also supported on &lt;code&gt;Redis&lt;/code&gt; cache store implementation as it overrides the default &lt;code&gt;serialize_entry&lt;/code&gt; method &lt;a href="https://github.com/rails/rails/blob/291a3d2ef29a3842d1156ada7526f4ee60dd2b59/activesupport/lib/active_support/cache/redis_cache_store.rb#L468-L474" rel="noopener noreferrer"&gt;[1]&lt;/a&gt;. Similar to utilizing the Redis client directly we will need to parse the resulting string back to a boolean manually. Even though we lose the &lt;code&gt;Entry&lt;/code&gt; features that is not a big deal if you are using &lt;code&gt;Redis&lt;/code&gt; or &lt;code&gt;Memcached&lt;/code&gt; since they provide most of these features out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Thanks a lot if you got this far!&lt;/p&gt;

&lt;p&gt;The level of caution that this post brings to the usage of Rails cache is, most of the times, not required. However, if you ever want to cache millions of simple objects knowing some of these details can make a difference!&lt;/p&gt;

&lt;p&gt;See you next time!&lt;/p&gt;

</description>
      <category>rails</category>
      <category>ruby</category>
      <category>redis</category>
      <category>cache</category>
    </item>
    <item>
      <title>N+1 &amp; Eager loading &amp; Beyond</title>
      <dc:creator>Rafael Nunes</dc:creator>
      <pubDate>Tue, 01 Dec 2020 01:30:55 +0000</pubDate>
      <link>https://dev.to/peaonunes/n-1-eager-loading-beyond-1in7</link>
      <guid>https://dev.to/peaonunes/n-1-eager-loading-beyond-1in7</guid>
      <description>&lt;p&gt;The &lt;strong&gt;N+1 problem&lt;/strong&gt; is one of the most common issues when our applications grow. That is frequently associated with &lt;a href="https://en.wikipedia.org/wiki/Object%E2%80%93relational_mapping"&gt;ORMs&lt;/a&gt; because their abstractions can hide the resulting queries executed. However, it's not limited to them since we can always manually fetch data in a manner that will culminate in that problem. &lt;/p&gt;

&lt;p&gt;Imagine we have &lt;code&gt;Match&lt;/code&gt;, and we want to report the last 100 matches with their duration. In an ORM like &lt;a href="https://guides.rubyonrails.org/active_record_basics.html"&gt;ActiveRecord&lt;/a&gt; that could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="no"&gt;Report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;duration: &lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now imagine that for every &lt;code&gt;Match&lt;/code&gt; played we have an associated &lt;code&gt;Game&lt;/code&gt;. So besides the match itself, we want to report the game name, for example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="no"&gt;Report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;duration: &lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;game_name: &lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So even though &lt;code&gt;Game&lt;/code&gt; is in another table that is tied to &lt;code&gt;Match&lt;/code&gt; via the association, so Active Record will make use of &lt;a href="https://rubyinrails.com/2014/01/08/what-is-lazy-loading-in-rails/"&gt;lazy loading&lt;/a&gt; to load the required data for us. Lazy loading is handy because you can easily query related data on demand.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;matches&lt;/span&gt; &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;games&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;games&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;games&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;games&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;#&lt;/span&gt; &lt;span class="mi"&gt;98&lt;/span&gt; &lt;span class="n"&gt;queries&lt;/span&gt; &lt;span class="n"&gt;later&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;games&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;games&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;However, the problem that was introduced here is hidden in the queries level. Because we are lazy loading the games on every loop iteration that will lead to a new SQL query to the database every time. The resulting number of queries would be &lt;code&gt;1 for the matches + 100 for loading games = 101 queries&lt;/code&gt; —boom that's our N+1.&lt;/p&gt;




&lt;h2&gt;
  
  
  Eager Loading
&lt;/h2&gt;

&lt;p&gt;Eager loading is another strategy to prevent N+1. The strategy consists in loading upfront any data of interest so whenever you need to access that data it would already be available in memory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:game&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="no"&gt;Report&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;duration: &lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;duration&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;game_name: &lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The code uses the &lt;code&gt;includes&lt;/code&gt; query method to indicate what relationships we need to query alongside the &lt;code&gt;Matches&lt;/code&gt; one, it does so by leveraging the relationship between &lt;code&gt;Matches&lt;/code&gt; and &lt;code&gt;Games&lt;/code&gt;. Active Record will ensure that all of the specified associations are loaded using the minimum possible number of queries. It could do a join and or an additional SQL, &lt;strong&gt;but no lazy load anymore.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;matches&lt;/span&gt; &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;matches&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;games&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;games&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;match_id&lt;/span&gt; &lt;span class="k"&gt;IN&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Preventing lazy loading 🙅‍♂️
&lt;/h2&gt;

&lt;p&gt;One alternative is to stop working with Models and transforming them into hashes, or other in-memory only entities. Having that, we can safely operate without worrying about dispatching queries, but the trade-off is that we lose that rich API and we need to re-expose any functionality attached to the Model.&lt;/p&gt;

&lt;p&gt;Another alternative is to use tools that help us to track and identify the N+1 issues early in the process. Packages like &lt;a href="https://github.com/flyerhzm/bullet"&gt;bullet&lt;/a&gt; alert us when we should add eager loading to queries or when you should cache, for example. We the tools work for us but we are still reactive to alerts (on prod or dev environments).&lt;/p&gt;

&lt;p&gt;Rails 6.1 was released with &lt;a href="//guides.rubyonrails.org/6_1_release_notes.html#strict-loading-associations"&gt;strict loading&lt;/a&gt; and that introduces an optional strict mode for models to prevent lazy load!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Match&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="c1"&gt;# attrs...&lt;/span&gt;
  &lt;span class="ss"&gt;has_one: :game&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;strict_loading: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Game&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="c1"&gt;# attrs...&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;Match&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;game&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; ActiveRecord::StrictLoadingViolationError Exception: Match is marked as strict_loading and Game cannot be lazily loaded.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can set up the &lt;code&gt;strict_loading&lt;/code&gt; at the application level, the model level or association level. If we ever try to lazy load the association we will get an error 🎉 . That is great because we are proactive and we cannot create lazy queries in the first place!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Pros and Cons&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;The clear benefit is that we avoid flooding the data source with individual queries for every relationship inside the loop. That reduces the risk of the calls, the load in the data sources and generally ends up being more performant.&lt;/p&gt;

&lt;p&gt;The caveat is that these single queries to all records and its relationships are not much more expensive than the ones we run on every loop iteration. So if you need to load everything at some point, then eager loading should be adequate.&lt;/p&gt;

&lt;p&gt;Of course, that comes with a memory cost to load everything upfront. And ultimately if you in our code you end up not using all the data queried that you're loading then you might be wasting memory and slowing down some queries.&lt;/p&gt;




&lt;h2&gt;
  
  
  Beyond relational Eager Loading 🚀
&lt;/h2&gt;

&lt;p&gt;Sometimes we need to load data that is not explicitly related in the database, that can be fetched from other data source (APIs, cache, DBs, ...) so we cannot leverage frameworks’ features like the one from &lt;code&gt;ActiveRecord&lt;/code&gt;. However, it is possible to implement eager loading by ourselves or use other patterns that avoid N+1 in similar manners, like &lt;a href="https://github.com/graphql/dataloader#other-implementations"&gt;data-loaders&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/yns3VgsP30GDm/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/yns3VgsP30GDm/giphy.gif" alt="https://media.giphy.com/media/yns3VgsP30GDm/giphy.gif"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your process is very data-intensive or is not a web request-response you might need to look into further alternatives. We could consider caching, denormalising the data, preprocessing data, batch vs streaming processing, etc. These are all big topics that deserve much more elaboration than this post aims to do. If you are interested in these topics, I recommend &lt;a href="https://dataintensive.net/"&gt;Designing Data-Intensive&lt;/a&gt; applications which cover these topics in a great manner.&lt;/p&gt;

&lt;p&gt;In summary, whatever implementation the principle is still the same: &lt;strong&gt;use abstractions to query all necessary data with the minimum amount of queries possible&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I might explore more of these topics later, but for now, this is it, see you later 👋&lt;/p&gt;

</description>
      <category>performance</category>
      <category>rails</category>
    </item>
    <item>
      <title>Reflections of five years doing Hacktoberfest</title>
      <dc:creator>Rafael Nunes</dc:creator>
      <pubDate>Mon, 16 Nov 2020 02:26:04 +0000</pubDate>
      <link>https://dev.to/peaonunes/reflections-of-five-years-doing-hacktoberfest-481c</link>
      <guid>https://dev.to/peaonunes/reflections-of-five-years-doing-hacktoberfest-481c</guid>
      <description>&lt;p&gt;The event has grown and I with it. I was thinking about that and decided to share some thoughts... I might change my mind later.&lt;/p&gt;

&lt;p&gt;Five or four years ago, I had little engagement with open source and collaborating with the community in general. Despite my genuine interest in giving back, I knew little about practical ways of doing it. &lt;/p&gt;

&lt;p&gt;Then I heard about Hacktoberfest for the first time. The idea of going beyond using and sharing open source, and actually to collaborate sounded nice, in addition to that, we would get rewards, looks great!&lt;/p&gt;

&lt;p&gt;I am going to be open (puns intended), and I admit that the shirt was appealing to me. We can argue whether or not that's "cheap" from me, but we should agree to the fact that with the right incentives, we all get more traction.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3o6MbnubDfLpci65fq/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3o6MbnubDfLpci65fq/giphy.gif" alt="and they contribute to entertainment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The event over the years
&lt;/h2&gt;

&lt;p&gt;The event changed the goal number of PRs a couple of times, 3 to 4, 4 to 5... I also saw multiple in-person meetups spawning so people could work together, sense of community growing! And in this year's edition, you could even plant a tree instead of getting a T-shirt you can still &lt;a href="https://tree-nation.com/profile/fundraising/digitalocean"&gt;donate it&lt;/a&gt; 🌲.&lt;/p&gt;

&lt;p&gt;Imho, they did the most meaningful change was done this year, and it came for good: the new rules. The increasing success and the lack of quality checks of the contributions laid the path to the maintainer's burden. The problem only got more significant, and the organisers acknowledged it.&lt;/p&gt;

&lt;p&gt;The PRs now only count towards the goal if maintainers opted-in to participate by classifying their projects with the hacktoberfest topic, or if they labelled it with the specific hacktboer label, or if they approved it.&lt;/p&gt;

&lt;p&gt;That's great at various levels, and I hope we all will see more and get a more mature format over the upcoming years.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--i1322CbO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gptl657qrgas2fyq4i92.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--i1322CbO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gptl657qrgas2fyq4i92.png" alt="five years os hacktoberfest logos"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  My contributions over the years
&lt;/h2&gt;

&lt;p&gt;I started by collaborating with open projects from the uni I went and &lt;a href="https://github.com/pet-informatica"&gt;research groups&lt;/a&gt; I was part of previously. That was sufficient to achieve that first year, but that had very little to do the broader development community. &lt;/p&gt;

&lt;p&gt;The following years I tried to fill that gap, I contributed to the open &lt;a href="https://github.com/inloco/supernova"&gt;design systems&lt;/a&gt; as the one from the company I was working. In addition to that, I tried to find issues related to technologies I was interested in or that I used. For example, I found some nice issues about &lt;a href="https://github.com/facebook/react-native/issues/21581"&gt;converting React Native components out off React.createClass&lt;/a&gt; and &lt;a href="https://github.com/facebook/react-native/issues/21485"&gt;removing TimerMixin, SubscribableMixin from React Native components&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⭐️ Trying to find issues that relate with you interest is a great strategy. I struggled in the beginning because I was looking for any repos, on any languages, etc. I soon realised that if I searched for something related to my skills/interests, I would be able to collaborate much more.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Another example, when I was looking into functional programming with &lt;a href="https://ramdajs.com/"&gt;Radma&lt;/a&gt;, it made sense to me to collaborate on &lt;a href="https://github.com/char0n/ramda-adjunct"&gt;radmda-adjunct&lt;/a&gt; utility functions. And when I was having fun using &lt;a href="https://www.gatsbyjs.com/"&gt;Gatsby&lt;/a&gt;, I was happy to know they were translating the docs to &lt;a href="https://github.com/gatsbyjs/gatsby-pt-BR"&gt;pt-BR&lt;/a&gt;, and I could jump into that.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/lzz3B3xLZluuY/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/lzz3B3xLZluuY/giphy.gif" alt="and they contribute to entertainment"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  This year
&lt;/h2&gt;

&lt;p&gt;Early this year &lt;a href="https://blitzjs.com/"&gt;Blitz&lt;/a&gt; appeared with a very appealing to me with its focus on productivity, simplicity and conventions to the React world. Having worked both Ruby and JS, I always felt we were messing something like Rails for JS. Naturally, I wanted this to succeed, so I tried to collaborate with it whenever I could. Although I have not worked on any big project, I was able to chip away some issues throughout the whole year.&lt;/p&gt;

&lt;p&gt;At the beginning of this October, the dependabot updated a gem called &lt;a href="https://github.com/BetterErrors/better_errors"&gt;better_errors&lt;/a&gt;, and some projects I use on work started to fail. Despite unblocking my team reverting the version, I took a step further to try to find the issue, and I managed to push a fix for it. I was not very bad, after all!&lt;/p&gt;

&lt;p&gt;Lastly, I  found a great project called &lt;a href="https://github.com/rubyforgood"&gt;rubyforgood&lt;/a&gt;, which is a collection of open projects dedicated to making the world gooder! How cool is that? Despite my contribution to that not even counting towards the event goal, I think I found something much more valuable, and I hope I can do way more for it soon.&lt;/p&gt;

&lt;p&gt;None of the examples above would be possible if I have not gradually been more involved with the community and comfortable with jumping around open codebases. It gets more doable with time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/RHOy0GlzSCK5o7zjrP/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/RHOy0GlzSCK5o7zjrP/giphy.gif" alt="can I make some an original and groundbreaking observation?"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Some observations
&lt;/h2&gt;

&lt;p&gt;I learned a lot just by exploring different codebases and navigating the issues, but of course, tackling some of them and pushing the code changes required. All that helped me to be much more comfortable with new codebases, different stacks/paradigms, mental models, etc. And learn the way people solve various problems.&lt;/p&gt;

&lt;p&gt;Another good thing that I thought the event created was a sense of belonging. For sure, a shirt might not be much of a big deal for a lot of people, but I soon realised that it created a sense of community for a bunch of others.&lt;/p&gt;

&lt;p&gt;The event gradually brought every part of the community closer, and I think that is great. I started to watch various repositories, communities discussions, innovations and to filter way the desire to try re-write my apps every time a new thing popped up. &lt;/p&gt;

&lt;p&gt;I believe there is much more space for learning and evolution on all sides of the event, and just time and practice will allow us to develop a better community as a whole.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thoughts
&lt;/h2&gt;

&lt;p&gt;The most challenging part is to start. So if you are new to it, then start small, because small issues and small PRs will lay the path for you to get comfortable. Try to find topics that relate to your interests/skills. Share your achievements. I'm bad at this, but I feel nice when others celebrate my accomplishments with me.&lt;/p&gt;

&lt;p&gt;Fail fast and learn quickly. Try to hold your fear of failing, the more you fail, the more you learn as well. Ultimately you get used to taking risks and learn much faster.&lt;/p&gt;

&lt;p&gt;Let's support our community, both maintainers and users in a healthy way 🙌. Let's keep this wheel rolling. There is still much left to be done, and do not wait for another hacktoberfest to start doing it!&lt;/p&gt;

&lt;p&gt;Lastly, be open and stay safe. See you soon 👋&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>opensource</category>
    </item>
    <item>
      <title>Circuitbox: How to Circuit Breaker in Ruby</title>
      <dc:creator>Rafael Nunes</dc:creator>
      <pubDate>Wed, 24 Jun 2020 12:05:03 +0000</pubDate>
      <link>https://dev.to/peaonunes/circuitbox-how-to-circuit-breaker-in-ruby-3hc2</link>
      <guid>https://dev.to/peaonunes/circuitbox-how-to-circuit-breaker-in-ruby-3hc2</guid>
      <description>&lt;p&gt;A few years ago, I made a post called &lt;a href="https://medium.com/@peaonunes/hystrix-from-creating-resilient-applications-to-monitoring-metrics-a38bffdca897"&gt;Hystrix: from creating resilient applications to monitoring metrics&lt;/a&gt; where I talked about avoiding catastrophes with circuit breakers in &lt;code&gt;Java&lt;/code&gt; and &lt;strong&gt;monitoring&lt;/strong&gt; our applications using &lt;strong&gt;Prometheus&lt;/strong&gt; and &lt;strong&gt;Grafana&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This post focused on using &lt;a href="https://github.com/yammer/circuitbox"&gt;Circuitbox&lt;/a&gt;, a &lt;code&gt;Ruby&lt;/code&gt; gem for creating circuit breakers.&lt;/p&gt;

&lt;p&gt;If you are not keen to read now then you can watch the video version of this post with extended examples that is available below.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/33l9ROqmapk"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Service to service communication
&lt;/h2&gt;

&lt;p&gt;When building some service, it is not uncommon that we would do &lt;strong&gt;remote calls&lt;/strong&gt; to APIs to perform some action. These points of connection to external services turn to be &lt;strong&gt;points of failure&lt;/strong&gt; on our applications.&lt;/p&gt;

&lt;p&gt;Downstream services help us to achieve our goals, but the more critical is that service, the more significant the impact of its failure will generate and propagate in the platform.&lt;/p&gt;

&lt;p&gt;If any external API stops working, would your application &lt;strong&gt;still operate&lt;/strong&gt;?&lt;/p&gt;

&lt;h2&gt;
  
  
  Circuit Breakers ⚡️
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://martinfowler.com/bliki/CircuitBreaker.html"&gt;Circuit Breaker&lt;/a&gt; is a software design pattern that proposes the monitoring of the remote calls &lt;strong&gt;failures&lt;/strong&gt;, so when it reaches a certain &lt;strong&gt;threshold&lt;/strong&gt;, it "opens the circuit" forwarding all the calls to an elegant and alternative flux. Handling the error gracefully and/or providing a default behaviour for the feature in case of failure.&lt;/p&gt;

&lt;p&gt;The pattern states a &lt;strong&gt;time window&lt;/strong&gt; on what it will request that service again to check its health. When the downstream API start responding accordingly under the same thresholds, then the circuit will close and enable the main flow again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--W1-xRdxF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sfk74zncglxfqfuq5dv0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--W1-xRdxF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sfk74zncglxfqfuq5dv0.png" alt="circuit breaker state machine"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The intention behind circuit breakers is to avoid pursuing a failure service if we &lt;strong&gt;already know&lt;/strong&gt; that it is unstable and not reliable at the moment. We then can decide what to do and keep our systems operating or partially operating.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some use cases
&lt;/h3&gt;

&lt;p&gt;Fail fast: We don't wait for a timeout if we know it won't result in success.&lt;/p&gt;

&lt;p&gt;Partially fail: When we have an option to continue with a different response from the ideal.&lt;/p&gt;

&lt;p&gt;Best effort: We try to call the other service, but we don't care about the result, eg. Non-critical analytics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Hands-on 🙌
&lt;/h2&gt;

&lt;p&gt;What would that look to use a circuit breaker in &lt;code&gt;Ruby&lt;/code&gt;? &lt;/p&gt;

&lt;p&gt;The following exercise code is available on GitHub at &lt;a href="https://github.com/peaonunes/circuitbox-example"&gt;circuitbox-example&lt;/a&gt;. There we have a node server and a &lt;a href="https://rubyonrails.org/"&gt;&lt;code&gt;Rails&lt;/code&gt;&lt;/a&gt; application. The &lt;code&gt;node&lt;/code&gt; server will be the downstream service consumed by our main &lt;code&gt;Rails&lt;/code&gt; application.&lt;/p&gt;

&lt;h3&gt;
  
  
  Simulating a failure ⚠️
&lt;/h3&gt;

&lt;p&gt;To simulate a downstream service, we have the &lt;strong&gt;target-server&lt;/strong&gt;, an &lt;code&gt;express&lt;/code&gt; server with only the index route (&lt;code&gt;/&lt;/code&gt;). We will be querying it from our main application.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="kd"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&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;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;delay&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;fast&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;50&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="nx"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&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;sendStatus&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="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;delay&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;To facilitate our experiments, we are going to pass in the query string a parameter called &lt;code&gt;speed&lt;/code&gt;. We'll use that parameter to simulate a &lt;strong&gt;slow&lt;/strong&gt; or a &lt;strong&gt;fast&lt;/strong&gt; network response.&lt;/p&gt;

&lt;p&gt;Whenever it receives &lt;code&gt;speed&lt;/code&gt; as &lt;code&gt;fast&lt;/code&gt;, then the server will delay the answer by &lt;code&gt;50ms&lt;/code&gt;. If it gets anything else, it will delay the reply by &lt;code&gt;200ms&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4ctKFi46--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sdc1j6wj4j9zpd5ihilq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4ctKFi46--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/sdc1j6wj4j9zpd5ihilq.jpg" alt="response with a delay"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  The consumer 💻
&lt;/h3&gt;

&lt;p&gt;In our &lt;code&gt;Rails&lt;/code&gt; application, I've created an index route as well. It will have the same parameter as &lt;strong&gt;target-server&lt;/strong&gt; that will be passed down to the remote call.&lt;/p&gt;

&lt;p&gt;We are going to perform &lt;strong&gt;ten calls&lt;/strong&gt; in sequence to our downstream service and return all the answers at once. The following code will do the work for us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
  &lt;span class="n"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:speed&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="n"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="nb"&gt;sleep&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="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Request number &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:4000/?speed=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="n"&gt;answers&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We take the &lt;code&gt;speed&lt;/code&gt; parameter, and then we map through an array of size ten doing a call for every element passing down our query param. We delay every call by 1 second on purpose, so later we can tweak the circuit configuration and see different results. Finally, we render the &lt;code&gt;answers&lt;/code&gt; array with all the responses from our API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Vz-39DYq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qefe0o0jamzuqwqtfxa0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Vz-39DYq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/qefe0o0jamzuqwqtfxa0.jpg" alt="responses array"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The app is hitting the &lt;code&gt;express&lt;/code&gt; server, that looks great! 🚀. Even though the requests are "slow" they are successful as we have not set any timeouts.&lt;/p&gt;

&lt;p&gt;Changing the remote call to &lt;code&gt;HTTP.timeout(0.1).get&lt;/code&gt; will set the timeout as &lt;code&gt;100ms&lt;/code&gt; and then we should see an error as the API is delaying the response by &lt;code&gt;200ms&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--9iW2DtBf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d7dryn69tlbj3nev7u17.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9iW2DtBf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d7dryn69tlbj3nev7u17.jpg" alt="timeout from the api"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And &lt;em&gt;voila&lt;/em&gt; ✨ we got our exception!&lt;br&gt;
Let's keep that &lt;code&gt;HTTP::TimeoutError&lt;/code&gt; in a note because we are going to need it later. &lt;/p&gt;
&lt;h3&gt;
  
  
  Adding the Circuitbox 📦
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/yammer/circuitbox"&gt;Circuitbox&lt;/a&gt;, a &lt;code&gt;Ruby&lt;/code&gt; &lt;code&gt;gem&lt;/code&gt; for creating circuit breakers. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"It wraps calls to external services and monitors for failures in one minute intervals. Once more than 10 requests have been made with a 50% failure rate, Circuitbox stops sending requests to that failing service for one minute. That helps your application gracefully degrade."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can add that in our &lt;code&gt;Gemfile&lt;/code&gt; as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'circuitbox'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'~&amp;gt; 1.1'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'&amp;gt;= 1.1.1'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To utilise the circuit breaker, we need to instantiate a new &lt;code&gt;Circuitbox&lt;/code&gt; class passing at least two arguments: the &lt;strong&gt;server/action name&lt;/strong&gt; and an &lt;strong&gt;array of exceptions&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The exceptions collection is there for counting failures, so if we get an error that is not on that collection, it will not count towards the circuit threshold. Do you remember that &lt;code&gt;HTTP::TimeoutError&lt;/code&gt;? We are going to use it now 😁.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TargetClient&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;:)&lt;/span&gt;
    &lt;span class="vi"&gt;@speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;speed&lt;/span&gt;
    &lt;span class="vi"&gt;@circuit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Circuitbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;circuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:target_server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;exceptions: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TimeoutError&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="nb"&gt;attr_reader&lt;/span&gt; &lt;span class="ss"&gt;:speed&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:circuit&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;call&lt;/span&gt;
    &lt;span class="n"&gt;circuit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;circuitbox_exceptions: &lt;/span&gt;&lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.1&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"http://localhost:4000/?speed=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can create a &lt;code&gt;TargetClient&lt;/code&gt; class that will encapsulate that logic of creating the circuit breaker and making the request. On initialise, it receives and saves the &lt;code&gt;speed&lt;/code&gt; parameter and creates the &lt;code&gt;circuit&lt;/code&gt; assigning the &lt;code&gt;target_server&lt;/code&gt; name and the exception we want to track.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;index&lt;/span&gt;
  &lt;span class="n"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:speed&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

  &lt;span class="n"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="nb"&gt;sleep&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="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Request number &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="no"&gt;TargetClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;speed: &lt;/span&gt;&lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;render&lt;/span&gt; &lt;span class="ss"&gt;json: &lt;/span&gt;&lt;span class="n"&gt;answers&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, the circuit will return &lt;code&gt;nil&lt;/code&gt; for failed requests and open circuits. Then if we hit the endpoint again with &lt;code&gt;speed=slow&lt;/code&gt;, we should expect all the answers to be &lt;code&gt;nil&lt;/code&gt;, but no exception is thrown.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZlSC2omb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ptnicxvjcwfvvyax0e4a.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZlSC2omb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ptnicxvjcwfvvyax0e4a.jpg" alt="all failed answers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that is what happens 🥳! Because we gave a name to the circuit, the &lt;strong&gt;gem&lt;/strong&gt; can track down the requests across all the instances of it. Another cool thing it does by default is to log the status of the call and whether or not the circuit is open.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ArALr3rL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wyns4ghgurzzgygduffz.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ArALr3rL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/wyns4ghgurzzgygduffz.jpg" alt="logs of closed circuit and failed requests"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The first message indicates that we are making the request. The second one exposes the status of the request (as a failure in this case). Although all the applications failed, the circuit remained &lt;strong&gt;closed&lt;/strong&gt; because we are no hitting the threshold necessary to open it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tweaking configs ⚙️
&lt;/h3&gt;

&lt;p&gt;Circuitbox provides a set of configuration we can change to fine-tune its shape and make that fit in our needs. Some of them are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;sleep_window&lt;/code&gt;: seconds the circuit stays open once it has passed the error threshold. Defaults to &lt;code&gt;300&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;time_window&lt;/code&gt;: length of the interval (in seconds) over which it calculates the error rate. Defaults to &lt;code&gt;60&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;volume_threshold&lt;/code&gt;: number of requests within &lt;code&gt;time_window&lt;/code&gt; seconds before it calculates error rates. Defaults to &lt;code&gt;10&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;error_threshold&lt;/code&gt;: exceeding this rate will open the circuit (checked on failures). Defaults to &lt;code&gt;50%&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Knowing that default configuration, we can conclude that the circuit will open if within &lt;strong&gt;60&lt;/strong&gt; seconds we get at least &lt;strong&gt;10&lt;/strong&gt; requests and &lt;strong&gt;50%&lt;/strong&gt; of them fail. For the sake of the exercise, we can rearrange that numbers so we can force the circuit to open and see the results.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="vi"&gt;@circuit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Circuitbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;circuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="ss"&gt;:target_server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;exceptions: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TimeoutError&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;time_window: &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;volume_threshold: &lt;/span&gt;&lt;span class="mi"&gt;5&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;Making both the &lt;code&gt;time_window&lt;/code&gt; and the &lt;code&gt;volume_threshold&lt;/code&gt; to &lt;strong&gt;5&lt;/strong&gt; will lead to open the circuit when we get at least &lt;strong&gt;5&lt;/strong&gt; requests during &lt;strong&gt;5&lt;/strong&gt; seconds, and &lt;strong&gt;50%&lt;/strong&gt; of them fail. We then can try again hitting our app with &lt;code&gt;/?speed=slow&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ueaiHBrr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gqcpueja3voat80ng3b1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ueaiHBrr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/gqcpueja3voat80ng3b1.jpg" alt="open circuit on logs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are the logs after executing it again. If we were to look at the actual response of the &lt;code&gt;Rails&lt;/code&gt; app, we would not notice anything different; the answers would be all &lt;code&gt;nil&lt;/code&gt; again. However, there is some cool stuff going on under the hood.&lt;/p&gt;

&lt;p&gt;We are still passing the &lt;code&gt;slow&lt;/code&gt; as a parameter, and as a result, all requests should fail. After the &lt;strong&gt;5th&lt;/strong&gt; request, the gem calculates the error rate, and we get above the &lt;strong&gt;50%&lt;/strong&gt; threshold of failure. Therefore the circuit &lt;strong&gt;opens&lt;/strong&gt;, and we stop querying the API and just default to the &lt;code&gt;nil&lt;/code&gt; answer. That's why it stops logging the &lt;code&gt;querying&lt;/code&gt; message and its status.&lt;/p&gt;

&lt;h3&gt;
  
  
  Watching it recover 📈
&lt;/h3&gt;

&lt;p&gt;The beauty of using circuit breakers is that we avoid pursuing a failure service if we &lt;strong&gt;already know&lt;/strong&gt; that it is unstable, but beyond that, we check back to see if it recovered already.  &lt;/p&gt;

&lt;p&gt;Let's now tweak our inputs to force the instability and then force a &lt;strong&gt;fast&lt;/strong&gt; response.&lt;/p&gt;

&lt;p&gt;To simulate the API recovered, we are going to change the &lt;code&gt;speed&lt;/code&gt; parameter passed down. So we start with whatever we get from the query string, but after some requests, we change that to be &lt;code&gt;fast&lt;/code&gt;. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;answers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="nb"&gt;sleep&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="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"Request number &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
  &lt;span class="n"&gt;speed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'fast'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;
  &lt;span class="no"&gt;TargetClient&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;speed: &lt;/span&gt;&lt;span class="n"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the app side of things we are keeping &lt;code&gt;time_window&lt;/code&gt; as &lt;strong&gt;5&lt;/strong&gt; seconds, so the interval observed is the same. However, let's decrease &lt;code&gt;volume_threshold&lt;/code&gt; to &lt;strong&gt;2&lt;/strong&gt;, so we need to get at least &lt;strong&gt;2&lt;/strong&gt; requests to calculate the error rate. Finally, let's override &lt;code&gt;sleep_window&lt;/code&gt; to be &lt;strong&gt;2&lt;/strong&gt; seconds (which by default. waits 300 seconds).&lt;/p&gt;

&lt;p&gt;So whit a shorter&lt;code&gt;sleep_window&lt;/code&gt; we should expect the circuit will get back to the API sooner. That new configuration should look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="vi"&gt;@circuit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Circuitbox&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;circuit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="ss"&gt;:target_server&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;exceptions: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TimeoutError&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="ss"&gt;time_window: &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;volume_threshold: &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="ss"&gt;sleep_window: &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After calling our endpoint again, we get &lt;code&gt;null&lt;/code&gt; on every answer besides the last one.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wdxIZ17O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pqb2ljoopl6ft2shjp97.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wdxIZ17O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/pqb2ljoopl6ft2shjp97.png" alt="json with all response nill besides the last one"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can break down the flux of our requests as:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The first &lt;strong&gt;4&lt;/strong&gt; requests happen within the &lt;strong&gt;5&lt;/strong&gt; seconds window, the gem realises we hit our threshold. Therefore, it opens the circuit.&lt;/li&gt;
&lt;li&gt;Our next attempt to request the API will pass &lt;code&gt;speed=fast&lt;/code&gt; as we set to do that if &lt;code&gt;i &amp;gt; 3&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Because the circuit is open all efforts during the &lt;code&gt;sleep_window&lt;/code&gt; will be short-circuited and return &lt;code&gt;null&lt;/code&gt; immediately.&lt;/li&gt;
&lt;li&gt;After some time the &lt;code&gt;sleep_window&lt;/code&gt; ceases and closes the circuit. That makes the following request to reach the API again, and as we passed&lt;code&gt;speed=fast&lt;/code&gt; so the request will succeed.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The actual logs tell us that story.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PXH3-mnk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3kthi9i10ctmchiin7pq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PXH3-mnk--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/3kthi9i10ctmchiin7pq.png" alt="logs from the circuit box showing the attempts and the short-circuited requests"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that is awesome 🥳! We were able to simulate the whole process of querying an API in a bad state, opening the circuit and querying it back once everything is good!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions 🌯
&lt;/h2&gt;

&lt;p&gt;A circuit breaker is a pattern that helps us to avoid catastrophes. We manage to make our applications to &lt;strong&gt;fail gracefully&lt;/strong&gt;, and therefore they end up being &lt;strong&gt;more resilient&lt;/strong&gt;. It helped me in past experiences on &lt;code&gt;Java&lt;/code&gt; and &lt;code&gt;Ruby&lt;/code&gt; projects, but there are many &lt;a href="https://github.com/search?q=circuit+breaker"&gt;implementations on GitHub&lt;/a&gt; for different languages as well.&lt;/p&gt;

&lt;p&gt;I'm curious about your thoughts, how do you all avoid catastrophes? Have you ever tried circuit breakers?&lt;/p&gt;

</description>
      <category>ruby</category>
      <category>circuitbreaker</category>
      <category>designpattern</category>
      <category>rails</category>
    </item>
    <item>
      <title>How I avoid the side project frustration</title>
      <dc:creator>Rafael Nunes</dc:creator>
      <pubDate>Mon, 15 Jun 2020 12:24:13 +0000</pubDate>
      <link>https://dev.to/peaonunes/how-i-avoid-the-side-project-frustration-57eh</link>
      <guid>https://dev.to/peaonunes/how-i-avoid-the-side-project-frustration-57eh</guid>
      <description>&lt;p&gt;I just don't do them anymore.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/3orieSCgKXLMRtKeHu/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/3orieSCgKXLMRtKeHu/giphy.gif" alt="movie credits"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Okay, seriously now...&lt;/p&gt;

&lt;p&gt;How many repositories of unfinished side projects do you have? I  have a lot of them. There is no &lt;strong&gt;secret sauce&lt;/strong&gt; in this post, but I realised that some methods that I already know could push me to be more productive and happy. So I'm sharing them here. 🤗&lt;/p&gt;

&lt;h2&gt;
  
  
  From excitement to frustration
&lt;/h2&gt;

&lt;p&gt;Many times I get excited about new technologies and get in that hacker mood, I cannot rest until I try that out. Maybe I am looking into practice some skill that will be useful in the future. Or that project might be just for fun!&lt;/p&gt;

&lt;p&gt;No matter what the trigger is, we may get motivated about an idea and want to turn that into a real thing. However, it is not extraordinary to get frustrated about that. That is very common it and happens to me quite often.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/tJDAeuB5NMtNUx1Swx/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/tJDAeuB5NMtNUx1Swx/giphy.gif" alt="projects!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was frustrated about the side project frustration 🤣.  I started thinking more and more about that, and I decided to focus on the problems behind that occurring so often to me. Then I managed to narrow down and classify some of the issues that contribute to that feeling.&lt;/p&gt;

&lt;h3&gt;
  
  
  The friction of setting up a new project
&lt;/h3&gt;

&lt;p&gt;We create a repository, install the dependencies, play around with the configs, then we have to wrap up for the day, never to come back to it. Or worse, we go back to it only to find out all that initial excitement was gone and we would not even know the next step anyway.&lt;/p&gt;

&lt;p&gt;Setting up a new project is time-consuming, and I dropped various projects at this stage.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hard to quickly get feedback on something
&lt;/h3&gt;

&lt;p&gt;Given that I would have everything set up, another painful part was sharing progress with someone. How do I deploy my project? Everybody is using &lt;a href="https://jamstack.org/"&gt;JAMStack&lt;/a&gt; now... or maybe &lt;a href="https://aws.amazon.com/"&gt;AWS&lt;/a&gt;... I used &lt;a href="https://www.heroku.com/"&gt;Heroku&lt;/a&gt; before... &lt;em&gt;Damn&lt;/em&gt;, I just wanted to show that to a friend. 😕&lt;/p&gt;

&lt;p&gt;Sharing work in progress can be overwhelming, indeed, from choosing the "right" option to configuring everything properly. There is a lot to cover.&lt;/p&gt;

&lt;h3&gt;
  
  
  The undefined scope
&lt;/h3&gt;

&lt;p&gt;Most of the times, I start the project without much of a plan. Frequently I would find myself doing a lot at the same time (frontend, backend, hosting) without a clear strategy and boundaries around it. So I always felt I was not getting any closer to the "end".&lt;/p&gt;

&lt;p&gt;The point is: there is no "end" unless &lt;strong&gt;you&lt;/strong&gt; define it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/Fd0rrjTJ3yLDi/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/Fd0rrjTJ3yLDi/giphy.gif" alt="infinity loop!"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Speeding up the setup and feedback loop
&lt;/h2&gt;

&lt;p&gt;When I have a short time to try out something I do not want to bother that much about the settings and the infrastructure unless those are the targets of my study. I'll be probably interested in application code.&lt;/p&gt;

&lt;p&gt;One thing that is helping me a lot is to use &lt;a href="https://codesandbox.io/dashboard/recent"&gt;CodeSandBox&lt;/a&gt; more and more. Whenever I have an idea that I can try out by creating a sandbox, I do. I open up a new tab in the browser, select a template and start coding.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/do6sy"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;The app is fantastic, and you can choose from a wide variety of templates from GraphQL Apollo Server to Svelte. It optimises my time, so I get to focus on coding. I've been way more productive that way. 😊&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I do not lose time creating the repository, installing dependencies, opening an editor, tweaking configs. It's all already there in a minute.&lt;/li&gt;
&lt;li&gt;I can share the sandbox links with anyone  🎉. There is both the editor and the app view available to share. I got rid off thinking about deploying.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Plus it has a lot of other benefits:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connect to GitHub and create a repository from the sandbox.&lt;/li&gt;
&lt;li&gt;Deploy to Netlify and Vercel.&lt;/li&gt;
&lt;li&gt;Invite others to edit a sandbox live with you.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If your side project cannot live in a Codesandbox, you can still leverage tools and services. Maybe there are boilerplates that you could use. You may expose your localhost application with &lt;a href="https://ngrok.com/"&gt;Ngrok&lt;/a&gt;. Perhaps deploy to &lt;a href="https://devcenter.heroku.com/articles/git"&gt;Heroku&lt;/a&gt; using its cli. You can even deploy to &lt;a href="https://github.com/apps/netlify"&gt;Netlify&lt;/a&gt; or &lt;a href="https://vercel.com/docs/v2/git-integrations/vercel-for-github"&gt;Vercel&lt;/a&gt; using their GitHub integrations. And many more.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining the undefined scope
&lt;/h2&gt;

&lt;p&gt;Done is better than perfect. Although it may sound a bit cliche, it is true. Getting something working helps you to build a sense of &lt;strong&gt;fulfilment&lt;/strong&gt;, &lt;strong&gt;happiness&lt;/strong&gt;, and why not &lt;strong&gt;relief&lt;/strong&gt; about achieving the goal.&lt;/p&gt;

&lt;p&gt;If I'm working on something in the sandbox or not, it does not matter. I realised I needed to plan to get more things done. Then I started to figure out the necessary work and set specific objectives. &lt;/p&gt;

&lt;p&gt;In my method, I write down small enough pieces of work that I could tackle at once. They may require half an hour, an hour, or more, as long as I can understand the time they might take &lt;em&gt;it's okay&lt;/em&gt;. That way, whenever I have spare time to work on something, I try to pick the piece of work that fits.&lt;/p&gt;

&lt;p&gt;It's not always easy to understand the chunks of work, and that is precisely why it is so important to plan. You have the opportunity to search first, look for tutorials, read docs, and you get to learn before doing it!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--fKWLsH1D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1tw2pcyatxxsat4jlqoi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--fKWLsH1D--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/1tw2pcyatxxsat4jlqoi.png" alt="todo-list of side projects"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've been using a todo-list at the moment (on &lt;a href="https://www.notion.so/"&gt;Notion&lt;/a&gt;), and the best part is that it is working! The way you decide to organise that list is always up to you. You may use a &lt;a href="https://trello.com/"&gt;Trello&lt;/a&gt; board, notepads, post-its in your workstation, or even nothing at all if that's not your style. Find the tool that you are comfortable using, and that can do the job. &lt;/p&gt;

&lt;p&gt;It all narrows down to &lt;strong&gt;planning&lt;/strong&gt;. Although it may sound too much for a side project, if you can spend some time thinking about it before doing it, you will probably be more productive. &lt;/p&gt;

&lt;p&gt;I've noticed some improvements after applying these techniques:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I'm happier because I'm always &lt;strong&gt;moving forward&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;I know things that I could do in &lt;strong&gt;10min&lt;/strong&gt; if I want to.&lt;/li&gt;
&lt;li&gt;I have a clear picture of all projects in progress and their &lt;strong&gt;next steps&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;I got to practice more &lt;strong&gt;breaking things down&lt;/strong&gt; into smaller units of work.&lt;/li&gt;
&lt;li&gt;I now realise ahead of time if the project is what I actually &lt;strong&gt;want&lt;/strong&gt; to do.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/pT4pmRFs15Yg8/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/pT4pmRFs15Yg8/giphy.gif" alt="jim carrey typing a lot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusions
&lt;/h2&gt;

&lt;p&gt;Being more &lt;strong&gt;intentional&lt;/strong&gt; in planning and using tools that I am comfortable with is what is making the difference to me. The way I look and approach my side projects is different now. The techniques I use to tackle them can help you too, but you may find your unique routines as well! 🥳&lt;/p&gt;

&lt;p&gt;So, what are your big frustrations with side projects? How are you overcoming them? Thoughts, ideas and suggestions are always welcome.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Cover by &lt;a href="https://unsplash.com/photos/IUY_3DvM__w"&gt;Matt Duncan on Unsplash&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>productivity</category>
      <category>sideprojects</category>
      <category>career</category>
      <category>learning</category>
    </item>
    <item>
      <title>Loading a directory as a tree structure in Node</title>
      <dc:creator>Rafael Nunes</dc:creator>
      <pubDate>Mon, 08 Jun 2020 11:36:08 +0000</pubDate>
      <link>https://dev.to/peaonunes/loading-a-directory-as-a-tree-structure-in-node-52bg</link>
      <guid>https://dev.to/peaonunes/loading-a-directory-as-a-tree-structure-in-node-52bg</guid>
      <description>&lt;p&gt;Hey you all 👋! This article is the first follow up on &lt;code&gt;JSCity&lt;/code&gt; series. If you haven't read it yet, feel free to check it out in the post bellow:&lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/peaonunes" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F160426%2F4f840e90-65e6-482b-9538-e9e834cd2577.jpeg" alt="peaonunes"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/peaonunes/jscity-visualizing-javascript-code-5cej" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;JSCity visualizing JavaScript code&lt;/h2&gt;
      &lt;h3&gt;Rafael Nunes ・ May 31 '20&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#react&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#reactthreefiber&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#threejs&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#visualization&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;In this post we will explore:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Loading directories using &lt;code&gt;node&lt;/code&gt; APIs.&lt;/li&gt;
&lt;li&gt;Building a tree structure that represents the directories loaded.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://en.wikipedia.org/wiki/Test-driven_development" rel="noopener noreferrer"&gt;Test driven development&lt;/a&gt; to define the expectations around the output before implementing the code.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While in the MVP of &lt;code&gt;JSCity&lt;/code&gt; all the processing happens in the browser (file upload, code parsing, visualization), for the second version I'm aiming to create modular packages, with the intention of increasing re-usability of these modules for future versions.&lt;/p&gt;

&lt;p&gt;In this post, we'll be building the module that loads a local directory into a well-defined structure. The objective is to be able to export it as function of a package later.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I took this opportunity to use Typescript, but you can achieve the same goal with vanilla JavaScript.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Defining the structure
&lt;/h2&gt;

&lt;p&gt;Directories in operating systems are displayed and represented in a hierarchical &lt;a href="https://en.wikipedia.org/wiki/Tree_structure" rel="noopener noreferrer"&gt;tree structure&lt;/a&gt;. The &lt;a href="https://en.wikipedia.org/wiki/Tree_(data_structure)" rel="noopener noreferrer"&gt;tree data structure&lt;/a&gt; is widely used to represent and traverse data efficiently. &lt;/p&gt;

&lt;p&gt;The elements in a tree are called nodes and edges. A node contains some piece information, in our case information about the file or directory. In the following image, the arrows between the nodes are what we call edges.&lt;/p&gt;

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

&lt;p&gt;Nodes without children are often called leaf nodes and the highest node in a tree is called the root node.&lt;/p&gt;

&lt;p&gt;There are multiple well known algorithms to traverse a tree. These will facilitate the process of building the city. So how can we make that directory tree in &lt;code&gt;node&lt;/code&gt;?&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;node&lt;/code&gt; &lt;a href="https://nodejs.org/api/fs.html#fs_file_system" rel="noopener noreferrer"&gt;file system API&lt;/a&gt; allows us to read any directory with &lt;code&gt;fs.readdirSync&lt;/code&gt;, for example. It returns the array of strings representing the subfolders and files of that folder.&lt;/p&gt;

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

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialPath&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="c1"&gt;// [ 'example.js', 'utils' ]&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;We can then leverage this to build our own tree structure!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I did find &lt;a href="https://github.com/mihneadb/node-directory-tree" rel="noopener noreferrer"&gt;node-directory-tree&lt;/a&gt; package that does that for us. Despite that, I believe it is a good exercise to build the tree by ourselves.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To represent a node I decided to create the &lt;code&gt;TreeNode&lt;/code&gt; class. The properties of a &lt;code&gt;TreeNode&lt;/code&gt; are the path in the file system and an array of &lt;code&gt;TreeNode&lt;/code&gt; (representing the sub-directories and files). When &lt;code&gt;TreeNode&lt;/code&gt; is a file the &lt;code&gt;children&lt;/code&gt; array will remain empty just like the leaf nodes we learned before.&lt;/p&gt;

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

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TreeNode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;TreeNode&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;constructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&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;children&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="p"&gt;}&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;That's a good enough first version of our tree nodes. Let's keep going.&lt;/p&gt;

&lt;h2&gt;
  
  
  Defining the root node
&lt;/h2&gt;

&lt;p&gt;Now let's create some tests!&lt;/p&gt;

&lt;p&gt;I will use a folder called &lt;code&gt;fixtures&lt;/code&gt; as the input of our tests. That folder contains just some example files.&lt;/p&gt;

&lt;p&gt;So given an initial path, we want it to return the &lt;code&gt;root&lt;/code&gt; node representing that directory. We want to assert that the &lt;code&gt;root&lt;/code&gt; contains the expected properties.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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;buildTree&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;initialPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fixtures&lt;/span&gt;&lt;span class="dl"&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 root node&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;rootNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;buildTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialPath&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;rootNode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBeNull&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;rootNode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;initialPath&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;rootNode&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toHaveProperty&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;children&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;For now this test will fail, but that's expected. We still need to build the function mentioned in the code above.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;buildTree&lt;/code&gt; function receives a path as input and returns the tree structure for that directory.&lt;/p&gt;

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

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TreeNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootPath&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;That is enough to get our first test to pass ✅🎉&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Reading the folder and its children
&lt;/h2&gt;

&lt;p&gt;We can see that the &lt;code&gt;buildTree&lt;/code&gt; function does not really build the full tree structure yet. That's our next step. The &lt;code&gt;fixtures&lt;/code&gt; folder used by our test looks like the following.&lt;/p&gt;

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

fixtures
├── example.js
└── utils
   └── sum.js


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

&lt;/div&gt;

&lt;p&gt;The output of the function should represent the following tree.&lt;/p&gt;

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

&lt;p&gt;We can assert that the &lt;code&gt;root&lt;/code&gt;, in our case &lt;code&gt;fixtures&lt;/code&gt;, has two  children: &lt;code&gt;utils&lt;/code&gt; folder and &lt;code&gt;example.js&lt;/code&gt; file.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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 return root node with its exact 2 children&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;rootNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;buildTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialPath&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;rootNode&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="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&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;childrenPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rootNode&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="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;child&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;childrenPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&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;initialPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/utils`&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&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;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;childrenPath&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&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;initialPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/example.js`&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&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="p"&gt;});&lt;/span&gt;


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

&lt;/div&gt;

&lt;p&gt;We can also assert that &lt;code&gt;utils&lt;/code&gt; folder has the &lt;code&gt;sum.js&lt;/code&gt; file inside of it.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&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 add utils node with its children inside root&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;rootNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;buildTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;initialPath&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;utils&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;rootNode&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="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;child&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;child&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&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;initialPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/utils`&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;utils&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;not&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toBeNull&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;utils&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="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;utils&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="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]?.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toEqual&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;initialPath&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/utils/sum.js`&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;And of course, they are going to fail at this point.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkz48f0h1g9ajd0gikne4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkz48f0h1g9ajd0gikne4.png" alt="failed tests of buildTree function"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the tree
&lt;/h3&gt;

&lt;p&gt;We now need to extend &lt;code&gt;buildTree&lt;/code&gt; so it builds the entire tree, not only the root node.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://en.wikipedia.org/wiki/Depth-first_search" rel="noopener noreferrer"&gt;Depth-first search aka DFS&lt;/a&gt; algorithm is a well-known technique to traverse a tree. In the iterative DFS algorithm we will need to use a &lt;a href="https://en.wikipedia.org/wiki/Stack_(abstract_data_type)" rel="noopener noreferrer"&gt;Stack&lt;/a&gt;, which has the first-in-last-out (FILO) approach. &lt;/p&gt;

&lt;p&gt;With DFS, our step by step looks like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;We first add the &lt;code&gt;root&lt;/code&gt; to the stack.&lt;/li&gt;
&lt;li&gt;We loop while the stack is not empty (that means we still have nodes to visit).&lt;/li&gt;
&lt;li&gt;We &lt;code&gt;pop&lt;/code&gt; an item from the stack to be our new &lt;code&gt;currentNode&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We use &lt;code&gt;fs.readdirSync(currentNode.path)&lt;/code&gt; to get the node's sub-directories and files.&lt;/li&gt;
&lt;li&gt;For each one of them, we create a node and add it to the &lt;code&gt;currentNode.children&lt;/code&gt; array. If it's a directory we also &lt;code&gt;push&lt;/code&gt; it in the stack to visit it later.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2jbbdahr6y45si4hcp72.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2jbbdahr6y45si4hcp72.gif" alt="animated gif of the build algorithm"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the end, we've visited all the directories, files and sub-directories and built our tree. The implementation looks like the this:&lt;/p&gt;

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

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;buildTree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;root&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TreeNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;rootPath&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;stack&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="k"&gt;while &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&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;currentNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pop&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="nx"&gt;currentNode&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;children&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

      &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;child&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;childPath&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;currentNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;child&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;const&lt;/span&gt; &lt;span class="nx"&gt;childNode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TreeNode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;childPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;currentNode&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="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;childNode&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="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;statSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;childNode&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;isDirectory&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;childNode&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;root&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 used &lt;code&gt;fs.readdirSync&lt;/code&gt; as before to discover the children of a folder. We also used &lt;code&gt;fs.statSync&lt;/code&gt; to read the stats of the current path, it allows us to ask whether or not that child I'm looking at is a directory.&lt;/p&gt;

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

&lt;p&gt;Green tests, yay 🙌, we have solved the problem of building the tree structure! When we log our &lt;code&gt;root&lt;/code&gt; we are able to see its properties.&lt;/p&gt;


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

&lt;p&gt;&lt;span class="nx"&gt;TreeNode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
  &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test/fixtures&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br&gt;
  &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;br&gt;
    &lt;span class="nx"&gt;TreeNode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
      &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test/fixtures/example.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br&gt;
      &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;br&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;&lt;br&gt;
    &lt;span class="nx"&gt;TreeNode&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;br&gt;
      &lt;span class="nl"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;test/fixtures/utils&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;br&gt;
      &lt;span class="nx"&gt;children&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;br&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;&lt;br&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;&lt;br&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;/p&gt;

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

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  What's next?&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;We got the desired output, but there is more we could do. For example, we can add a filter to exclude files of certain extension from our tree. I'll do that since I want to visualize &lt;code&gt;.js&lt;/code&gt; files only.&lt;/p&gt;

&lt;p&gt;There is also the possibility of adding properties like &lt;code&gt;type&lt;/code&gt;, &lt;code&gt;extension&lt;/code&gt;, &lt;code&gt;size&lt;/code&gt; (...) to our &lt;code&gt;TreeNode&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;The next chapter will leverage this newly created structure to parse every &lt;code&gt;JavaScript&lt;/code&gt; file in it and compute metrics about the code!&lt;/p&gt;

&lt;p&gt;Was this post useful to you? I'm always keen to hear suggestions and comments. 👋&lt;/p&gt;

</description>
      <category>node</category>
      <category>tree</category>
      <category>javascript</category>
      <category>fs</category>
    </item>
    <item>
      <title>JSCity visualizing JavaScript code</title>
      <dc:creator>Rafael Nunes</dc:creator>
      <pubDate>Sun, 31 May 2020 12:53:37 +0000</pubDate>
      <link>https://dev.to/peaonunes/jscity-visualizing-javascript-code-5cej</link>
      <guid>https://dev.to/peaonunes/jscity-visualizing-javascript-code-5cej</guid>
      <description>&lt;p&gt;This is the very first article that talks about the &lt;strong&gt;idea&lt;/strong&gt;,  &lt;strong&gt;motivation&lt;/strong&gt; and the &lt;strong&gt;mvp&lt;/strong&gt; of &lt;a href="https://github.com/peaonunes/jscity" rel="noopener noreferrer"&gt;JSCity&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;I learned a lot while doing it and hopefully you will also find something interesting to take out of it as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  react-three-fiber
&lt;/h2&gt;

&lt;p&gt;So, late last year I started creating &lt;a href="https://github.com/peaonunes/jscity" rel="noopener noreferrer"&gt;JSCity&lt;/a&gt;. The ultimate goal was to visualize JavaScript projects as cities. But why?&lt;/p&gt;

&lt;p&gt;It all started when I saw the following &lt;a href="https://twitter.com/0xca0a/status/1184586883520761856" rel="noopener noreferrer"&gt;tweet&lt;/a&gt; by &lt;a href="https://twitter.com/0xca0a" rel="noopener noreferrer"&gt;Paul Henschel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1184586883520761856-965" src="https://platform.twitter.com/embed/Tweet.html?id=1184586883520761856"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1184586883520761856-965');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1184586883520761856&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;My reaction was: "&lt;em&gt;Wow! That's really cool and it's built with &lt;code&gt;React&lt;/code&gt;, how?!&lt;/em&gt;"&lt;/p&gt;

&lt;p&gt;The answer was &lt;a href="https://github.com/react-spring/react-three-fiber" rel="noopener noreferrer"&gt;react-three-fiber&lt;/a&gt;. I was amazed by the project 🤯. It is a &lt;code&gt;React&lt;/code&gt; &lt;a href="https://reactjs.org/docs/reconciliation.html" rel="noopener noreferrer"&gt;reconciler&lt;/a&gt; for &lt;a href="https://threejs.org/" rel="noopener noreferrer"&gt;Threejs&lt;/a&gt;, and I got really curious to see what it does.&lt;/p&gt;

&lt;p&gt;On one side there is &lt;code&gt;React&lt;/code&gt;, a very popular and robust library to build UIs.  Because of its declarative nature &lt;code&gt;React&lt;/code&gt; is really good for a lot of things and the community is always pushing the ecosystem forward.&lt;/p&gt;

&lt;p&gt;On the other side, there is &lt;code&gt;Threejs&lt;/code&gt;, the most popular 3D library for &lt;code&gt;JavaScript&lt;/code&gt; with a very powerful and rich API.&lt;/p&gt;

&lt;p&gt;Although it is very possible to combine them together the &lt;code&gt;Threejs&lt;/code&gt; imperative nature makes that a non-trivial work. For example, synchronizing &lt;code&gt;React&lt;/code&gt; state with the 3D canvas can be painful.&lt;/p&gt;

&lt;p&gt;Now let's take checkout this &lt;a href="https://codesandbox.io/s/rrppl0y8l4?file=/src/index.js" rel="noopener noreferrer"&gt;sandbox&lt;/a&gt;. Feel free to play around with it.&lt;/p&gt;

&lt;p&gt;&lt;iframe src="https://codesandbox.io/embed/rrppl0y8l4?view=split"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;code&gt;react-three-fiber&lt;/code&gt; builds the bridge between the composable and declarative &lt;code&gt;React&lt;/code&gt; nature and the powerful API from &lt;code&gt;Threejs&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A lot of initial setup and complexity is abstracted. However, the main part is that it exposes a very good &lt;a href="https://github.com/react-spring/react-three-fiber/blob/master/api.md" rel="noopener noreferrer"&gt;API&lt;/a&gt;, handy hooks and maps objects from &lt;code&gt;Threejs&lt;/code&gt; to &lt;code&gt;React&lt;/code&gt; components. &lt;/p&gt;

&lt;p&gt;Now we can leverage of the best of these two different universes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Matching an intention with an idea
&lt;/h2&gt;

&lt;p&gt;I immediately wanted to try it. But what should I do?&lt;/p&gt;

&lt;p&gt;I made a few examples using &lt;code&gt;react-three-fiber&lt;/code&gt; on &lt;a href="https://codesandbox.io" rel="noopener noreferrer"&gt;CodeSandbox&lt;/a&gt;, but I wanted to continually explore and build something bigger.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/LlLPJYt7pgolgHLcmq/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/LlLPJYt7pgolgHLcmq/giphy.gif" alt="idea conception"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've used &lt;code&gt;Threejs&lt;/code&gt; in the past to build a project called &lt;a href="https://swiftcity.github.io/" rel="noopener noreferrer"&gt;SwiftCity&lt;/a&gt; (no longer maintained) - a visualizer of Swift code. Then it clicked 💡! I can bring that same idea of visualizing code as cities, but this time applying to JavaScript universe.&lt;/p&gt;

&lt;p&gt;I would also be able to explore some other interesting topics like &lt;code&gt;react-three-fiber&lt;/code&gt;, &lt;a href="https://en.wikipedia.org/wiki/Abstract_syntax_tree" rel="noopener noreferrer"&gt;ASTs&lt;/a&gt;, &lt;code&gt;babel&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;Besides, 3D things are so cool, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  JSCity
&lt;/h2&gt;

&lt;p&gt;So JSCity idea came to visualize JavaScript code as cities. My intention was to build a &lt;strong&gt;demo&lt;/strong&gt; to get a sense of how that would look like.&lt;/p&gt;

&lt;h3&gt;
  
  
  Explaining "The City Metaphor"
&lt;/h3&gt;

&lt;p&gt;To summarize, the idea behind &lt;a href="https://www.inf.usi.ch/faculty/lanza/Downloads/Wett07b.pdf" rel="noopener noreferrer"&gt;City Metaphor&lt;/a&gt; is to analyze and view software systems as cities. The key point is to explore and understand the complexity of a system by mapping the source code to a city.&lt;/p&gt;

&lt;h3&gt;
  
  
  The concepts
&lt;/h3&gt;

&lt;p&gt;Before rushing to implement the MVP we have to define how to translate JavaScript code into a city. For example, cities have buildings, right? And also blocks. So here are the building blocks that I've chosen for our city:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What piece of code does a &lt;strong&gt;building&lt;/strong&gt; represent?&lt;/li&gt;
&lt;li&gt;How do we define the dimensions of a building (width, height and length) ?&lt;/li&gt;
&lt;li&gt;How do we show the code hierarchy as areas of a city?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl799qkw4ksnexcgmz6pe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fl799qkw4ksnexcgmz6pe.png" alt="Azures City Topology from Visualizing Software Systems as Cities"&gt;&lt;/a&gt;&lt;/p&gt;
Azures City Topology from Visualizing Software Systems as Cities



&lt;h4&gt;
  
  
  The buildings in the city
&lt;/h4&gt;

&lt;p&gt;In the original metaphor, a building was mapped to represent a Java class. However, various elements can own a lot of responsibilities in JavaScript.&lt;/p&gt;

&lt;p&gt;For instance, the buildings could be Functions, Classes, Objects, etc. Beyond that, functions might appear as &lt;a href="https://developer.mozilla.org/en-US/docs/Glossary/IIFE" rel="noopener noreferrer"&gt;IFFEs&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions" rel="noopener noreferrer"&gt;arrow functions&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures" rel="noopener noreferrer"&gt;closures&lt;/a&gt;, &lt;a href="https://developer.mozilla.org/en-US/docs/web/JavaScript/Reference/Operators/function" rel="noopener noreferrer"&gt;function expressions&lt;/a&gt; and more.&lt;/p&gt;

&lt;p&gt;I decided then to &lt;strong&gt;only consider&lt;/strong&gt; &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions" rel="noopener noreferrer"&gt;simple function definitions&lt;/a&gt; and its clojures for the purpose of the demo.&lt;/p&gt;

&lt;h4&gt;
  
  
  Dimensions
&lt;/h4&gt;

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

&lt;p&gt;Several metrics can be taken to define the measurements of a building. I decided that the building &lt;strong&gt;height&lt;/strong&gt; would be given by the &lt;strong&gt;number of lines of code&lt;/strong&gt; of the analyzed function. The &lt;strong&gt;width and length&lt;/strong&gt; then would be defined by the amount of &lt;strong&gt;calls to other functions&lt;/strong&gt; inside the examined function.&lt;/p&gt;

&lt;h4&gt;
  
  
  Topology
&lt;/h4&gt;

&lt;p&gt;The city topology is mapped to elements of the system hierarchy.&lt;/p&gt;

&lt;p&gt;Since there are no packages, namespaces or anything equivalent in JavaScript, the mapping will limit to the following levels: the &lt;strong&gt;project&lt;/strong&gt;, &lt;strong&gt;directories&lt;/strong&gt; and the &lt;strong&gt;files&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;calculate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;text&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;minus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
  &lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;minus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;times&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;b&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="nx"&gt;a&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;b&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;The code above would look something like this:&lt;/p&gt;

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

&lt;p&gt;Function definitions that belong to a file will appear inside the file limits. In the image above, the light grey area represents a file and its functions are the buildings.&lt;/p&gt;

&lt;p&gt;Function declarations that are declared inside another function (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures" rel="noopener noreferrer"&gt;clojures&lt;/a&gt;) will have their own block stacked on top of the building that represents their parent function. We can see that the largest building represents a function that has a clojure inside of it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building the MVP
&lt;/h3&gt;

&lt;p&gt;Even having previous experience with the concept and knowing more or less what I would need to build, I still wanted to keep it minimal at first.&lt;/p&gt;

&lt;p&gt;I &lt;strong&gt;will not go&lt;/strong&gt; into implementations details here. But do not worry! The next posts will be really focused on exploring every part.&lt;/p&gt;

&lt;p&gt;In summary, the steps that I took were:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Created functions where I could read the content of a JavaScript file and parse it to get its &lt;code&gt;AST&lt;/code&gt;. For that I've used &lt;a href="https://babeljs.io/docs/en/babel-parser" rel="noopener noreferrer"&gt;babel-parser&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Coded something to navigate the &lt;code&gt;AST&lt;/code&gt; and collect the necessary data from the functions. Instead of using tools like &lt;a href="https://babeljs.io/docs/en/babel-traverse" rel="noopener noreferrer"&gt;babel-traverse&lt;/a&gt; for this, I actually implemented it myself (and I regret it 😅)!&lt;/li&gt;
&lt;li&gt;Implemented an algorithm to create the city grid and place the buildings in the right place from scratch. Although I still have the code from SwiftCity, I can barely understand it anymore 😬.&lt;/li&gt;
&lt;li&gt;Used &lt;code&gt;react-three-fiber&lt;/code&gt; to read the city definition and to render the city.&lt;/li&gt;
&lt;li&gt;Used &lt;code&gt;React&lt;/code&gt;to build the app and handle the input file that would be imported.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  The first version
&lt;/h3&gt;

&lt;p&gt;I made it in the end 🎉! The live version is available at &lt;a href="https://peaonunes.github.io/jscity/" rel="noopener noreferrer"&gt;JSCity&lt;/a&gt; and the code is on &lt;a href="https://github.com/peaonunes/jscity" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; as well.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1202165153866715136-242" src="https://platform.twitter.com/embed/Tweet.html?id=1202165153866715136"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1202165153866715136-242');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1202165153866715136&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;There is a lot that this first version does not cope with. For example, as I opt in to just consider function definitions a lot of modern JavaScript code will not be represented. One example is functions defined using the the arrow notation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Some conclusions
&lt;/h3&gt;

&lt;p&gt;I got inspired and could not rest until trying out &lt;code&gt;react-three-fiber&lt;/code&gt;. All because of a tweet. And that is a lesson to me:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Share your work whatever that is. It may inspire someone.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;My initial intention was to focus on experimenting with 3D through &lt;code&gt;react-three-fiber&lt;/code&gt;, but what ended up happening was me spending most of the time trying to get a good enough city creation algorithm... That was hard! Another lesson here was:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Choose a project that will let you focus on what you want to learn.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Nonetheless, it was really fun to build it: I got to play around with other nice tools like &lt;code&gt;babel-parser&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/ifYxDMBr1XP8hQvPeY/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/ifYxDMBr1XP8hQvPeY/giphy.gif" alt="giving magic stick"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What is next?
&lt;/h2&gt;

&lt;p&gt;I got it working. Now I want to make it better.&lt;/p&gt;

&lt;p&gt;The code is very limited and fragile at the moment. I want to extend JSCity and be able to load a directory and build the entire city from that. &lt;/p&gt;

&lt;p&gt;From now on I will be diving deep into each part of the implementation one at the time. I'll be sharing it through posts and I hope some of these things are interesting to someone else too!&lt;/p&gt;

&lt;p&gt;Let me know what do you think about the idea. Thoughts, suggestions and comments are always welcome. See you in the next chapter.&lt;/p&gt;

</description>
      <category>react</category>
      <category>reactthreefiber</category>
      <category>threejs</category>
      <category>visualization</category>
    </item>
    <item>
      <title>Feature Flag approach with GraphQL and React 🕹</title>
      <dc:creator>Rafael Nunes</dc:creator>
      <pubDate>Mon, 25 May 2020 03:51:35 +0000</pubDate>
      <link>https://dev.to/open-graphql/feature-flag-approach-with-graphql-and-react-3l5o</link>
      <guid>https://dev.to/open-graphql/feature-flag-approach-with-graphql-and-react-3l5o</guid>
      <description>&lt;p&gt;&lt;a href="https://martinfowler.com/articles/feature-toggles.html"&gt;Feature flag&lt;/a&gt; (or feature toggle, feature switch…) comes with different shapes and implementations, however, is a well known and powerful technique for allowing teams to modify system behaviour without changing code.&lt;/p&gt;

&lt;p&gt;The idea is to be able to enable or disable features during execution time without any deploy. That is a powerful tool with &lt;a href="https://github.com/search?q=feature+flag"&gt;various&lt;/a&gt; implementations across different languages, the applications are many: A/B testing, toggle app configuration, delivery new features gradually, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Storage
&lt;/h2&gt;

&lt;p&gt;While having feature flags is very handy they introduce complexity starting by the management of the flags. That is one of the reasons why you will find managed services like Optimizely, Rollout, and others. In addition to the feature, they offer a lot more like analytics, and targeting.&lt;/p&gt;

&lt;p&gt;It does not mean that you need a third-party app or integration to start using feature flags. In fact, every tool and approach should be considered depending on what do you need at the implementation moment.&lt;/p&gt;

&lt;p&gt;You may opt-in for a managed service or manage your own feature flags in your own database as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  API
&lt;/h2&gt;

&lt;p&gt;So once you have decided how to manage the flags we need to expose them in our GraphQL API. The objective is always to strive for making your schema self contained and easy to understand, ideally, it should not reflect the way it is stored in the database (although it can).&lt;/p&gt;

&lt;p&gt;We want to expose the features available for some user, app or instance. A query that provides that information could look like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;enabledFeatures&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Feature&lt;/span&gt;&lt;span class="p"&gt;!]!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Feature&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the schema above, we are defining two important units in our domain, they are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Feature&lt;/code&gt; and &lt;code&gt;enabledFeatures&lt;/code&gt;. &lt;code&gt;Feature&lt;/code&gt; is a representation of the feature you want to switch on and off and it only contains a &lt;code&gt;name&lt;/code&gt; at the moment.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;enabledFeatures&lt;/code&gt; is a query that returns an array of &lt;code&gt;Feature&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We only return the features enabled so whoever is consuming the API does not need to know the entire set of features. The lack of some feature in the array means that the feature is not visible/available.&lt;/p&gt;

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

&lt;blockquote&gt;
&lt;p&gt;Note: In the backend, you can identify the user through headers such as &lt;a href="https://developer.mozilla.org/pt-BR/docs/Web/HTTP/Headers/Authorization"&gt;Authorization&lt;/a&gt; and filter features for that user. Or filter based in any other information in the request, for example, &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/User-Agent"&gt;User Agent&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You can see this schema being served live on this &lt;a href="https://codesandbox.io/s/graphql-feature-flag-7jxju"&gt;API sandbox&lt;/a&gt;. I'm using &lt;a href="https://www.apollographql.com/docs/apollo-server/"&gt;Apollo Server&lt;/a&gt; in the example.&lt;br&gt;
&lt;iframe src="https://codesandbox.io/embed/graphql-feature-flag-7jxju"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Querying
&lt;/h2&gt;

&lt;p&gt;Having the contract defined we are now able to fetch features. You can play around on the playground built in the sandbox example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight graphql"&gt;&lt;code&gt;&lt;span class="k"&gt;query&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="n"&gt;enabledFeatures&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;In the React application, I will be using &lt;a href="https://www.apollographql.com/docs/react/"&gt;Apollo Client&lt;/a&gt; as I'm familiar with the API, but it does not matter the library you use. You can follow along with the implementation of this &lt;a href="https://codesandbox.io/s/feature-flag-client-graphql-4jwpk?file=/src/App.js"&gt;client sandbox&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A component that queries all the features would look like the following:&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;QUERY&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;gql&lt;/span&gt;&lt;span class="s2"&gt;`
  query {
    enabledFeatures {
      name
    }
  }
`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;BasicQuery&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;QUERY&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="nx"&gt;loading&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;Loading...&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;Error :&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="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="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="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;List of features:&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&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;ul&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enabledFeatures&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;feature&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;li&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&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;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="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&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;p&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;li&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&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;lt;/&lt;/span&gt;&lt;span class="nt"&gt;ul&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;
  &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;Having that is a good start point, right know you already have a way to query all the features and you can make use of it to dynamically turn something on and off. So let's make that.&lt;/p&gt;

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

&lt;h3&gt;
  
  
  useFeatureFlag
&lt;/h3&gt;

&lt;p&gt;I want to guard a component so every time the user hit that part of the code we only render it if the feature is enabled. To avoid writing this logic over and over again I'm going to build a hook (previously I've used &lt;a href="https://reactjs.org/docs/render-props.html"&gt;render props&lt;/a&gt;, but you can also make it a &lt;a href="https://reactjs.org/docs/higher-order-components.html"&gt;HOC&lt;/a&gt; component, you can work with whatever suits you prefer). The hook gets a feature name it checks if that is enabled and returns the status to the caller.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;useFeature&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="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;QUERY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;feature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;error&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="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;data&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;feature&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;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enabledFeatures&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;enabled&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;feature&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;That hook uses the same query we used before and it will return whether or not the passed &lt;code&gt;name&lt;/code&gt; is present in the list of features, as well as loading and error state if you want to handle the intermediate states. We can now use it in any component to switch the render output depending on it.&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;Feature3&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;feature3&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;feature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useFeatureFlag&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enabled&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="kc"&gt;undefined&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;Loading &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;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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;error&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;Error :&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;feature&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;enabled&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;h2&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;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; is enabled.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;h2&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;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; is disabled.&lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nt"&gt;h2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If we have only &lt;code&gt;feature1&lt;/code&gt; and &lt;code&gt;feature2&lt;/code&gt; enabled when querying &lt;code&gt;feature3&lt;/code&gt; we should see the disabled message. Similarly, if we query &lt;code&gt;feature2&lt;/code&gt; or &lt;code&gt;feature1&lt;/code&gt; we should see the enabled message.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  Caching and better UX
&lt;/h2&gt;

&lt;p&gt;Although our &lt;code&gt;useFeatureFlag&lt;/code&gt; is enough to define if a feature is enabled, it queries &lt;code&gt;enabledFeatures&lt;/code&gt; when the component is mounted. Depending on the application and the goal of your flag it can decrease the user experience because the user will have to wait for the query to finish.&lt;/p&gt;

&lt;p&gt;Thankfully &lt;code&gt;Apollo Client&lt;/code&gt; comes by default with an &lt;a href="https://www.google.com/search?client=opera&amp;amp;q=apollo+in+memory+cache&amp;amp;sourceid=opera&amp;amp;ie=UTF-8&amp;amp;oe=UTF-8"&gt;in-memory cache implementation&lt;/a&gt;! Knowing that we deduce the &lt;code&gt;useFeatureFlag&lt;/code&gt; will be slower only on its first execution. After that, the result will be cached. However, we can go further and cache it ahead of time.&lt;/p&gt;

&lt;p&gt;We can implement a pretty similar component to the &lt;code&gt;BasicQuery&lt;/code&gt; what would follow the same principles as &lt;code&gt;useFeatureFlag&lt;/code&gt;, but it is not concerned about any specific feature. It is only worried about querying them and rendering the children.&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;function&lt;/span&gt; &lt;span class="nx"&gt;FeatureFlags&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;children&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;useQuery&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;QUERY&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="nx"&gt;loading&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;Loading...&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="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&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;Error :&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="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Fragment&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="nc"&gt;React&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;Fragment&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You may customize the way you render by ignoring the loading state or error, depending on your needs.&lt;/p&gt;

&lt;p&gt;It works like context providers and you could indeed use the context API to create a provider to share its features and consume them with hooks. But this approach may be good enough as well.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FeatureFlags&lt;/code&gt; could be placed in the top of your component tree or would wrap a portion of your App that can be controlled by the feature flags.&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;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;ApolloProvider&lt;/span&gt; &lt;span class="na"&gt;client=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;client&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;FeatureFlags&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="na"&gt;className=&lt;/span&gt;&lt;span class="s2"&gt;"App"&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;h1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;Hello Feature Flag&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;section&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;BasicQuery&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;section&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;section&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;Feature2&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;section&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;section&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;Feature3&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;section&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;
    &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;FeatureFlags&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;ApolloProvider&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This approach is not sophisticated, however already have some advantages like saving network calls being fired on every &lt;code&gt;useFeatureFlag&lt;/code&gt;. Which also avoids the pending state in every guarded component. The trade-off here is to slow down the overall load in favour of the later dependants rendering way faster.&lt;/p&gt;

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

&lt;p&gt;The cache consistency can be a problem if we change the feature in the backend, but the user already cached the queries. For working around that you may extend the hook to receive a &lt;a href="https://www.apollographql.com/docs/react/api/react-hoc/#optionsfetchpolicy"&gt;fetch policy&lt;/a&gt; option. Apollo allows you to configure the way you interact with the cache and you can opt-in for &lt;code&gt;network-only&lt;/code&gt;, for example. Nevertheless, the in-memory cache only lives until the page is refreshed it might not be that critical depending on your use case.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is next?
&lt;/h2&gt;

&lt;p&gt;That is my initial take when thinking about feature flags with GraphQL. The possibilities are many and as I wrote several times in this article it will depend on your use cases! So make it better work for you.&lt;/p&gt;

&lt;p&gt;In my perception potential extensions would be:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Adding options or variations as a field of &lt;code&gt;Feature&lt;/code&gt;, then you can branch the feature implementation depending on its variation or properties (aka A/B testing).&lt;/li&gt;
&lt;li&gt;Making the components and hooks more generic accepting the query as props to them.&lt;/li&gt;
&lt;li&gt;Adding a new query, &lt;code&gt;featureEnabled&lt;/code&gt; to query the &lt;code&gt;enabled&lt;/code&gt; status by the &lt;code&gt;name&lt;/code&gt; directly from the backend so you do not have to filter it in the client-side.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What is your take on feature flags? 😊🙌🏽&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;cover image by &lt;a href="https://unsplash.com/photos/phkp6WdpnIc"&gt;Mikkel Bech on Unsplash&lt;/a&gt;&lt;/em&gt;&lt;br&gt;
This post is a complete rewrite of &lt;a href="https://medium.com/open-graphql/feature-flag-approach-for-react-using-apollo-client-5bfbd99c6cbd"&gt;feature flag approach for react using apollo client&lt;/a&gt;. I felt it needed an update.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>graphql</category>
      <category>react</category>
      <category>featureflag</category>
      <category>apollo</category>
    </item>
    <item>
      <title>Multiple Apollo Clients in React</title>
      <dc:creator>Rafael Nunes</dc:creator>
      <pubDate>Fri, 09 Aug 2019 01:22:15 +0000</pubDate>
      <link>https://dev.to/open-graphql/multiple-apollo-clients-in-react-3jhh</link>
      <guid>https://dev.to/open-graphql/multiple-apollo-clients-in-react-3jhh</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a review after one year of &lt;a href="https://medium.com/open-graphql/apollo-multiple-clients-with-react-b34b571210a5" rel="noopener noreferrer"&gt;Apollo Multiple Clients with React?&lt;/a&gt;. I took a time to rewrite it, adding community implementation suggestions, Apollo Federation, etc. Realised then that I could share my humble knowledge here as well.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This quick post explains how to use different Apollo clients in the same React application, but in the end, discuss other approaches when working on multiple GraphQL APIs. This is not intended to question the GraphQL philosophy by any means 😝!&lt;/p&gt;

&lt;p&gt;I wrote this because I found myself questioning how could I use multiple clients to query different GraphQL APIs from my React application. It turns out there were lots of issues in Apollo GitHub project, discussing the &lt;strong&gt;need&lt;/strong&gt; and presenting suggested implementations for it.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;TL;DR: passing any ApolloClient instance to Query/Mutation/Subscription components as props works just fine! Check: &lt;a href="https://github.com/peaonunes/apollo-multiple-clients-example" rel="noopener noreferrer"&gt;https://github.com/peaonunes/apollo-multiple-clients-example&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Some links to related issues, discussions, and proposals are listed below. Some of the old proposals indeed were merged and come along old &lt;code&gt;react-apollo&lt;/code&gt; versions. However, the approach to using the Apollo client and querying changed a lot (for better) since 2.1.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/apollographql/react-apollo/pull/481" rel="noopener noreferrer"&gt;https://github.com/apollographql/react-apollo/pull/481&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/apollographql/react-apollo/issues/464" rel="noopener noreferrer"&gt;https://github.com/apollographql/react-apollo/issues/464&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/apollographql/react-apollo/issues/1588" rel="noopener noreferrer"&gt;https://github.com/apollographql/react-apollo/issues/1588&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/apollographql/react-apollo/pull/729" rel="noopener noreferrer"&gt;https://github.com/apollographql/react-apollo/pull/729&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Why would we need multiple Apollo clients?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/apollographql/apollo-client" rel="noopener noreferrer"&gt;Apollo Client&lt;/a&gt; accepts only one &lt;code&gt;client uri&lt;/code&gt; on its initialization, therefore, it is meant to be used with one client at the time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;ApolloClient&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apollo-boost&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApolloClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://48p1r2roz4.sse.codesandbox.io&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;So if in your React application you need to retrieve data from two different GraphQL services, for example, you cannot use the same &lt;code&gt;client&lt;/code&gt; or provider instance.&lt;/p&gt;

&lt;p&gt;In my case specifically, I was just looking for a quick win implementation approach to get data from two GraphQL APIs to validate a solution. I was not worrying too much about schemas collision since the types, cache, state (...) would not overlap.&lt;/p&gt;

&lt;p&gt;In my scenario, it would make sense to have a way of switching clients when querying APIs on Apollo. In the current approach though, you wrap your entire application with the &lt;code&gt;ApolloProvider&lt;/code&gt; component which passes the client for the application through the context.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ApolloProvider&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="s2"&gt;react-apollo&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;ApolloClient&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;apollo-boost&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;render&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="s2"&gt;react-dom&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;React&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;react&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;client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApolloClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
 &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://48p1r2roz4.sse.codesandbox.io&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;ApolloProvider&lt;/span&gt; &lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;client&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;div&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
 &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;h2&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;My&lt;/span&gt; &lt;span class="nx"&gt;first&lt;/span&gt; &lt;span class="nx"&gt;Apollo&lt;/span&gt; &lt;span class="nx"&gt;app&lt;/span&gt; &lt;span class="err"&gt;🚀&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/h2&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/div&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/ApolloProvider&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nf"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;root&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;That actually makes it simple to query data using the &lt;a href="https://www.apollographql.com/docs/react/essentials/queries/" rel="noopener noreferrer"&gt;Query Component&lt;/a&gt;, but it also means that the client provided via context is the only used when querying.&lt;/p&gt;

&lt;h3&gt;
  
  
  ⭐️ First Solution
&lt;/h3&gt;

&lt;p&gt;I spent some time looking through numerous issues and related projects and it turns out that there is a way of overriding the context client for &lt;code&gt;Query&lt;/code&gt; and &lt;code&gt;Mutation&lt;/code&gt; component passing another client through props 🎉 🎉 !&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Update Aug 2019: Although they have changed the implementation it still works. &lt;a href="https://github.com/apollographql/react-apollo/blob/master/packages/components/src/Query.tsx#L17" rel="noopener noreferrer"&gt;https://github.com/apollographql/react-apollo/blob/master/packages/components/src/Query.tsx#L17&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-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;Query&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;anotherClient&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;query&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="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&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="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;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;div&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Query&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 feature is not mentioned in any part of the &lt;a href="https://www.apollographql.com/docs/react/essentials/get-started/" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt;. We can indeed pass any client for the components that they will give preference for the one passed via props order than via context. So we could make:&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="c1"&gt;// ...&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customClient&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ApolloClient&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://other-api/graphql&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;Dogs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onDogSelected&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;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Query&lt;/span&gt; &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;GET_DOGS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;client&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;customClient&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="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;loading&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Loading...&lt;/span&gt;&lt;span class="dl"&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="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s2"&gt;`Error! &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&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="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="nt"&gt;select&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;"dog"&lt;/span&gt; &lt;span class="na"&gt;onChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;onDogSelected&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;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;dogs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dog&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;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;option&lt;/span&gt; &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;dog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;breed&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;dog&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;breed&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;option&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&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;lt;/&lt;/span&gt;&lt;span class="nt"&gt;select&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="si"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="nc"&gt;Query&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I have implemented a runnable example that uses two different clients in this repository: &lt;a href="https://github.com/peaonunes/apollo-multiple-clients-example" rel="noopener noreferrer"&gt;https://github.com/peaonunes/apollo-multiple-clients-example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://i.giphy.com/media/fLyBfKE6A4KKV9gQpa/giphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://i.giphy.com/media/fLyBfKE6A4KKV9gQpa/giphy.gif" title="pei" alt="img alt"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Even though this approach is functional you should keep in mind that you won't have Apollo features running applying for both clients unless you pass the same cache to the clients (that might be a risk in case of schema collision), manage other features will be by your own. Apollo features will get compromised and as the application grows your codebase becomes thicker and development will probably be slower.&lt;/p&gt;

&lt;h1&gt;
  
  
  What would be the ideal approach then?
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Solving the problem in the Frontend
&lt;/h2&gt;

&lt;p&gt;Some people found the original article on medium and beyond discussing the approaches they have come up with their implementations for solving this issue. &lt;/p&gt;

&lt;h3&gt;
  
  
  Community implementations
&lt;/h3&gt;

&lt;p&gt;Michael Duve, wrote &lt;a href="https://www.npmjs.com/package/@titelmedia/react-apollo-multiple-clients" rel="noopener noreferrer"&gt;&lt;code&gt;react-apollo-multiple-clients&lt;/code&gt;&lt;/a&gt; a packaged that allows you to switch between clients. It considers multiple providers and provides you a &lt;code&gt;HOC&lt;/code&gt; component that accepts a client prop to switch to the desired client consumer. &lt;a href="https://medium.com/@dazlious/hey-rafael-your-approach-inspired-me-to-find-a-more-generic-solution-to-the-problem-at-hand-9714a47fabfd" rel="noopener noreferrer"&gt;Discussion&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Paul Grieselhuber, suggested in his &lt;a href="https://www.loudnoises.us/next-js-two-apollo-clients-two-graphql-data-sources-the-easy-way/" rel="noopener noreferrer"&gt;post&lt;/a&gt; a way where everything worked through a single client and allowed you to simply toggle on context to select a &lt;code&gt;uri&lt;/code&gt; where the client will dispatch the requests. You can follow the discussion &lt;a href="https://medium.com/@paulgrieselhuber/while-this-looks-like-a-great-solution-for-data-from-multiple-graphql-sources-and-im-sure-works-4dc4da33d3cf" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Client-side schema stitching
&lt;/h3&gt;

&lt;p&gt;Despite support for server side, it is not common to see people trying to solve the issue right on the client, there are some issues looking for or requesting stitching on client side, &lt;a href="https://github.com/apollographql/graphql-tools/issues/797" rel="noopener noreferrer"&gt;#797&lt;/a&gt; for example.&lt;/p&gt;

&lt;p&gt;The company &lt;a href="https://hasura.io" rel="noopener noreferrer"&gt;Hasura&lt;/a&gt;, though, points out a way of &lt;a href="//blog.hasura.io/client-side-graphql-schema-resolving-and-schema-stitching-f4d8bccc42d2"&gt;client side schema stitching&lt;/a&gt; and it might be sufficient in your case.&lt;/p&gt;




&lt;p&gt;Although I think that these approaches solve the problem I also think they can increase so much the complexity of the frontend application as the application grows. From my point of view, the work should be done on Backend by providing a unique interface for all the different APIs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gateways for Frontends
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://microservices.io/patterns/apigateway.html" rel="noopener noreferrer"&gt;API Gateway&lt;/a&gt; is a known pattern with increasing adoption in our "microservice boom" age. API Gateway is a single interface between the services and clients.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzt7jy3nx55yz9wdm54xj.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzt7jy3nx55yz9wdm54xj.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It seems to be a consensus in the GraphQL world as well that the API Gateway is the way to go on connection with different GraphQL APIs. However sometimes going beyond that, since the Gateway itself can create a GraphQL interface for other &lt;strong&gt;REST&lt;/strong&gt; and &lt;strong&gt;RPC&lt;/strong&gt; APIs.&lt;/p&gt;

&lt;p&gt;The real problem of serving different APIs through a unique gateway is how to manage and orchestrate different schemas.&lt;/p&gt;

&lt;h3&gt;
  
  
  Schema Stitching
&lt;/h3&gt;

&lt;p&gt;The first attempt the Apollo team advocated for was &lt;a href="https://www.apollographql.com/docs/graphql-tools/schema-stitching/" rel="noopener noreferrer"&gt;Schema Stitching&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Schema stitching is the process of creating a single GraphQL schema from multiple underlying GraphQL APIs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.apollographql.com/the-next-generation-of-schema-stitching-2716b3b259c0" rel="noopener noreferrer"&gt;The next generation of schema stitiching&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://codeburst.io/nodejs-graphql-micro-services-using-remote-stitching-7540030a0753" rel="noopener noreferrer"&gt;NodeJS GraphQL Microservices using remote stitching&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After some time of development and feedback from the community this approach was considered fragile and it is now deprecated.&lt;/p&gt;

&lt;h3&gt;
  
  
  Apollo Federation
&lt;/h3&gt;

&lt;p&gt;Apollo recently launched a new concept for solving this problem of managing different schemas through a gateway which is called &lt;a href="https://blog.apollographql.com/apollo-federation-f260cf525d21" rel="noopener noreferrer"&gt;Apollo Federation&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Apollo Federation is our answer for implementing GraphQL in a microservice architecture. It’s designed to replace schema stitching and solve pain points such as coordination, separation of concerns, and brittle gateway code." James Baxley III&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;They have launched the Federation spec before and it already counts with implementations in some languages, &lt;a href="https://github.com/apollographql/apollo-server/tree/master/packages/apollo-gateway" rel="noopener noreferrer"&gt;apollo-gateway&lt;/a&gt;, for example. The idea is to have a gateway that composes the schemas and the federated services can connect with each other through &lt;code&gt;keys&lt;/code&gt; (just like primary keys) and they are also able to &lt;strong&gt;extend&lt;/strong&gt; types. All this just using regular GraphQL spec.&lt;/p&gt;

&lt;p&gt;I recommend taking the time to watch the video below and spend some time playing around with this promising approach.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/lRI0HfXBAm8"&gt;
&lt;/iframe&gt;
&lt;br&gt;
&lt;em&gt;Apollo Federation - A revolutionary architecture for building a distributed graph&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I personally tried it and I am seeing companies working on solutions based on this new approach. It is also notable that there are some challenges and space for other discussions like managing authentication/authorization, how flexible the gateway should be, etc. Hopefully, the Federation get evolving based on feedbacks from the community and companies.&lt;/p&gt;

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

&lt;p&gt;As I mentioned before this post is not about questioning the &lt;strong&gt;right&lt;/strong&gt; way on querying multiple GraphQL APIs, but it is about pointing out approaches that hopefully might be enough for solving the issues of today.&lt;/p&gt;

&lt;p&gt;I think the whole discussion about using API Gateways and managing different GraphQL schemas is just at the beginning and the community will continuously work on better solutions.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I am more than happy to read suggestions and engage discussions so leave your thoughts below.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>react</category>
      <category>apollo</category>
      <category>graphql</category>
      <category>microservices</category>
    </item>
    <item>
      <title>An introduction to the container world with Docker</title>
      <dc:creator>Rafael Nunes</dc:creator>
      <pubDate>Mon, 29 Jul 2019 02:14:41 +0000</pubDate>
      <link>https://dev.to/peaonunes/an-introduction-to-the-container-world-with-docker-37g7</link>
      <guid>https://dev.to/peaonunes/an-introduction-to-the-container-world-with-docker-37g7</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a repost from my 2017 article on &lt;a href="https://medium.com/@peaonunes/an-introduction-to-the-container-world-with-docker-6fd613f6b9c2" rel="noopener noreferrer"&gt;medium&lt;/a&gt;. Although today Docker is substantially more known topic as it was before I think it might be good to let the basic knowledge I shared in this post accessible in the dev.to platform as well. I took the opportunity to update the post and refine it though. So if you are new to it, come along and enjoy =)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  An introduction to the container world with Docker
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;What will I achieve?&lt;/strong&gt;  By the end of this article, you will understand the core concepts of Docker, such as images, containers, Dockerfiles, using it along with useful docker commands. And comprehend why it is good for production and development and will be able to run your applications using Dockerfile and Docker Compose.&lt;/p&gt;

&lt;p&gt;At this time you probably heard someone talking or read some article that cites Docker. But what is it all about? Why should I use Docker? And why is it good for both dev and production systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why use containers?
&lt;/h2&gt;

&lt;p&gt;Imagine yourself having two different services (1 and 2) running in the same host machine at &lt;a href="https://aws.amazon.com/free/?sc_channel=PS&amp;amp;sc_campaign=acquisition_BR&amp;amp;sc_publisher=google&amp;amp;sc_medium=english_cloud_computing_b&amp;amp;sc_content=aws_core_e&amp;amp;sc_detail=a.w.s&amp;amp;sc_category=cloud_computing&amp;amp;sc_segment=89108828668&amp;amp;sc_matchtype=e&amp;amp;sc_country=BR&amp;amp;s_kwcid=AL!4422!3!89108828668!e!!g!!a.w.s&amp;amp;ef_id=V3yH-wAABIFQ5XJP:20170501150650:s&amp;amp;all-free-tier.sort-by=item.additionalFields.SortRank&amp;amp;all-free-tier.sort-order=asc" rel="noopener noreferrer"&gt;AWS&lt;/a&gt;, they have the same technology dependency, both is running under the &lt;strong&gt;framework v2&lt;/strong&gt;. Right now you have to upgrade the &lt;strong&gt;service 1&lt;/strong&gt; to the new version &lt;strong&gt;framework v3&lt;/strong&gt;, because it integrates with the monetization platform of your company.&lt;/p&gt;

&lt;p&gt;So you have to enter inside your machine running at AWS using command line tools and now you update the framework! Unfortunately the &lt;strong&gt;service 2&lt;/strong&gt; is not compatible with this new version and everything starts breaking! You can rent another machine on AWS, enter in it, copy all the files of &lt;strong&gt;service 2&lt;/strong&gt; and install the older version of the framework, now it is running fine.&lt;/p&gt;

&lt;p&gt;However, is this mean time the team had another version of the &lt;strong&gt;service 2&lt;/strong&gt; and you just installed the older one because you have copied the wrong code base! The process starts over again! Isn't it getting boring?&lt;/p&gt;

&lt;p&gt;When it comes to provisioning machines and configuring dependencies to run some application there are some options. Tools such as X allows you to write infrastructure as a code and automatically configure and deploy machines and related. We can go beyond that though.&lt;/p&gt;

&lt;p&gt;Using cloud services or not hosting, delivering and running services add some relevant concerns like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How do I guarantee a stable environment for my application?&lt;/li&gt;
&lt;li&gt;How do I manage the environment configuration of my application?&lt;/li&gt;
&lt;li&gt;How do I scale and upgrade my service efficiently?&lt;/li&gt;
&lt;li&gt;How to isolate my service dependencies from the others?&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Containers
&lt;/h2&gt;

&lt;p&gt;Containers are not a new concept, used since early 30's to the actual patent in 1956 by &lt;a href="https://medium.com/r/?url=https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FMalcom_McLean" rel="noopener noreferrer"&gt;Malcom McLean&lt;/a&gt;. The need of shipping different packages of products with different constraints (size, dimension, weight…) came to the standardization of a shipping model called container.&lt;/p&gt;

&lt;p&gt;Metaphors aside, in the software production world we find the same needs. And here comes the Software Container, something that bundles the software product and manages its configuration for shipping.&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%2Fcdn-images-1.medium.com%2Fmax%2F600%2F1%2AIp-5CxcjDNwDuninfBXstA.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%2Fcdn-images-1.medium.com%2Fmax%2F600%2F1%2AIp-5CxcjDNwDuninfBXstA.png" title="docker" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker
&lt;/h2&gt;

&lt;p&gt;Software Container is not a new concept too, but working on it is a hard low-level job for most of the engineers. Docker, however, turns out being a fast, easy to use, and powerful tool for containerization of your software.&lt;/p&gt;

&lt;p&gt;Using Docker you define &lt;strong&gt;images&lt;/strong&gt; which are descriptions of a software environment settings and commands. And from those images, you can run containers which are the actual executable bundle.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does the docker work?
&lt;/h2&gt;

&lt;p&gt;Docker runs under the host system kernel, the containers contains only user space files and all resources, configuration needed, libs, dependencies and executable commands are defined through &lt;strong&gt;images&lt;/strong&gt; which are light and easily adaptable for different purposes.&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%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AZXebwLEaHI_a6Bv9_wdbFw.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%2Fcdn-images-1.medium.com%2Fmax%2F800%2F1%2AZXebwLEaHI_a6Bv9_wdbFw.png" title="docker pipe" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Differently from VM's, Docker does not emulate the entire OS on the host machine and that is why is so light compared to VM. The Docker Engine works like a middleware managing the containers process along the host OS. The containers with Docker only loads the &lt;strong&gt;necessary bins/libs&lt;/strong&gt; (and the app obviously 😛) for your App to run.&lt;/p&gt;

&lt;p&gt;The goods come are notorius when you start using.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Resource efficiency:&lt;/strong&gt; You are able to configure disk space, memory usage, libs and bins to load of your container. Being able to create the lightest and efficient environment for your app.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Compatible:&lt;/strong&gt; Compatible with Linux, Windows and MacOS distributions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Easy to run and fast:&lt;/strong&gt; Easy installation, command line tools use and optimizations of the building and run containers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Software maintenance:&lt;/strong&gt; Release new versions changing the containers and guaranteeing the right environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Scalability:&lt;/strong&gt; Scale your service replicating containers as long as your traffic is heavy and turn some down when it is not so bothered.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Security:&lt;/strong&gt; The containers are isolated from the host machine, so it can't access anything outside its own boundaries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reproducibility:&lt;/strong&gt; The containers are a well defined environment and you can guarantee the same infrastructure over a set of definitions.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Hands on! 🙌🏽
&lt;/h2&gt;

&lt;p&gt;Let's try out using Docker now! Installation: On &lt;a href="https://docs.docker.com/install/" rel="noopener noreferrer"&gt;Install Docker&lt;/a&gt; you will find the instructions for your correct system. There are dist for Mac, Windows and Linux dists.&lt;/p&gt;

&lt;p&gt;Once you have the docker installed and running on your machine jump to your terminal and hit &lt;code&gt;docker -v&lt;/code&gt; for checking your docker version. Now try run the following:&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 -it alpine sh
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command says to docker run in interactive mode, &lt;code&gt;-it&lt;/code&gt; flag, the &lt;a href="https://hub.docker.com/_/alpine" rel="noopener noreferrer"&gt;Linux Alpine&lt;/a&gt; and runs the &lt;code&gt;sh&lt;/code&gt; command. So as you probably does not have the alpine image on your machine the Docker will download it before running.&lt;/p&gt;

&lt;p&gt;If everything went well you should be on the &lt;code&gt;sh shell&lt;/code&gt; mode of the alpine. That’s right, you are on a terminal of a Linux running inside a container in just a few seconds! Try &lt;code&gt;ls&lt;/code&gt; for checking the files and folders.&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%2Fmiro.medium.com%2Fmax%2F700%2F1%2A28BUgCTlWvcfCRFruJeXRQ.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%2Fmiro.medium.com%2Fmax%2F700%2F1%2A28BUgCTlWvcfCRFruJeXRQ.png" title="Your shell" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now type &lt;code&gt;exit&lt;/code&gt; and you are done. You will exit and stop the container.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;strong&gt;Note&lt;/strong&gt;: The Docker was built for Linux and it's now native for Windows too. However, on Mac, it still has to run a VM in the background for emulating the host. It is still much lighter than using VM's for all the job.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Images
&lt;/h2&gt;

&lt;p&gt;You might asked yourself on how does the Docker know about alpine and where did he get it from. The alpine comes from this &lt;a href="https://hub.docker.com/_/alpine/" rel="noopener noreferrer"&gt;repository&lt;/a&gt; on &lt;a href="https://hub.docker.com" rel="noopener noreferrer"&gt;DockerHub&lt;/a&gt;. DockerHub which is a repository of container images. Users and organizations can publish their official docker image of their [software, language, system, OS, …].&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%2Fmiro.medium.com%2Fmax%2F500%2F1%2AC6u7ZD0b5g_cfVvgmCO2dQ.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%2Fmiro.medium.com%2Fmax%2F500%2F1%2AC6u7ZD0b5g_cfVvgmCO2dQ.png" title="dockerhub" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;DockerHub is the GitHub of containers. You can pull some image for starting a containers like you pull some code on GitHub to run. The daemon looks for the image in the host machine, if he does not find it then he looks for the image on the DockerHub.&lt;/p&gt;

&lt;p&gt;Using a &lt;strong&gt;Dockerfile&lt;/strong&gt; you can start from a very basic image definition and create &lt;strong&gt;layers&lt;/strong&gt; over it, describing the next steps of the image execution. Doing that, you can be incremented and adapted to your needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dockerfile
&lt;/h2&gt;

&lt;p&gt;Clone the following code for ease the next steps. &lt;a href="https://github.com/peaonunes/intro-docker-examples" rel="noopener noreferrer"&gt;Download here&lt;/a&gt;. There are two folders holding two different applications one called &lt;strong&gt;node-service&lt;/strong&gt; and the other is &lt;strong&gt;webapp&lt;/strong&gt;. Let's start with webapp, create a new file called Dockerfile at the webapp folder.&lt;/p&gt;

&lt;p&gt;I recommend the reading of the &lt;a href="https://docs.docker.com/engine/reference/builder/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;The first thing we set on a Dockerfile is the starter image from our app. In this case, the &lt;strong&gt;webapp&lt;/strong&gt; is a React application so an environment with Node.js installed is fine for us. Thankfully there is an image on DockerHub for that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:6.3.1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command says that from the starting image &lt;code&gt;node:6.3.1&lt;/code&gt; do the rest. &lt;a href="https://hub.docker.com/_/node/" rel="noopener noreferrer"&gt;This image&lt;/a&gt; contains the Node.js version 6.3.1 installed under a Linux distribution. Let's continue writing down others commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:6.3.1

# Run a command for creating the following path on container
RUN mkdir -p /usr/web-app

# Sets the work directory of our app to be the new path
WORKDIR /usr/web-app

# Copy all files from current directory to the new path in container
COPY . /usr/web-app

# Run the command for installing our node dependencies 
RUN npm install

# Define the command that will execute when the container start
CMD npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that we have our file set. Let's run the application inside the container.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd webapp
$ docker build -t web-app .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It might take some time to download the image of Node Running the &lt;code&gt;build&lt;/code&gt; builds the image based on the Dockerfile present on current (&lt;code&gt;.&lt;/code&gt;) directory. The &lt;code&gt;-t&lt;/code&gt; is a flag for tagging this image and name it &lt;code&gt;web-app&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker images
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your &lt;code&gt;web-app&lt;/code&gt; image should be listed. Now let's run our app!&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 -d --name web-app-container -p 3000:3000 web-app
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The docker run your container in a no interactive mode by the flag &lt;code&gt;d&lt;/code&gt;, it then names your container with &lt;code&gt;--name web-app-container&lt;/code&gt;, and also maps the port using &lt;code&gt;-p&lt;/code&gt; (format is &lt;code&gt;port-on-your-machine:port-on-the-container&lt;/code&gt;). And use our image named &lt;code&gt;web-app&lt;/code&gt; for that. Try to go for your browser on &lt;code&gt;http://localhost:3000&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F500%2F1%2A2sF2r111hPpv7GHyYeyu0A.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%2Fmiro.medium.com%2Fmax%2F500%2F1%2A2sF2r111hPpv7GHyYeyu0A.png" title="its alive!" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The React app is running inside the container on &lt;code&gt;localhost:3000&lt;/code&gt;. This port on the container is mapped to our host machine so we can access the application.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;webapp&lt;/strong&gt; dependes on some data from the &lt;strong&gt;node-service&lt;/strong&gt; so as you can see an error message is displayed on the place for id and name❗️&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker ps
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The command above lists all the containers that are running at the moment, try &lt;code&gt;-a&lt;/code&gt; for display all containers created. Now we can see that it's really running if you aren't sure yet try to stop the container and reload the browser!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker stop &amp;lt;container-id-listed-on-ps&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's move to and start the &lt;strong&gt;node-service&lt;/strong&gt; application. Go to its root folder and create a new Dockerfile for this service. As it is a node application it will be pretty much the same.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:6.3.1

RUN mkdir -p /usr/node-service

WORKDIR /usr/node-service

COPY . /usr/node-service

RUN npm install

CMD npm start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's build and run the &lt;strong&gt;node-service&lt;/strong&gt; container, then reload the &lt;strong&gt;webapp&lt;/strong&gt;!&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ cd ../node-service
$ docker build -t node-service .
$ docker run -d --name node-service-container -p 8080:8080 node-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fmiro.medium.com%2Fmax%2F700%2F1%2AifIjvV1xyyAO7m2sw5Kd5Q.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%2Fmiro.medium.com%2Fmax%2F700%2F1%2AifIjvV1xyyAO7m2sw5Kd5Q.png" title="Yeaaah data!" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Perfect! Your containers are now running and talking to each other! ✅&lt;br&gt;
If for any reason you need to delete an &lt;strong&gt;image&lt;/strong&gt; or a &lt;strong&gt;container&lt;/strong&gt; built use:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Images use &lt;code&gt;$ docker rmi &amp;lt;containerID&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Containers use &lt;code&gt;$ docker rm &amp;lt;containerID&amp;gt;&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It might be useful to run your container in interactive mode to debugging or doing work on the container environment, in this case use &lt;code&gt;-it&lt;/code&gt;  flag on &lt;code&gt;docker run&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;However, if you want to enter in the container on &lt;code&gt;bash&lt;/code&gt;, for example, and your container is already running go for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker exec -it &amp;lt;containerID&amp;gt; bash
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can try all these commands above in the container we just created.&lt;/p&gt;

&lt;p&gt;⭐️ Now you know a little bit of containers using Docker and already ran it for real! That's great! There are only a few more topics that I want to go through.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Right now I recommend you to take a cup of coffee ☕️ and relax before continuing.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Docker Compose
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://docs.docker.com/compose/" rel="noopener noreferrer"&gt;Docker Compose&lt;/a&gt; is a tool that came installed along Docker and is useful on the orchestration of different containers. The point is to let your Composer manage the build and the run all of yours projects.&lt;/p&gt;

&lt;p&gt;Container orchestration is the next level for managing our services lifecyles. We are able to manage and control enumerous things like: Load balancing, Redundancy, Resources allocation, Scale up and down the instances, etc.&lt;/p&gt;

&lt;p&gt;The Docker compose is the defualt format to use along &lt;a href="https://docs.docker.com/engine/swarm" rel="noopener noreferrer"&gt;Docker Swarm&lt;/a&gt; orchestrator.&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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fm6pkbaefw4996fqv5fy9.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%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fm6pkbaefw4996fqv5fy9.png" title="That is probably illustrative. Octopuses probably do not stack containers on whales!" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, we are able to try it in our project that we just made! We just have to create the &lt;code&gt;docker-compose.yml&lt;/code&gt; file!&lt;/p&gt;

&lt;p&gt;Access the root folder &lt;code&gt;intro-docker-examples&lt;/code&gt; of your project and create the &lt;code&gt;docker-compose.yml&lt;/code&gt; file. Let's now configure it properly.&lt;/p&gt;

&lt;p&gt;In this file, you have to define our apps under the services property. We are going to define first the &lt;strong&gt;webapp&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "2"
services:
  webapp:
    build: ./webapp
    ports:
      - "3000:3000"
    depends_on:
      - node-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We defined above the &lt;strong&gt;webapp&lt;/strong&gt; service with the build instruction for build the project folder (it will look for our Dockerfile), the map of the ports as well as we did early in the commands and we are saying that for this service to run it depends on the &lt;strong&gt;node-service&lt;/strong&gt; so the docker compose will run the &lt;strong&gt;node-service&lt;/strong&gt; first for guarantee this dependency.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version: "2"
services:
  node-service:
    build: ./node-service
    ports:
      - "8080:8080"
  webapp:
    build: ./webapp
    ports:
      - "3000:3000"
    depends_on:
      - node-service
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we defined now the &lt;strong&gt;node-service&lt;/strong&gt; as we did for webapp. The version defines the type of the docker compose configuration and this template is related to version 2!&lt;/p&gt;

&lt;p&gt;Stop now the older containers if they are still running and  remove them using the commands I showed you before. And now we could see the Docker Compose building everything again. From the command line on the root folder go for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker-compose up
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create new images for your projects, build the containers and run them on an interactive view. You will now see the logs from the services.&lt;/p&gt;

&lt;p&gt;Access the &lt;code&gt;http://localhost:3000&lt;/code&gt; and check now that everyhing is working fine!&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%2Fmiro.medium.com%2Fmax%2F500%2F1%2ARn0No7dAwANDcFzBry4V-Q.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%2Fmiro.medium.com%2Fmax%2F500%2F1%2ARn0No7dAwANDcFzBry4V-Q.png" title="your containers run like this!" alt="alt text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For stopping the containers go to another tab on your terminal, navigate to the folder and run the command below. It will stop each container in order.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker-compose down 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's great! Everything working fine, but what does will happen if I have to change my Dockerfiles definitions? If you are using the &lt;code&gt;docker-compose&lt;/code&gt; then simply run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker-compose up --build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In case you made editions to your Dockerfile you can use the flag &lt;code&gt;-- build&lt;/code&gt;` to force rebuild the images and containers. The rebuild of any docker container uses &lt;strong&gt;cached steps&lt;/strong&gt; for optimizations. That means the docker only rebuilds the steps from the step changed to the final.&lt;/p&gt;

&lt;p&gt;The final files of this implementation are available &lt;a href="https://github.com/peaonunes/intro-docker-examples/tree/feature/dockerization" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker beyond production
&lt;/h2&gt;

&lt;p&gt;Using Docker for production deployment is a reality and has a lot of benefits. However, using Docker under the development environment is also a good practice.&lt;/p&gt;

&lt;p&gt;Defining the configuration and dependencies of your project on a Dockerfile sets correctly the environment to anyone who is going to work on your project! This &lt;strong&gt;avoid issues&lt;/strong&gt; dependencies related to host and libs versions and allow your the host machine environment to stay clean.&lt;/p&gt;

&lt;p&gt;For example, you can spin up a local database such as postgres or mongodb in a container and make your application locally connect to it instead of having this installed in your computer.&lt;/p&gt;

&lt;p&gt;A good tip for devs is look for &lt;a href="https://docs.docker.com/engine/tutorials/dockervolumes" rel="noopener noreferrer"&gt;volumes&lt;/a&gt;. This creates a channel that enables synchronization between a folder inside the container and the host machine. So if you write your code on the host machine it will be synced to the code in the container.&lt;/p&gt;

&lt;p&gt;Some languages and applications, like in webapps, have the capable of hot reload. So as long as you code from your host machine you can see the changes being compiled and ran into the container. But if your technology does not have this function you can open a terminal tab to enter in the container and recompile/run the project as well.&lt;/p&gt;

&lt;p&gt;You can also use Docker in your &lt;strong&gt;CI/CD&lt;/strong&gt; pipelines building docker images to run test over and publishing them if it is healthy.&lt;/p&gt;

&lt;h2&gt;
  
  
  The end?
&lt;/h2&gt;

&lt;p&gt;Actually it is the beginning of our journey using Docker! There a lot to learn and practice! Look forward more topics and concepts of Docker.&lt;/p&gt;

&lt;p&gt;As &lt;a href="https://kubernetes.io" rel="noopener noreferrer"&gt;Kubernetes&lt;/a&gt; became really popular, is the most popular container orchestrator in the block. The next step for you is definetly explore the endeavors related with container orchertration!&lt;/p&gt;

&lt;p&gt;If this article helped you somehow please leave your appreciation ❤, if it did not fulfill your expectations please send your feedback ✉️ and always share your thoughts in the comment section below 📃!&lt;/p&gt;

&lt;p&gt;See you next time =]&lt;/p&gt;

</description>
      <category>docker</category>
      <category>devops</category>
      <category>microservices</category>
      <category>containers</category>
    </item>
  </channel>
</rss>
