<?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: Antonio Lo Fiego</title>
    <description>The latest articles on DEV Community by Antonio Lo Fiego (@antoniolofiego).</description>
    <link>https://dev.to/antoniolofiego</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%2F444947%2Fe9c0cd81-f910-49cb-b035-a2091c943720.jpeg</url>
      <title>DEV Community: Antonio Lo Fiego</title>
      <link>https://dev.to/antoniolofiego</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/antoniolofiego"/>
    <language>en</language>
    <item>
      <title>Setting up a Next.js Application with TypeScript, JIT Tailwind CSS and Jest/react-testing-library</title>
      <dc:creator>Antonio Lo Fiego</dc:creator>
      <pubDate>Fri, 06 Aug 2021 02:15:47 +0000</pubDate>
      <link>https://dev.to/antoniolofiego/setting-up-a-next-js-application-with-typescript-jit-tailwind-css-and-jest-react-testing-library-1n07</link>
      <guid>https://dev.to/antoniolofiego/setting-up-a-next-js-application-with-typescript-jit-tailwind-css-and-jest-react-testing-library-1n07</guid>
      <description>&lt;p&gt;A few weeks ago, I tweeted about how frustrating of an experience is to set up a Next.js project that includes TypeScript as well as a working testing framework.&lt;/p&gt;


&lt;blockquote&gt;
&lt;p&gt;Setting up a Next.js TS project with Jest and RTL is beyond frustrating. &lt;br&gt;I really can't blame folks who are scared to get into the JS world. It really makes no sense how much confusing extra work you need just to make a testing framework work. I lost hours and got nowhere.&lt;/p&gt;— Antonio Lo Fiego ☁️ (he/him) (@antonio_lofiego) &lt;a href="https://twitter.com/antonio_lofiego/status/1412102191528153092?ref_src=twsrc%5Etfw" rel="noopener noreferrer"&gt;July 5, 2021&lt;/a&gt;
&lt;/blockquote&gt; &lt;br&gt;
I tend to use &lt;code&gt;create-next-app&lt;/code&gt; over &lt;code&gt;create-react-app&lt;/code&gt; because Next is such a pleasure to work with, thanks to its extremely intuitive file-based routing, support for server-side rendering, static site generation and incremental site generation, wonderful components such as the &lt;code&gt;Image&lt;/code&gt; optimization and an overall wonderful DX.

&lt;p&gt;Something that &lt;code&gt;create-next-app&lt;/code&gt; has been lacking, though, is a single source-of-truth when it comes to setting up testing environments. &lt;code&gt;CRA&lt;/code&gt; ships with &lt;a href="https://jestjs.io/" rel="noopener noreferrer"&gt;Jest&lt;/a&gt; and &lt;a href="https://testing-library.com/docs/react-testing-library/intro/" rel="noopener noreferrer"&gt;React Testing Library&lt;/a&gt; out of the box and there's no major tweaking needed to start working on a project using TDD. The Next.js docs are wonderful, but nowhere they mention testing.&lt;/p&gt;

&lt;p&gt;Moreover, Next makes it so easy and straightforward to use TypeScript. You could just run &lt;code&gt;yarn create next-app --typescript new-project&lt;/code&gt; and all the setup is done for you. One feature I absolutely love about TypeScript are &lt;a href="https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping" rel="noopener noreferrer"&gt;path aliases&lt;/a&gt;, as they make it so easy to work with larger React projects without having to deal with a jungle of &lt;code&gt;../../../../&lt;/code&gt;s. While adding TypeScript to Next is nice and easy, it just adds more complexity when trying to set it up with Jest and RTL. &lt;/p&gt;

&lt;p&gt;Even more headaches are added if we want to include Tailwind CSS, arguably the best CSS framework out there right now. With their newly released JIT compiler, it has become such a pleasure to style your apps without writing a single line of traditional CSS, but setting it up along the rest of the tools is also another head scratcher.&lt;/p&gt;

&lt;p&gt;After banging my head on this for quite some time, I finally put together a solid template that you can use to start your Next project with this wonderful stack and in this article I'll walk you through how I did it, so you can understand where certain complexities arose.&lt;/p&gt;
&lt;h2&gt;
  
  
  create-next-app
&lt;/h2&gt;

&lt;p&gt;The first step is to get a boilerplate Next app using &lt;code&gt;create-next-app&lt;/code&gt; with the &lt;code&gt;--typescript&lt;/code&gt; flag. That will take care of all the TS-related dependencies and configurations and get us started with the initial bits of components.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn create next-app &lt;span class="nt"&gt;--typescript&lt;/span&gt; new-project
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Path Aliases
&lt;/h2&gt;

&lt;p&gt;As mentioned, I love using TS path aliases in my React projects, as it means that whenever I am building my &lt;code&gt;pages&lt;/code&gt; I can just import my components from &lt;code&gt;@components&lt;/code&gt; instead of manually writing relative imports.&lt;/p&gt;

&lt;p&gt;To do this, we can open our &lt;code&gt;tsconfig.json&lt;/code&gt; file, and add a couple of extra lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"compilerOptions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"baseUrl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"paths"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"@components/*"&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="s2"&gt;"components/*"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"@styles/*"&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="s2"&gt;"styles/*"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"@pages/*"&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="s2"&gt;"pages/*"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"@hooks/*"&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="s2"&gt;"hooks/*"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&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;Note that these are the shortcuts I use, but you can change the actual path alias to whatever you'd prefer (E.g: &lt;code&gt;@/Components/*&lt;/code&gt; or &lt;code&gt;#components/&lt;/code&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  Tailwind CSS and JIT Mode
&lt;/h2&gt;

&lt;p&gt;We can move on to Tailwind CSS. I specifically want to enable the JIT compiler as it works wonders and makes my CSS development so much smoother.&lt;/p&gt;

&lt;p&gt;First of all, let's install the dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; tailwindcss@latest postcss@latest autoprefixer@latest postcss-cli
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, we can run &lt;code&gt;npx tailwindcss init -p&lt;/code&gt; to get an empty Tailwind CSS config file as well as the appropriate PostCSS configuration. Given that we are using JIT, we don't specifically need to add the folders to purge in the configuration, but in case we decide to stop using JIT, this will take care of the production build. Our &lt;code&gt;tailwind.config.js&lt;/code&gt; file should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;mode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;jit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;purge&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./pages/**/*.{js,ts,jsx,tsx}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./components/**/*.{js,ts,jsx,tsx}&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;darkMode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// or 'media' or 'class'&lt;/span&gt;
    &lt;span class="na"&gt;theme&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;variants&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;extend&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;plugins&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;styles&lt;/code&gt; folder that &lt;code&gt;create-next-app&lt;/code&gt; generated for us, we can get rid of the &lt;code&gt;Home.module.css&lt;/code&gt; file and clear the &lt;code&gt;globals.css&lt;/code&gt; file. We will add a &lt;code&gt;tailwind.css&lt;/code&gt; file which will only contain the Tailwind directives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight css"&gt;&lt;code&gt;&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;components&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;@tailwind&lt;/span&gt; &lt;span class="n"&gt;utilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, we need to add two scripts to our &lt;code&gt;package.json&lt;/code&gt; that will take care of building new classes as we work in our application as well as building the final CSS package.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&gt;...&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"scripts"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next dev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next build"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"start"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next start"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"lint"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next lint"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"css:dev"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TAILWIND_MODE=watch postcss ./styles/tailwind.css -o ./styles/globals.css --watch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"css:build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"postcss ./styles/tailwind.css -o ./styles/globals.css"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="err"&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;The &lt;code&gt;css:dev&lt;/code&gt; script will run PostCSS in watch mode, and Tailwind will listen for changes in our component classes to build new utilities classes on the go. Once everything is done, we can build the final version of the CSS by running our &lt;code&gt;css:build&lt;/code&gt; script.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: On Windows, the &lt;code&gt;dev&lt;/code&gt; script might not work because of how environment variables are declared on Windows. A simple solution is to add another package called &lt;code&gt;cross-env&lt;/code&gt;, which handles for you all the platform idiosyncrasies while setting environment variables. Just add &lt;code&gt;cross-env&lt;/code&gt; before &lt;code&gt;TAILWIND_MODE&lt;/code&gt; and you're all set!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's now test if Tailwind works properly. Replace the content of your &lt;code&gt;pages/index.tsx&lt;/code&gt; file with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight tsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;Home&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&amp;gt;&lt;/span&gt;
            &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;main&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="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'h-[100vh] flex flex-col justify-center align-middle text-center'&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="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'text-[72px] bg-clip-text text-transparent bg-gradient-to-r from-green-400 to-blue-500 font-extrabold'&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        Batteries Included Next.js
                    &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;h2&lt;/span&gt; &lt;span class="na"&gt;className&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;'text-2xl max-w-md mx-auto'&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
                        A Next.js Boilerplate with TypeScript, Tailwind CSS and testing
                        suite 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;&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;main&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;/&amp;gt;&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;Now, in two terminal windows, run both &lt;code&gt;yarn dev&lt;/code&gt; and &lt;code&gt;yarn css:dev&lt;/code&gt; and on &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt; you should see:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1628200125810%2F-oQjGDoYs.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.hashnode.com%2Fres%2Fhashnode%2Fimage%2Fupload%2Fv1628200125810%2F-oQjGDoYs.png" alt="A working Next.js page with Tailwind CSS"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Setting up Jest and React Testing Library
&lt;/h2&gt;

&lt;p&gt;We need to install a few dependencies to make Jest and RTL work properly with TypeScript.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;yarn add &lt;span class="nt"&gt;-D&lt;/span&gt; @testing-library/dom @testing-library/jest-dom @testing-library/react @testing-library/user-event babel-jest jest jest-dom node-mocks-http ts-jest ts-loader
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Specifically:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;All the &lt;code&gt;@testing-library&lt;/code&gt; packages allow us to render our React components in what basically can be thought as a virtual browser and test their functionality&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;jest&lt;/code&gt; is a testing framework, that we will use to write, run and structure our test suites&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;babel-jest&lt;/code&gt; is used to transform and compile our code&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ts-jest&lt;/code&gt; and &lt;code&gt;ts-loader&lt;/code&gt; allow us to test TypeScript-based code in Jest&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;node-mocks-http&lt;/code&gt; will help us generate mocks of our request and response objects when testing our Next API routes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We need to create a file called &lt;code&gt;setupTests.js&lt;/code&gt; at the root of our project, similar to what you would find in a &lt;code&gt;CRA&lt;/code&gt;-generated app. This file will have a single line of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@testing-library/jest-dom/extend-expect&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;We also need to create a &lt;code&gt;.babelrc&lt;/code&gt; file. It will contain the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"presets"&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="s2"&gt;"next/babel"&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;Let's now create the configuration file for &lt;code&gt;jest&lt;/code&gt;, called &lt;code&gt;jest.config.js&lt;/code&gt; at the root of our project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;testPathIgnorePatterns&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;rootDir&amp;gt;/.next/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;rootDir&amp;gt;/node_modules/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;setupFilesAfterEnv&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;rootDir&amp;gt;/setupTests.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^.+&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;.(js|jsx|ts|tsx)$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;rootDir&amp;gt;/node_modules/babel-jest&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;As mentioned in the &lt;a href="https://jestjs.io/docs/webpack#handling-static-assets" rel="noopener noreferrer"&gt;&lt;code&gt;jest&lt;/code&gt; docs&lt;/a&gt;, we don't usually need to use CSS files during tests, so we can mock them out the test suites by mapping every &lt;code&gt;.css&lt;/code&gt; import to a mock file. To do this, let's create a new subfolder in our &lt;code&gt;styles&lt;/code&gt; folder called &lt;code&gt;__mocks__&lt;/code&gt;, and let's create a very simple file inside of it called &lt;code&gt;styleMock.js&lt;/code&gt;, which will export an empty object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have to let Jest know that whenever it encounters a css file import it should instead import this &lt;code&gt;styleMock.js&lt;/code&gt; file. To do that, let's add another line to our &lt;code&gt;jest.config.js&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&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="na"&gt;moduleNameMapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;.(css|less|scss|sass)$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;rootDir&amp;gt;/styles/__mocks__/styleMock.js&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;We also need to make Jest aware of the path aliases that we defined in our &lt;code&gt;tsconfig.json&lt;/code&gt; file. To our &lt;code&gt;moduleNameMapper&lt;/code&gt; object, let's add two more lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&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="na"&gt;moduleNameMapper&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s1"&gt;.(css|less|scss|sass)$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;rootDir&amp;gt;/styles/__mocks__/styleMock.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^@pages/(.*)$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;rootDir&amp;gt;/pages/$1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;^@components/(.*)$&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;&amp;lt;rootDir&amp;gt;/components/$1&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will tell Jest that whenever it finds an import that starts with either &lt;code&gt;@pages&lt;/code&gt; or &lt;code&gt;@component&lt;/code&gt;, it should actually import from the &lt;code&gt;pages&lt;/code&gt; and &lt;code&gt;components&lt;/code&gt; folders in the root directory.&lt;/p&gt;

&lt;p&gt;Let's test out our setup! I'll create a folder called, unsurprisingly, &lt;code&gt;tests&lt;/code&gt; at the root of my project. I will mirror the organization of my project, meaning that I will have a &lt;code&gt;components&lt;/code&gt; folder as well as a &lt;code&gt;pages&lt;/code&gt; folder which also contains an &lt;code&gt;api&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;pages&lt;/code&gt; folder, let's write our first test for the newly created &lt;code&gt;index.tsx&lt;/code&gt;, in a file called &lt;code&gt;index.text.tsx&lt;/code&gt;:&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="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="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@pages/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;renders without crashing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;heading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Batteries Included Next.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&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;Let's start the test script by running &lt;code&gt;yarn test&lt;/code&gt; and... We get an error.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  ● App › renders without crashing

    The error below may be caused by using the wrong &lt;span class="nb"&gt;test &lt;/span&gt;environment, see https://jestjs.io/docs/configuration#testenvironment-string.
    Consider using the &lt;span class="s2"&gt;"jsdom"&lt;/span&gt; &lt;span class="nb"&gt;test &lt;/span&gt;environment.

    ReferenceError: document is not defined
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That &lt;code&gt;ReferenceError&lt;/code&gt; is an issue that is caused by how Next.js renders its pages. Given that it tries to pre-render every page on the server side for better optimization and SEO, the &lt;code&gt;document&lt;/code&gt; object is not defined, as it is a client-side only. According to &lt;a href="https://testing-library.com/docs/react-testing-library/api/#render" rel="noopener noreferrer"&gt;RTL's docs&lt;/a&gt; about the &lt;code&gt;render&lt;/code&gt; function:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;By default, React Testing Library will create a div and append that div to the &lt;code&gt;document.body&lt;/code&gt; and this is where your React component will be rendered.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But we do not have a &lt;code&gt;document&lt;/code&gt; to begin with, so this fails! Luckily, &lt;code&gt;jest&lt;/code&gt; suggests a solution for this in the error message.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Consider using the "jsdom" test environment.&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's add a &lt;code&gt;jest-environment&lt;/code&gt; string at the top of our &lt;code&gt;index.test.tsx&lt;/code&gt;:&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="cm"&gt;/**
 * @jest-environment jsdom
 */&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="nx"&gt;screen&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@testing-library/react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;App&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@pages/index&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;App&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;renders without crashing&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nx"&gt;screen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getByRole&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;heading&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Batteries Included Next.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBeInTheDocument&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the tests will pass without any problem! Also, notice how we can import the &lt;code&gt;App&lt;/code&gt; component from &lt;code&gt;'@pages/index&lt;/code&gt; thanks to our &lt;code&gt;moduleNameMapper&lt;/code&gt; work we did earlier.&lt;/p&gt;

&lt;p&gt;Let's now test the API route. The default API example that &lt;code&gt;create-next-app&lt;/code&gt; generates has a simple JSON response of &lt;code&gt;{"name": "John Doe"}&lt;/code&gt;. In our &lt;code&gt;tests/pages/api&lt;/code&gt; folder we can create a new file called &lt;code&gt;hello.test.ts&lt;/code&gt; to mimic the &lt;code&gt;hello&lt;/code&gt; API name:&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;createMocks&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node-mocks-http&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;handler&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@pages/api/hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&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;/api/hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;returns a message with the specified name&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;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="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createMocks&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;GET&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;handler&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;_getStatusCode&lt;/span&gt;&lt;span class="p"&gt;()).&lt;/span&gt;&lt;span class="nf"&gt;toBe&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="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&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="nf"&gt;_getData&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="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;objectContaining&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
                &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;John Doe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;})&lt;/span&gt;
        &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, we don't need to change the environment to &lt;code&gt;jsdom&lt;/code&gt; as we are only using server-side code. In order to test our API route, we also need to mock the request and response that we pass to the API handler. In order to do this, we import the &lt;code&gt;createMocks&lt;/code&gt; function from &lt;code&gt;node-mocks-http&lt;/code&gt;, which helps us simulate a request and response object in a very intuitive manner and test it with Jest.&lt;/p&gt;

&lt;p&gt;Let's run again &lt;code&gt;yarn test&lt;/code&gt; and everything works just fine!&lt;/p&gt;

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

&lt;p&gt;There were a very large number of moving parts in putting together this template. A lot of the issues came with correctly choosing the &lt;code&gt;jest&lt;/code&gt; related packages, as most were either incompatible with TypeScript or just weren't boding well with Next.js.&lt;/p&gt;

&lt;p&gt;The template is available on my GitHub as &lt;a href="https://github.com/antoniolofiego/Batteries-Included-Next.js" rel="noopener noreferrer"&gt;&lt;code&gt;Batteries-Included-Next.js&lt;/code&gt;&lt;/a&gt;. If this has helped you or you start using this template, let me know what you are working on as I would be extremely curious to know!&lt;/p&gt;

&lt;p&gt;If you like this article, I'd suggest you to follow me on &lt;a href="https://twitter.com/antonio_lofiego" rel="noopener noreferrer"&gt;Twitter&lt;/a&gt; and give a listen to my new podcast, &lt;a href="https://twitter.com/cloudcodelife" rel="noopener noreferrer"&gt;cloud, code, life|&lt;/a&gt; where we chat about these technologies and more every week! Thanks for reading and good luck in your Next.js adventures!&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>typescript</category>
      <category>jest</category>
      <category>tailwindcss</category>
    </item>
    <item>
      <title>The Hitchhiker’s Guide to the Containers: A Foolproof, Hands-on Docker Tutorial (Part 1)</title>
      <dc:creator>Antonio Lo Fiego</dc:creator>
      <pubDate>Sun, 02 Aug 2020 01:34:31 +0000</pubDate>
      <link>https://dev.to/antoniolofiego/the-hitchhiker-s-guide-to-the-containers-a-foolproof-hands-on-docker-tutorial-part-1-4pgf</link>
      <guid>https://dev.to/antoniolofiego/the-hitchhiker-s-guide-to-the-containers-a-foolproof-hands-on-docker-tutorial-part-1-4pgf</guid>
      <description>&lt;p&gt;For a beginner, it is not an easy task to understand Docker. I will admit that I have struggled with using and understanding containers for a long time and I still have a lot to work on. There is a ton of subtleties that goes into solidly grasping the concepts behind Docker, why it is so revolutionary, and why even a budding programmer might benefit from learning it and using it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--OU1OklyC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media2.giphy.com/media/f9Rrghj6TDckb5nZZR/giphy.gif%3Fcid%3Decf05e47kyxuoduhgc2jfofwhix1gvnhxbp4spk29x3p5r0g%26rid%3Dgiphy.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--OU1OklyC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media2.giphy.com/media/f9Rrghj6TDckb5nZZR/giphy.gif%3Fcid%3Decf05e47kyxuoduhgc2jfofwhix1gvnhxbp4spk29x3p5r0g%26rid%3Dgiphy.gif" alt="It is amazing"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is my humble attempt to channel hours and hours of headaches, despair, and a-ha! moments into a beginner-friendly, digestible format. This is the first in a series of articles, and I hope it will give you a headstart in your Docker journey!&lt;/p&gt;

&lt;h2&gt;
  
  
  Some history
&lt;/h2&gt;

&lt;p&gt;The typical way of writing software was simple. A developer works on his local machine, installing a bunch of packages, setting up the environment, etc. Once the necessary code was in good shape, our dev friend shares the code to the ops folks, and... it doesn't work.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Ops:&lt;/strong&gt; Your code doesn't work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dev:&lt;/strong&gt; Hey it worked on my machine!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ops:&lt;/strong&gt; What version of &lt;code&gt;XXX&lt;/code&gt; do you run?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Dev:&lt;/strong&gt; I have no idea, man...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you can imagine, a very long time was spent troubleshooting dev environments instead of shipping features and improvements.&lt;/p&gt;

&lt;p&gt;The solution found was in &lt;strong&gt;hypervisors&lt;/strong&gt; and &lt;strong&gt;Virtual Machines (VMs)&lt;/strong&gt;. With VMs, you can package and ship a fully configured operating system along with your code, and spin up as many development and test environments as you see fit with it. Coding becomes just booting up a VM, configuring the environments as you need them, develop software, test it, and your job is done! But how does all of this work? What are VMs? Let's look at the architecture of a computer running VMs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qrOwSQAs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596313897133/V0-9594IP.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qrOwSQAs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596313897133/V0-9594IP.png" alt="Types of VM"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a lot of terms that you might not know, so let's go through them. The &lt;strong&gt;infrastructure&lt;/strong&gt; is the computer hardware, meaning CPU, RAM, SSDs and hard disks, motherboards, and anything else is part of the physical components of the host machine. The &lt;strong&gt;Host OS&lt;/strong&gt; is the operating system that is installed on the infrastructure. As an example, if you were to purchase a MacBook, the aluminum shell and all the components are part of the infrastructure, while MacOS is the Host Os.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;hypervisor&lt;/strong&gt; is a piece of software that handles the creation of Virtual Machines. Each of these VMs can run their independent process, as they believe they are using the hardware resources from the infrastructure. In reality, the hypervisor allocates hardware from the pool of resources that the infrastructure makes available. In simplest terms, it creates a virtual representation of portions of the Host Machine hardware and lets Virtual Machine run on those, managing the resources.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--R0UHKcba--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596306270830/a10Buy6vP.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--R0UHKcba--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596306270830/a10Buy6vP.gif" alt="How does a hypervisor work?"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see from the diagram, are two types of hypervisors, depending on where they sit in the system architecture. &lt;/p&gt;

&lt;h4&gt;
  
  
  Bare-Metal Hypervisors (Type 1):
&lt;/h4&gt;

&lt;p&gt;The hypervisor software is installed directly on the hardware and embedded in its components. In this case, there is no Host OS on these infrastructures. These are the most common type of hypervisors used in production environments, as they are more secure and have a higher performance by being so close to the machine level.&lt;/p&gt;

&lt;h4&gt;
  
  
  Hosted Hypervisors (Type 2):
&lt;/h4&gt;

&lt;p&gt;The hypervisor software is installed on an operating system. If you have played with VMs, this is most likely the type of hypervisor that you have used. Simply think of Oracle VirtualBox, Parallels Desktop, VMWare Fusion, or any of the major VM providers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Dmz5N7et--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596309047453/pww4mOHmh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Dmz5N7et--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596309047453/pww4mOHmh.png" alt="Bare-metal vs Hosted Hypervisors"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The important point to note here is that, while a hypervisor provides all the resources and virtualized hardware, it does not provide an operating system. This is where the &lt;strong&gt;Guest OS&lt;/strong&gt; plays its part, as the OS that is running on the VM. These are fully-fledged OS, including all the additional pieces of software needed to make the system run. This introduces a ton of additional bloat to the process and reduces the number of VMs that a single host can run.&lt;/p&gt;

&lt;p&gt;Think about installing any OS. A fresh installation of Windows, for example, also comes with all the usual additional applications and supporting software. I doubt that our production-grade Nginx server will make plenty of use of a shiny copy of Paint 3D. &lt;/p&gt;

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

&lt;p&gt;A container solves the timeless problem of "IDK, man. It works on my machine" and the performance overheads of VMs by providing you a portable, replicable image of your development environment that can run on any OS. When an application is containerized, it is bundled with all of its dependencies. In this way, if I want to run the application on a different machine, I don't need to install anything else other than Docker, as all that makes my application tick comes embedded with the Docker Image.&lt;/p&gt;

&lt;p&gt;The reason why this works is that Docker runs its containers directly on our machine's &lt;strong&gt;kernel&lt;/strong&gt;. The kernel is the very low-level program that has complete control over both software and hardware in your computer, allowing the two to communicate.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Des-HFVE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596317886484/oQnh3758L.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Des-HFVE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596317886484/oQnh3758L.png" alt="Where kernel sits in a computer"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All of the Docker container's processes run along with the main operating system's processes, albeit in a logically isolated fashion. This isolation is made possible by utilities in the Linux kernel, specifically &lt;strong&gt;LXC&lt;/strong&gt; (LinuX Containers), &lt;strong&gt;cgroups&lt;/strong&gt; (control group), and &lt;strong&gt;namespaces&lt;/strong&gt;. The specifics of how these work are a little tricky, but we will explore them in a future tutorial. &lt;/p&gt;

&lt;p&gt;Docker is built off of these utilities, extending them and making them easy to use with a high-level API, called the Docker Engine. The Docker Engine is a REST API that can be accessed via HTTP or, most commonly, through a command-line interface. It sends instructions to the Docker Daemon, a constantly running background process that manages every interaction between Docker containers and the machine's kernel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--4eMNePgs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596302358014/I12LtIqFL.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--4eMNePgs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596302358014/I12LtIqFL.png" alt="Levels of interaction with Docker"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Comparing Docker with VMs
&lt;/h4&gt;

&lt;p&gt;Let's look again at the VM architectural diagram and let's compare it to how Docker does its things.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ERRqwsM---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596298477648/alMXfcmFx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ERRqwsM---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596298477648/alMXfcmFx.png" alt="VM vs containers"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is where Docker has an advantage over VMs. Given that, as we explained before, the containers use the kernel of the host to run their processes, there is no overhead to run a container. A container has no kernel booting to do, it uses only the processes that are necessary to run the containerized application, it stops whenever my application stops and does not occupy hardware resources while not in use.&lt;/p&gt;

&lt;h4&gt;
  
  
  TL;DR
&lt;/h4&gt;

&lt;p&gt;Docker is a quick way to package applications in the environment that they were developed in, making sure that they can run no matter the underlying infrastructure, configuration, or OS.&lt;/p&gt;

&lt;h4&gt;
  
  
  Even more TL;DR
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Te2vaTSY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596235460123/5sSjCOnwM.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Te2vaTSY--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596235460123/5sSjCOnwM.jpeg" alt="How Docker was born"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Some Docker jargon
&lt;/h2&gt;

&lt;p&gt;We explained what Docker is why it is great, but you surely have heard of Dockerfiles, Docker images, Docker containers, and maybe others. Let's clarify what those things mean.&lt;/p&gt;

&lt;h4&gt;
  
  
  Docker Image
&lt;/h4&gt;

&lt;p&gt;Docker images are read-only files that are to build containers. They include everything that the containerized process needs to run, such as source code, dependencies, runtimes, and objects. Most crucially, it provides a private filesystem to the container. Images are lightweight, portable, and can be used to deploy applications quickly and at scale. Every image is built from a Docker-specific script called a Dockerfile. &lt;/p&gt;

&lt;h4&gt;
  
  
  Dockerfile
&lt;/h4&gt;

&lt;p&gt;A Dockerfile is a recipe that provides &lt;em&gt;mostly&lt;/em&gt; clear and sequential instructions on how to build an image. A Dockerfile is composed of a series of &lt;code&gt;[action]&lt;/code&gt; &lt;code&gt;[target]&lt;/code&gt; commands, each of which creates a new layer. We will cover layers in a later installment of this series, but for now, we can think of these as building blocks that can be individually cached (i.e. saved to memory) for future builds.&lt;/p&gt;

&lt;h4&gt;
  
  
  Docker Container
&lt;/h4&gt;

&lt;p&gt;Once we build an image from a Dockerfile, we can finally deploy it as a container. Containers are nothing more than instances of Docker images. Multiple containers can run at the same time on the same machine and multiple containers can be instantiated from the same Docker image. Containers live for the time it takes for their processes to run or until they fail. &lt;/p&gt;

&lt;p&gt;Combined with an extremely fast start time, we can see why they are valuable in environments that need to scale quickly. We can start as many containers as our underlying infrastructure can handle or as much as our manually allocated resources allow and we can get rid of them just as quickly.&lt;/p&gt;

&lt;h4&gt;
  
  
  Docker Registry
&lt;/h4&gt;

&lt;p&gt;If we want to control every detail of our services on our own, we can write a Dockerfile that specifies every single step of the way to get there. But in most use cases we might be interested in running pre-built images of services that we use daily. For that reason, we can browse  &lt;a href="https://hub.docker.com"&gt;Docker Hub&lt;/a&gt;, an online registry of pre-built images of various software, from commonly used applications like databases (MySQL, Redis, Postgres, etc...), web servers (Nginx, Apache), or CMS (WordPress) to development environments in most languages (Python, Node.js, Java, etc...).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--evs4r-_6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596243680676/_m6HenMF4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--evs4r-_6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596243680676/_m6HenMF4.png" alt="Explore-Docker-Hub.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The images that you build through your Dockerfiles can be pushed to the various registries, either to DockerHub if we want to make them publicly available or registries like &lt;a href="https://aws.amazon.com/ecr/"&gt;AWS Elastic Container Registry&lt;/a&gt;,  &lt;a href="https://azure.microsoft.com/en-us/services/container-registry/"&gt;Azure Container Registry&lt;/a&gt;, or &lt;a href="https://cloud.google.com/container-registry"&gt;GCP Container Registry&lt;/a&gt; if we want to keep them private. If we want our images to be uber-private, we can also host our private registry by running a local instance of the &lt;a href="https://hub.docker.com/_/registry"&gt;Docker Registry&lt;/a&gt;, which is available as a Docker image on Docker Hub.&lt;/p&gt;

&lt;p&gt;We have now a better idea of the basic building blocks of Docker. We can also identify the cycle of Docker containers, from creation to instantiation.&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--zGwTKSnC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596255174293/jg6QyfiZV.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--zGwTKSnC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn.hashnode.com/res/hashnode/image/upload/v1596255174293/jg6QyfiZV.png" alt="Docker Lifecycle"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Next steps?
&lt;/h2&gt;

&lt;p&gt;Whew! That was already a lot of information to digest! Make sure you understand the underlying concepts of Docker and why so many developers love the fact that it is in this world. In Part 2 of this series, we will start getting our feet wet with the Docker CLI, pull a few images from Docker Hub, and get experience with properly running containers in various use cases.&lt;/p&gt;

&lt;p&gt;For now, if you want, keep in touch with me via &lt;a href="https://twitter.com/antonio_lofiego"&gt;Twitter&lt;/a&gt; and let me know what you think about this guide. I hope you liked your first steps with Docker because it's gonna be a hike!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LsS8d5Pi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media1.tenor.com/images/0299b55a1c548d4af747a30af607f3a1/tenor.gif%3Fitemid%3D8832122" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LsS8d5Pi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://media1.tenor.com/images/0299b55a1c548d4af747a30af607f3a1/tenor.gif%3Fitemid%3D8832122" alt="Excited!"&gt;&lt;/a&gt; &lt;/p&gt;

</description>
      <category>docker</category>
      <category>tutorial</category>
      <category>microservices</category>
    </item>
  </channel>
</rss>
