<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ Zell Liew - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ Zell Liew - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Sun, 24 May 2026 16:30:01 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/author/zellwk/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ Mongoose 101: An Introduction to the Basics, Subdocuments, and Population ]]>
                </title>
                <description>
                    <![CDATA[ Mongoose is a library that makes MongoDB easier to use. It does two things: It gives structure to MongoDB Collections It gives you helpful methods to use In this article, we'll go through:  The basics of using Mongoose  Mongoose subdocuments Mongo... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/mongoose101/</link>
                <guid isPermaLink="false">66c4c794d788a9c53d88d2f1</guid>
                
                    <category>
                        <![CDATA[ mongoose ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Wed, 22 Jan 2020 14:00:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9c9d9f740569d1a4ca38bb.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Mongoose is a library that makes MongoDB easier to use. It does two things:</p>
<ol>
<li>It gives structure to MongoDB Collections</li>
<li>It gives you helpful methods to use</li>
</ol>
<p>In this article, we'll go through: </p>
<ol>
<li>The basics of using Mongoose </li>
<li>Mongoose subdocuments</li>
<li>Mongoose population</li>
</ol>
<p>By the end of the article, you should be able to use Mongoose without problems.  </p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>I assume you have done the following:</p>
<ol>
<li>You have installed MongoDB on your computer</li>
<li>You know how to set up a local MongoDB connection</li>
<li>You know how to see the data you have in your database</li>
<li>You know what "collections" are in MongoDB</li>
</ol>
<p>If you don't know any of these, please read <a target="_blank" href="https://zellwk.com/blog/local-mongodb">"How to set up a local MongoDB connection"</a> before you continue.</p>
<p>I also assume you know how to use MongoDB to create a simple CRUD app. If you don't know how to do this, please read <a target="_blank" href="https://zellwk.com/blog/crud-express-mongodb">"How to build a CRUD app with Node, Express, and MongoDB"</a> before you continue.</p>
<h2 id="heading-mongoose-basics">Mongoose Basics</h2>
<p>Here, you'll learn how to: </p>
<ol>
<li>Connect to the database</li>
<li>Create a Model</li>
<li>Create a Document</li>
<li>Find a Document</li>
<li>Update a Document</li>
<li>Delete a Document</li>
</ol>
<h3 id="heading-connecting-to-a-database">Connecting to a database</h3>
<p>First, you need to download Mongoose.</p>
<pre><code class="lang-bash">npm install mongoose --save
</code></pre>
<p>You can connect to a database with the <code>connect</code> method. Let's say we want to connect to a database called <code>street-fighters</code>. Here's the code you need:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>)
<span class="hljs-keyword">const</span> url = <span class="hljs-string">'mongodb://127.0.0.1:27017/street-fighters'</span>

mongoose.connect(url, { <span class="hljs-attr">useNewUrlParser</span>: <span class="hljs-literal">true</span> })
</code></pre>
<p>We want to know whether our connection has succeeded or failed. This helps us with debugging.</p>
<p>To check whether the connection has succeeded, we can use the <code>open</code> event. To check whether the connection failed, we use the <code>error</code> event.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> db = mongoose.connection
db.once(<span class="hljs-string">'open'</span>, <span class="hljs-function"><span class="hljs-params">_</span> =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Database connected:'</span>, url)
})

db.on(<span class="hljs-string">'error'</span>, <span class="hljs-function"><span class="hljs-params">err</span> =&gt;</span> {
  <span class="hljs-built_in">console</span>.error(<span class="hljs-string">'connection error:'</span>, err)
})
</code></pre>
<p>Try connecting to the database. You should see a log like this:</p>
<p><img src="https://zellwk.com/images/2019/mongoose/connect-database.png" alt="Connected to a database." width="600" height="400" loading="lazy"></p>
<h3 id="heading-creating-a-model">Creating a Model</h3>
<p>In Mongoose, you need to <strong>use models to create, read, update, or delete items</strong> from a MongoDB collection.</p>
<p>To create a Model, <strong>you need to create a Schema</strong>. A Schema lets you <strong>define the structure of an entry</strong> in the collection. This entry is also called a document.</p>
<p>Here's how you create a schema:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>)
<span class="hljs-keyword">const</span> Schema = mongoose.Schema

<span class="hljs-keyword">const</span> schema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-comment">// ...</span>
})
</code></pre>
<p>You can use <a target="_blank" href="https://mongoosejs.com/docs/guide.html">10 different kinds of values</a> in a Schema. Most of the time, you'll use these six:</p>
<ul>
<li>String</li>
<li>Number</li>
<li>Boolean</li>
<li>Array</li>
<li>Date</li>
<li>ObjectId</li>
</ul>
<p>Let's put this into practice.</p>
<p>Say we want to create characters for our Street Fighter database.</p>
<p>In Mongoose, it's a normal practice to <strong>put each model in its own file.</strong> So we will create a <code>Character.js</code> file first. This <code>Character.js</code> file will be placed in the <code>models</code> folder.</p>
<pre><code class="lang-bash">project/
    |- models/
        |- Character.js
</code></pre>
<p>In <code>Character.js</code>, we create a <code>characterSchema</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>)
<span class="hljs-keyword">const</span> Schema = mongoose.Schema

<span class="hljs-keyword">const</span> characterSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-comment">// ...</span>
})
</code></pre>
<p>Let's say we want to save two things into the database:</p>
<ol>
<li>Name of the character</li>
<li>Name of their ultimate move</li>
</ol>
<p>Both can be represented with Strings.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">'mongoose'</span>)
<span class="hljs-keyword">const</span> Schema = mongoose.Schema

<span class="hljs-keyword">const</span> characterSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-attr">name</span>: <span class="hljs-built_in">String</span>,
  <span class="hljs-attr">ultimate</span>: <span class="hljs-built_in">String</span>
})
</code></pre>
<p>Once we've created <code>characterSchema</code>, we can use mongoose's <code>model</code> method to create the model.</p>
<pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports = mongoose.model(<span class="hljs-string">'Character'</span>, characterSchema)
</code></pre>
<h3 id="heading-creating-a-document">Creating a document</h3>
<p>Let's say you have a file called <code>index.js</code>. This is where we'll perform Mongoose operations for this tutorial.</p>
<pre><code class="lang-bash">project/
    |- index.js
    |- models/
        |- Character.js
</code></pre>
<p>First, you need to load the Character model. You can do this with <code>require</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> Character = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./models/Character'</span>)
</code></pre>
<p>Let's say you want to create a character called Ryu. Ryu has an ultimate move called "Shinku Hadoken".</p>
<p>To create Ryu, you use the <code>new</code>, followed by your model. In this case, it's <code>new Character</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">new</span> Character ({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span>,
  <span class="hljs-attr">ultimate</span>: <span class="hljs-string">'Shinku Hadoken'</span>
})
</code></pre>
<p><code>new Character</code> creates the character in memory. It has not been saved to the database yet. <strong>To save to the database, you can run the <code>save</code> method</strong>.</p>
<pre><code class="lang-js">ryu.save(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">error, document</span>) </span>{
  <span class="hljs-keyword">if</span> (error) <span class="hljs-built_in">console</span>.error(error)
  <span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">document</span>)
})
</code></pre>
<p>If you run the code above, you should see this in the console.</p>
<figure><img src="https://zellwk.com/images/2019/mongoose/saved.png" alt="Ryu saved to the database." width="600" height="400" loading="lazy"></figure>

<h4 id="heading-promises-and-asyncawait">Promises and Async/await</h4>
<p><strong>Mongoose supports promises.</strong> It lets you write nicer code like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// This does the same thing as above</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">saveCharacter</span> (<span class="hljs-params">character</span>) </span>{
  <span class="hljs-keyword">const</span> c = <span class="hljs-keyword">new</span> Character(character)
  <span class="hljs-keyword">return</span> c.save()
}

saveCharacter({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span>,
  <span class="hljs-attr">ultimate</span>: <span class="hljs-string">'Shinku Hadoken'</span>
})
  .then(<span class="hljs-function"><span class="hljs-params">doc</span> =&gt;</span> { <span class="hljs-built_in">console</span>.log(doc) })
  .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> { <span class="hljs-built_in">console</span>.error(error) })
</code></pre>
<p>You can also use the <code>await</code> keyword if you have an asynchronous function.</p>
<p>If the Promise or Async/Await code looks foreign to you, I recommend reading <a target="_blank" href="https://zellwk.com/blog/async-await">"JavaScript async and await"</a> before continuing with this tutorial.</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">runCode</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">new</span> Character({
    <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span>,
    <span class="hljs-attr">ultimate</span>: <span class="hljs-string">'Shinku Hadoken'</span>
  })

  <span class="hljs-keyword">const</span> doc = <span class="hljs-keyword">await</span> ryu.save()
  <span class="hljs-built_in">console</span>.log(doc)
}

runCode()
  .catch(<span class="hljs-function"><span class="hljs-params">error</span> =&gt;</span> { <span class="hljs-built_in">console</span>.error(error) })
</code></pre>
<p>Note: I'll use the async/await format for the rest of the tutorial.</p>
<h4 id="heading-uniqueness">Uniqueness</h4>
<p>Mongoose adds a new character to the database each time you use <code>new Character</code> and <code>save</code>. If you run the code(s) above three times, you'd expect to see three Ryus in the database.</p>
<figure><img src="https://zellwk.com/images/2019/mongoose/three-ryus.png" alt="Three Ryus in the database." width="600" height="400" loading="lazy"></figure>

<p>We don't want to have three Ryus in the database. We want to have <strong>ONE Ryu only</strong>. To do this, we can use the <strong>unique</strong> option.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> characterSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-attr">name</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span> },
  <span class="hljs-attr">ultimate</span>: <span class="hljs-built_in">String</span>
})
</code></pre>
<p>The <code>unique</code> option <strong>creates a unique index</strong>. It ensures that we cannot have two documents with the same value (for <code>name</code> in this case).</p>
<p>For <code>unique</code> to work properly, you need to <strong>clear the Characters collection</strong>. To clear the Characters collection, you can use this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">await</span> Character.deleteMany({})
</code></pre>
<p>Try to add two Ryus into the database now. You'll get an <code>E11000 duplicate key error</code>. You won't be able to save the second Ryu.</p>
<figure><img src="https://zellwk.com/images/2019/mongoose/dup-error.png" alt="Duplicated key error." width="600" height="400" loading="lazy"></figure>

<p>Let's add another character into the database before we continue the rest of the tutorial.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ken = <span class="hljs-keyword">new</span> Character({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Ken'</span>,
  <span class="hljs-attr">ultimate</span>: <span class="hljs-string">'Guren Enjinkyaku'</span>
})

<span class="hljs-keyword">await</span> ken.save()
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose/ryu-ken.png" alt="Database contains two characters." width="600" height="400" loading="lazy"></figure>

<h3 id="heading-finding-a-document">Finding a document</h3>
<p>Mongoose gives you two methods to find stuff from MongoDB.</p>
<ol>
<li><code>findOne</code>: Gets one document.</li>
<li><code>find</code>: Gets an array of documents</li>
</ol>
<h4 id="heading-findone">findOne</h4>
<p><code>findOne</code> <strong>returns the first document</strong> it finds. You can specify any property to search for. Let's search for <code>Ryu</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">await</span> Character.findOne({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
<span class="hljs-built_in">console</span>.log(ryu)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose/found-one.png" alt="Found Ryu from the database." width="600" height="400" loading="lazy"></figure>

<h4 id="heading-find">find</h4>
<p><code>find</code> <strong>returns an array</strong> of documents. If you specify a property to search for, it'll return documents that match your query.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> chars = <span class="hljs-keyword">await</span> Character.find({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
<span class="hljs-built_in">console</span>.log(chars)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose/found-many-ryu.png" alt="Combed through the database and found one character with the name Ryu." width="600" height="400" loading="lazy"></figure>

<p>If you did not specify any properties to search for, it'll return an array that contains all documents in the collection.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> chars = <span class="hljs-keyword">await</span> Character.find()
<span class="hljs-built_in">console</span>.log(chars)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose/found-many.png" alt="Found two characters in the database." width="600" height="400" loading="lazy"></figure>

<h3 id="heading-updating-a-document">Updating a document</h3>
<p>Let's say Ryu has three special moves:</p>
<ol>
<li>Hadoken</li>
<li>Shoryuken</li>
<li>Tatsumaki Senpukyaku</li>
</ol>
<p>We want to add these special moves into the database. First, we need to update our <code>CharacterSchema</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> characterSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-attr">name</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span> },
  <span class="hljs-attr">specials</span>: <span class="hljs-built_in">Array</span>,
  <span class="hljs-attr">ultimate</span>: <span class="hljs-built_in">String</span>
})
</code></pre>
<p>Then, we use one of these two ways to update a character:</p>
<ol>
<li>Use <code>findOne</code>, then use <code>save</code></li>
<li>Use <code>findOneAndUpdate</code></li>
</ol>
<h4 id="heading-findone-and-save">findOne and save</h4>
<p>First, we use <code>findOne</code> to get Ryu.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">await</span> Character.findOne({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
<span class="hljs-built_in">console</span>.log(ryu)
</code></pre>
<p>Then, we update Ryu to include his special moves.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">await</span> Character.findOne({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
ryu.specials = [
  <span class="hljs-string">'Hadoken'</span>,
  <span class="hljs-string">'Shoryuken'</span>,
  <span class="hljs-string">'Tatsumaki Senpukyaku'</span>
]
</code></pre>
<p>After we modified <code>ryu</code>, we run <code>save</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">await</span> Character.findOne({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
ryu.specials = [
  <span class="hljs-string">'Hadoken'</span>,
  <span class="hljs-string">'Shoryuken'</span>,
  <span class="hljs-string">'Tatsumaki Senpukyaku'</span>
]

<span class="hljs-keyword">const</span> doc = <span class="hljs-keyword">await</span> ryu.save()
<span class="hljs-built_in">console</span>.log(doc)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose/ryu-updated.png" alt="Updated Ryu." width="600" height="400" loading="lazy"></figure>

<h4 id="heading-findoneandupdate">findOneAndUpdate</h4>
<p><code>findOneAndUpdate</code> is the same as MongoDB's <code>findOneAndModify</code> method.</p>
<p>Here, you search for Ryu and pass the fields you want to update at the same time.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Syntax</span>
<span class="hljs-keyword">await</span> findOneAndUpdate(filter, update)
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// Usage</span>
<span class="hljs-keyword">const</span> doc = <span class="hljs-keyword">await</span> Character.findOneAndUpdate(
  { <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> },
  {
    <span class="hljs-attr">specials</span>: [
      <span class="hljs-string">'Hadoken'</span>,
      <span class="hljs-string">'Shoryuken'</span>,
      <span class="hljs-string">'Tatsumaki Senpukyaku'</span>
    ]
  })

<span class="hljs-built_in">console</span>.log(doc)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose/ryu-updated.png" alt="Updated Ryu." width="600" height="400" loading="lazy"></figure>

<h4 id="heading-difference-between-findone-save-vs-findoneandupdate">Difference between findOne + save vs findOneAndUpdate</h4>
<p>Two major differences.</p>
<p>First, the <strong>syntax for <code>findOne` + `save</code> is easier to read</strong> than <code>findOneAndUpdate</code>.</p>
<p>Second, <code>findOneAndUpdate</code> does not trigger the <code>save</code> middleware.</p>
<p><strong>I'll choose <code>findOne</code> + <code>save</code></strong> over <code>findOneAndUpdate</code> anytime because of these two differences.</p>
<h3 id="heading-deleting-a-document">Deleting a document</h3>
<p>There are two ways to delete a character:</p>
<ol>
<li><code>findOne</code> + <code>remove</code></li>
<li><code>findOneAndDelete</code></li>
</ol>
<h4 id="heading-using-findone-remove">Using findOne + remove</h4>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">await</span> Character.findOne({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
<span class="hljs-keyword">const</span> deleted = <span class="hljs-keyword">await</span> ryu.remove()
</code></pre>
<h4 id="heading-using-findoneanddelete">Using findOneAndDelete</h4>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> deleted = <span class="hljs-keyword">await</span> Character.findOneAndDelete({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ken'</span> })
</code></pre>
<h2 id="heading-subdocuments">Subdocuments</h2>
<p>In Mongoose, <strong>subdocuments</strong> are documents that are <strong>nested in other documents</strong>. You can spot a subdocument when a schema is nested in another schema.</p>
<p>Note: MongoDB calls subdocuments <strong>embedded documents</strong>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> childSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-attr">name</span>: <span class="hljs-built_in">String</span>
});

<span class="hljs-keyword">const</span> parentSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-comment">// Single subdocument</span>
  <span class="hljs-attr">child</span>: childSchema,

  <span class="hljs-comment">// Array of subdocuments</span>
  <span class="hljs-attr">children</span>: [ childSchema ]
});
</code></pre>
<p>In practice, you don't have to create a separate <code>childSchema</code> like the example above. Mongoose helps you create nested schemas when you nest an object in another object.</p>
<pre><code class="lang-js"><span class="hljs-comment">// This code is the same as above</span>
<span class="hljs-keyword">const</span> parentSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-comment">// Single subdocument</span>
  <span class="hljs-attr">child</span>: { <span class="hljs-attr">name</span>: <span class="hljs-built_in">String</span> },

  <span class="hljs-comment">// Array of subdocuments</span>
  <span class="hljs-attr">children</span>: [{<span class="hljs-attr">name</span>: <span class="hljs-built_in">String</span> }]
});
</code></pre>
<p>In this section, you will learn to: </p>
<ol>
<li>Create a schema that includes a subdocument</li>
<li>Create documents that contain subdocuments</li>
<li>Update subdocuments that are arrays</li>
<li>Update a single subdocument</li>
</ol>
<h3 id="heading-updating-characterschema">Updating characterSchema</h3>
<p>Let's say we want to create a character called Ryu. Ryu has three special moves.</p>
<ol>
<li>Hadoken</li>
<li>Shinryuken</li>
<li>Tatsumaki Senpukyaku</li>
</ol>
<p>Ryu also has one ultimate move called:</p>
<ol>
<li>Shinku Hadoken</li>
</ol>
<p>We want to save the names of each move. We also want to save the keys required to execute that move.</p>
<p>Here, each move is a subdocument.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> characterSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-attr">name</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span> },
  <span class="hljs-comment">// Array of subdocuments</span>
  <span class="hljs-attr">specials</span>: [{
    <span class="hljs-attr">name</span>: <span class="hljs-built_in">String</span>,
    <span class="hljs-attr">keys</span>: <span class="hljs-built_in">String</span>
  }]
  <span class="hljs-comment">// Single subdocument</span>
  <span class="hljs-attr">ultimate</span>: {
    <span class="hljs-attr">name</span>: <span class="hljs-built_in">String</span>,
    <span class="hljs-attr">keys</span>: <span class="hljs-built_in">String</span>
  }
})
</code></pre>
<p>You can also use the childSchema syntax if you wish to. It makes the Character schema easier to understand.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> moveSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-attr">name</span>: <span class="hljs-built_in">String</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-built_in">String</span>
})

<span class="hljs-keyword">const</span> characterSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-attr">name</span>: { <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>, <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span> },
  <span class="hljs-comment">// Array of subdocuments</span>
  <span class="hljs-attr">specials</span>: [moveSchema],
  <span class="hljs-comment">// Single subdocument</span>
  <span class="hljs-attr">ultimate</span>: moveSchema
})
</code></pre>
<h3 id="heading-creating-documents-that-contain-subdocuments">Creating documents that contain subdocuments</h3>
<p>There are two ways to create documents that contain subdocuments:</p>
<ol>
<li>Pass a nested object into <code>new Model</code></li>
<li>Add properties into the created document.</li>
</ol>
<h4 id="heading-method-1-passing-the-entire-object">Method 1: Passing the entire object</h4>
<p>For this method, we construct a nested object that contains both Ryu's name and his moves.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span>,
  <span class="hljs-attr">specials</span>: [{
    <span class="hljs-attr">name</span>: <span class="hljs-string">'Hadoken'</span>,
    <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†“ â†˜ â†’ P'</span>
  }, {
    <span class="hljs-attr">name</span>: <span class="hljs-string">'Shoryuken'</span>,
    <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†’ â†“ â†˜ â†’ P'</span>
  }, {
    <span class="hljs-attr">name</span>: <span class="hljs-string">'Tatsumaki Senpukyaku'</span>,
    <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†“ â†™ â† K'</span>
  }],
  <span class="hljs-attr">ultimate</span>: {
    <span class="hljs-attr">name</span>: <span class="hljs-string">'Shinku Hadoken'</span>,
    <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†“ â†˜ â†’ â†“ â†˜ â†’ P'</span>
  }
}
</code></pre>
<p>Then, we pass this object into <code>new Character</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> char = <span class="hljs-keyword">new</span> Character(ryu)
<span class="hljs-keyword">const</span> doc = <span class="hljs-keyword">await</span> char.save()
<span class="hljs-built_in">console</span>.log(doc)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose-subdocuments/ryu.png" alt="Image of Ryu's document." width="600" height="400" loading="lazy"></figure>

<h4 id="heading-method-2-adding-subdocuments-later">Method 2: Adding subdocuments later</h4>
<p>For this method, we create a character with <code>new Character</code> first.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">new</span> Character({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
</code></pre>
<p>Then, we edit the character to add special moves:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">new</span> Character({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
<span class="hljs-keyword">const</span> ryu.specials = [{
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Hadoken'</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†“ â†˜ â†’ P'</span>
}, {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Shoryuken'</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†’ â†“ â†˜ â†’ P'</span>
}, {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Tatsumaki Senpukyaku'</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†“ â†™ â† K'</span>
}]
</code></pre>
<p>Then, we edit the character to add the ultimate move:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">new</span> Character({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })

<span class="hljs-comment">// Adds specials</span>
<span class="hljs-keyword">const</span> ryu.specials = [{
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Hadoken'</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†“ â†˜ â†’ P'</span>
}, {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Shoryuken'</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†’ â†“ â†˜ â†’ P'</span>
}, {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Tatsumaki Senpukyaku'</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†“ â†™ â† K'</span>
}]

<span class="hljs-comment">// Adds ultimate</span>
ryu.ultimate = {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Shinku Hadoken'</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†“ â†˜ â†’ â†“ â†˜ â†’ P'</span>
}
</code></pre>
<p>Once we're satisfied with <code>ryu</code>, we run <code>save</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">new</span> Character({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })

<span class="hljs-comment">// Adds specials</span>
<span class="hljs-keyword">const</span> ryu.specials = [{
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Hadoken'</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†“ â†˜ â†’ P'</span>
}, {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Shoryuken'</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†’ â†“ â†˜ â†’ P'</span>
}, {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Tatsumaki Senpukyaku'</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†“ â†™ â† K'</span>
}]

<span class="hljs-comment">// Adds ultimate</span>
ryu.ultimate = {
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Shinku Hadoken'</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†“ â†˜ â†’ â†“ â†˜ â†’ P'</span>
}

<span class="hljs-keyword">const</span> doc = <span class="hljs-keyword">await</span> ryu.save()
<span class="hljs-built_in">console</span>.log(doc)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose-subdocuments/ryu.png" alt="Image of Ryu's document." width="600" height="400" loading="lazy"></figure>

<h3 id="heading-updating-array-subdocuments">Updating array subdocuments</h3>
<p>The easiest way to update subdocuments is:</p>
<ol>
<li>Use <code>findOne</code> to find the document</li>
<li>Get the array</li>
<li>Change the array</li>
<li>Run <code>save</code></li>
</ol>
<p>For example, let's say we want to add <code>Jodan Sokutou Geri</code> to Ryu's special moves. The keys for <code>Jodan Sokutou Geri</code> are <code>â†“ â†˜ â†’ K</code>.</p>
<p>First, we find Ryu with <code>findOne</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">await</span> Characters.findOne({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
</code></pre>
<p>Mongoose documents behave like regular JavaScript objects. We can get the <code>specials</code> array by writing <code>ryu.specials</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">await</span> Characters.findOne({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
<span class="hljs-keyword">const</span> specials = ryu.specials
<span class="hljs-built_in">console</span>.log(specials)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose-subdocuments/specials.png" alt="Log of specials." width="600" height="400" loading="lazy"></figure>

<p>This <code>specials</code> array is a normal JavaScript array.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">await</span> Characters.findOne({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
<span class="hljs-keyword">const</span> specials = ryu.specials
<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">Array</span>.isArray(specials)) <span class="hljs-comment">// true</span>
</code></pre>
<p>We can use the <code>push</code> method to add a new item into <code>specials</code>,</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">await</span> Characters.findOne({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
ryu.specials.push({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Jodan Sokutou Geri'</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†“ â†˜ â†’ K'</span>
})
</code></pre>
<p>After updating <code>specials</code>, we run <code>save</code> to save Ryu to the database.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">await</span> Characters.findOne({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
ryu.specials.push({
  <span class="hljs-attr">name</span>: <span class="hljs-string">'Jodan Sokutou Geri'</span>,
  <span class="hljs-attr">keys</span>: <span class="hljs-string">'â†“ â†˜ â†’ K'</span>
})

<span class="hljs-keyword">const</span> updated = <span class="hljs-keyword">await</span> ryu.save()
<span class="hljs-built_in">console</span>.log(updated)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose-subdocuments/ryu-updated.png" alt="Ryu updated with Jodan Sokutou Geri" width="600" height="400" loading="lazy"></figure>

<h3 id="heading-updating-a-single-subdocument">Updating a single subdocument</h3>
<p>It's even easier to update single subdocuments. You can edit the document directly like a normal object.</p>
<p>Let's say we want to change Ryu's ultimate name from Shinku Hadoken to Dejin Hadoken. What we do is:</p>
<ol>
<li>Use <code>findOne</code> to get Ryu.</li>
<li>Change the <code>name</code> in <code>ultimate</code></li>
<li>Run <code>save</code></li>
</ol>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> ryu = <span class="hljs-keyword">await</span> Characters.findOne({ <span class="hljs-attr">name</span>: <span class="hljs-string">'Ryu'</span> })
ryu.ultimate.name = <span class="hljs-string">'Dejin Hadoken'</span>

<span class="hljs-keyword">const</span> updated = <span class="hljs-keyword">await</span> ryu.save()
<span class="hljs-built_in">console</span>.log(updated)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose-subdocuments/ryu-3.png" alt="Ryu document with Dejin Hadoken." width="600" height="400" loading="lazy"></figure>

<h2 id="heading-population">Population</h2>
<p>MongoDB documents have a size limit of 16MB. This means you can use subdocuments (or embedded documents) if they are small in number.</p>
<p>For example, Street Fighter characters have a limited number of moves. Ryu only has 4 special moves. In this case, it's okay to use embed moves directly into Ryu's character document.</p>
<figure><img src="https://zellwk.com/images/2019/mongoose-population/ryu.png" alt="Ryu's document." width="600" height="400" loading="lazy"></figure>

<p>But if you have data that can contain an unlimited number of subdocuments, you need to design your database differently.</p>
<p>One way is to create two separate models and combine them with populate.</p>
<h3 id="heading-creating-the-models">Creating the models</h3>
<p>Let's say you want to create a blog. And you want to store the blog content with MongoDB. Each blog has a title, content, and comments.</p>
<p>Your first schema might look like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> blogPostSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-attr">title</span>: <span class="hljs-built_in">String</span>,
  <span class="hljs-attr">content</span>: <span class="hljs-built_in">String</span>,
  <span class="hljs-attr">comments</span>: [{
    <span class="hljs-attr">comment</span>: <span class="hljs-built_in">String</span>
  }]
})

<span class="hljs-built_in">module</span>.exports = mongoose.model(<span class="hljs-string">'BlogPost'</span>, blogPostSchema)
</code></pre>
<p>There's a problem with this schema.</p>
<p>A blog post can have an unlimited number of comments. If a blog post explodes in popularity and comments swell up, the document might exceed the 16MB limit imposed by MongoDB.</p>
<p>This means we should not embed comments in blog posts. We should create a separate collection for comments.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> comments = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-attr">comment</span>: <span class="hljs-built_in">String</span>
})

<span class="hljs-built_in">module</span>.exports = mongoose.model(<span class="hljs-string">'Comment'</span>, commentSchema)
</code></pre>
<p>In Mongoose, we can link up the two models with Population.</p>
<p>To use Population, we need to:</p>
<ol>
<li>Set <code>type</code> of a property to <code>Schema.Types.ObjectId</code></li>
<li>Set <code>ref</code> to the model we want to link too.</li>
</ol>
<p>Here, we want <code>comments</code> in <code>blogPostSchema</code> to link to the Comment collection. This is the schema we'll use:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> blogPostSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-attr">title</span>: <span class="hljs-built_in">String</span>,
  <span class="hljs-attr">content</span>: <span class="hljs-built_in">String</span>,
  <span class="hljs-attr">comments</span>: [{ <span class="hljs-attr">type</span>: Schema.Types.ObjectId, <span class="hljs-attr">ref</span>: <span class="hljs-string">'Comment'</span> }]
})

<span class="hljs-built_in">module</span>.exports = mongoose.model(<span class="hljs-string">'BlogPost'</span>, blogPostSchema)
</code></pre>
<h3 id="heading-creating-a-blog-post">Creating a blog post</h3>
<p>Let's say you want to create a blog post. To create the blog post, you use <code>new BlogPost</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> blogPost = <span class="hljs-keyword">new</span> BlogPost({
  <span class="hljs-attr">title</span>: <span class="hljs-string">'Weather'</span>,
  <span class="hljs-attr">content</span>: <span class="hljs-string">`How's the weather today?`</span>
})
</code></pre>
<p>A blog post can have zero comments. We can save this blog post with <code>save</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> doc = <span class="hljs-keyword">await</span> blogPost.save()
<span class="hljs-built_in">console</span>.log(doc)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose-population/blog-post-no-comments.png" alt="Created a blog post document without comments." width="600" height="400" loading="lazy"></figure>

<h3 id="heading-creating-comments">Creating comments</h3>
<p>Now let's say we want to create a comment for the blog post. To do this, we create and save the comment.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> comment = <span class="hljs-keyword">new</span> Comment({
  <span class="hljs-attr">comment</span>: <span class="hljs-string">`It's damn hot today`</span>
})

<span class="hljs-keyword">const</span> savedComment = <span class="hljs-keyword">await</span> comment.save()
<span class="hljs-built_in">console</span>.log(savedComment)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose-population/comment.png" alt="Created and saved a comment." width="600" height="400" loading="lazy"></figure>

<p>Notice the saved comment has an <code>_id</code> attribute. We need to add this <code>_id</code> attribute into the blog post's <code>comments</code> array. This creates the link.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Saves comment to Database</span>
<span class="hljs-keyword">const</span> savedComment = <span class="hljs-keyword">await</span> comment.save()

<span class="hljs-comment">// Adds comment to blog post</span>
<span class="hljs-comment">// Then saves blog post to database</span>
<span class="hljs-keyword">const</span> blogPost = <span class="hljs-keyword">await</span> BlogPost.findOne({ <span class="hljs-attr">title</span>: <span class="hljs-string">'Weather'</span> })
blogPost.comments.push(savedComment._id)
<span class="hljs-keyword">const</span> savedPost = <span class="hljs-keyword">await</span> blogPost.save()
<span class="hljs-built_in">console</span>.log(savedPost)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose-population/blog-post-with-comments.png" alt="blog-post-with-comments" width="600" height="400" loading="lazy"><figcaption>Blog post with comments.</figcaption></figure>

<h3 id="heading-searching-blog-posts-and-their-comments">Searching blog posts and their comments</h3>
<p>If you tried to search for the blog post, you'll see the blog post has an array of comment IDs.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> blogPost = <span class="hljs-keyword">await</span> BlogPost.findOne({ <span class="hljs-attr">title</span>: <span class="hljs-string">'Weather'</span> })
<span class="hljs-built_in">console</span>.log(blogPost)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose-population/blog-post-with-comments.png" alt="Found blog post contains comment ids." width="600" height="400" loading="lazy"></figure>

<p>There are four ways to get comments.</p>
<ol>
<li>Mongoose population</li>
<li>Manual way #1</li>
<li>Manual way #2</li>
<li>Manual way #3</li>
</ol>
<h4 id="heading-mongoose-population">Mongoose Population</h4>
<p>Mongoose allows you to fetch linked documents with the <code>populate</code> method. What you need to do is call <code>.populate</code> when you execute with <code>findOne</code>.</p>
<p>When you call populate, you need to pass in the <code>key</code> of the property you want to populate. In this case, the <code>key</code> is <code>comments</code>. (Note: Mongoose calls this <code>key</code> a "path").</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> blogPost = <span class="hljs-keyword">await</span> BlogPost.findOne({ <span class="hljs-attr">title</span>: <span class="hljs-string">'Weather'</span> })
  .populate(<span class="hljs-string">'comments'</span>)
<span class="hljs-built_in">console</span>.log(blogPost)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose-population/populated.png" alt="Comments populated by Mongoose." width="600" height="400" loading="lazy"></figure>

<h4 id="heading-manual-way-method-1">Manual way (method 1)</h4>
<p>Without Mongoose Populate, you need to find the comments manually. First, you need to get the array of comments.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> blogPost = <span class="hljs-keyword">await</span> BlogPost.findOne({ <span class="hljs-attr">title</span>: <span class="hljs-string">'Weather'</span> })
  .populate(<span class="hljs-string">'comments'</span>)
<span class="hljs-keyword">const</span> commentIDs = blogPost.comments
</code></pre>
<p>Then, you loop through <code>commentIDs</code> to find each comment. If you go with this method, it's slightly faster to use <code>Promise.all</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> commentPromises = commentIDs.map(<span class="hljs-function"><span class="hljs-params">_id</span> =&gt;</span> {
  <span class="hljs-keyword">return</span> Comment.findOne({ _id })
})
<span class="hljs-keyword">const</span> comments = <span class="hljs-keyword">await</span> <span class="hljs-built_in">Promise</span>.all(commentPromises)
<span class="hljs-built_in">console</span>.log(comments)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose-population/found-comments.png" alt="Comments found." width="600" height="400" loading="lazy"></figure>


<h4 id="heading-manual-way-method-2">Manual way (method 2)</h4>
<p>Mongoose gives you an <code>$in</code> operator. You can use this <code>$in</code> operator to find all comments within an array. This syntax takes a little effort to get used to.</p>
<p>If I had to do the manual way, I'd prefer Manual #1 over this.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> commentIDs = blogPost.comments
<span class="hljs-keyword">const</span> comments = <span class="hljs-keyword">await</span> Comment.find({
    <span class="hljs-string">'_id'</span>: { <span class="hljs-attr">$in</span>: commentIDs }
})

<span class="hljs-built_in">console</span>.log(comments)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose-population/found-comments.png" alt="Comments found." width="600" height="400" loading="lazy"></figure>

<h4 id="heading-manual-way-method-3">Manual way (method 3)</h4>
<p>For the third method, we need to change the schema. When we save a comment, we link the comment to the blog post.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Linking comments to blog post</span>
<span class="hljs-keyword">const</span> commentSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-attr">comment</span>: <span class="hljs-built_in">String</span>
  <span class="hljs-attr">blogPost</span>: [{ <span class="hljs-attr">type</span>: Schema.Types.ObjectId, <span class="hljs-attr">ref</span>: <span class="hljs-string">'BlogPost'</span> }]
})

<span class="hljs-built_in">module</span>.exports = mongoose.model(<span class="hljs-string">'Comment'</span>, commentSchema)
</code></pre>
<p>You need to save the comment into the blog post, and the blog post id into the comment.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> blogPost = <span class="hljs-keyword">await</span> BlogPost.findOne({ <span class="hljs-attr">title</span>: <span class="hljs-string">'Weather'</span> })

<span class="hljs-comment">// Saves comment</span>
<span class="hljs-keyword">const</span> comment = <span class="hljs-keyword">new</span> Comment({
  <span class="hljs-attr">comment</span>: <span class="hljs-string">`It's damn hot today`</span>,
  <span class="hljs-attr">blogPost</span>: blogPost._id
})
<span class="hljs-keyword">const</span> savedComment = comment.save()

<span class="hljs-comment">// Links blog post to comment</span>
blogPost.comments.push(savedComment._id)
<span class="hljs-keyword">await</span> blogPost.save()
</code></pre>
<p>Once you do this, you can search the Comments collection for comments that match your blog post's id.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Searches for comments</span>
<span class="hljs-keyword">const</span> blogPost = <span class="hljs-keyword">await</span> BlogPost.findOne({ <span class="hljs-attr">title</span>: <span class="hljs-string">'Weather'</span> })
<span class="hljs-keyword">const</span> comments = <span class="hljs-keyword">await</span> Comment.find({ <span class="hljs-attr">_id</span>: blogPost._id })
<span class="hljs-built_in">console</span>.log(comments)
</code></pre>
<figure><img src="https://zellwk.com/images/2019/mongoose-population/found-comments.png" alt="Comments found." width="600" height="400" loading="lazy"></figure>

<p>I'd prefer Manual #3 over Manual #1 and Manual #2.</p>
<p>And Population beats all three manual methods.</p>
<h2 id="heading-quick-summary">Quick Summary</h2>
<p>You learned to use Mongoose on three different levels in this article: </p>
<ol>
<li>Basic Mongoose </li>
<li>Mongoose subdocuments</li>
<li>Mongoose population </li>
</ol>
<p>That's it!</p>
<hr>

<p>Thanks for reading. This article was originally posted on <a target="_blank" href="https://zellwk.com/blog/mongoose">my blog</a>.  Sign up for my newsletter if you want more articles to help you become a better frontend developer. </p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ A step-by-step intro to end-point testing ]]>
                </title>
                <description>
                    <![CDATA[ I've been playing around with testing lately. One thing I tried to do was to test the endpoints of my Express application. Setting up the test was the hard part. People who write about tests don't actually teach you how they set it up. I could not fi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/end-point-testing/</link>
                <guid isPermaLink="false">66c4c72a99f22436b71945e7</guid>
                
                    <category>
                        <![CDATA[ Express.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Testing ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Wed, 28 Aug 2019 23:51:55 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca097740569d1a4ca49a0.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I've been playing around with testing lately. One thing I tried to do was to test the endpoints of my Express application.</p>
<p>Setting up the test was the hard part. People who write about tests don't actually teach you how they set it up. I could not find any useful information about this, and I had to try and figure it out.</p>
<p>So today, I want to share the setup I created for myself. Hopefully, this can help you when you create your own tests.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-setting-up-jest-and-supertest">Setting up Jest and Supertest</a></li>
<li><a class="post-section-overview" href="#heading-connecting-jest-and-mongoose">Connecting Jest and Mongoose</a></li>
<li><a class="post-section-overview" href="#heading-seeding-a-database">Seeding a database</a></li>
</ol>
<h2 id="part1">Setting up Jest and Supertest</h2>

<p>First, let's talk about the stack.</p>
<h3 id="heading-the-stack">The Stack</h3>
<ul>
<li>I created my app with Express.</li>
<li>I used Mongoose to connect to MongoDB</li>
<li>I used Jest as my test framework.</li>
</ul>
<p>You might have expected Express and Mongoose because everyone else seems to use those two frameworks. I used them too.</p>
<p>But why Jest and not other test frameworks?</p>
<h3 id="heading-why-jest">Why Jest</h3>
<p>I don't like Facebook, so I didn't want to try anything that was created by Facebook's team. I know it sounds silly, but that was the truth.</p>
<p>Before Jest, I tried out all sorts of test frameworks. I tried Tap, Tape, Mocha, Jasmine, and AVA. Each test framework has its own pros and cons. I almost ended up with AVA, but I didn't go with AVA because I found it hard to set up. Eventually, I tried Jest out because Kent C. Dodds recommended it.</p>
<p>I fell in love with Jest after trying it out. I love it because:</p>
<ol>
<li>It's easy to setup</li>
<li>The <a target="_blank" href="https://egghead.io/lessons/javascript-use-jest-s-interactive-watch-mode">watch-mode</a> is amazing</li>
<li>When you <code>console.log</code> something, it actually shows up without any difficulty (this was a bitch with AVA).</li>
</ol>
<h3 id="heading-setting-up-jest">Setting up Jest</h3>
<p>First, you need to install Jest.</p>
<pre><code class="lang-js">npm install jest --save-dev
</code></pre>
<p>Next, you want to add tests scripts to your <code>package.json</code> file. It helps to add the <code>test</code> and <code>test:watch</code> scripts (for one-off testing and watch-mode respectively).</p>
<pre><code class="lang-js"><span class="hljs-string">"scripts"</span>: {
  <span class="hljs-string">"test"</span>: <span class="hljs-string">"jest"</span>,
  <span class="hljs-string">"test:watch"</span>: <span class="hljs-string">"jest --watch"</span>
},
</code></pre>
<p>You can choose to write your test files in one of the following formats. Jest picks them up for you automatically.</p>
<ol>
<li><code>js</code> files in the <code>__tests__</code> folder</li>
<li>files named with <code>test.js</code> (like <code>user.test.js</code>)</li>
<li>files named with <code>spec.js</code> (like <code>user.spec.js</code>)</li>
</ol>
<p>You can place your files however you like. When I tested endpoints, I put the test files together with my endpoints. I found this easier to manage.</p>
<pre><code class="lang-bash">- routes
  |- users/
    |- index.js
    |- users.test.js
</code></pre>
<h3 id="heading-writing-your-first-test">Writing your first test</h3>
<p>Jest includes <code>describe</code>, <code>it</code> and <code>expect</code> for you in every test file. You don't have to <code>require</code> them.</p>
<ul>
<li><code>describe</code> lets you wrap many tests together under one umbrella. (It is used for organizing your tests).</li>
<li><code>it</code> lets you run a test.</li>
<li><code>expect</code> lets you perform assertions. The test passes if all assertions passes.</li>
</ul>
<p>Here's an example of a test that fails. In this example, I <code>expect</code> that <code>1</code> should be strictly equal to <code>2</code>. Since <code>1 !== 2</code>, the test fails.</p>
<pre><code class="lang-js"><span class="hljs-comment">// This test fails because 1 !== 2</span>
it(<span class="hljs-string">"Testing to see if Jest works"</span>, <span class="hljs-function">() =&gt;</span> {
  expect(<span class="hljs-number">1</span>).toBe(<span class="hljs-number">2</span>);
});
</code></pre>
<p>You'll see a failing message from Jest if you run Jest.</p>
<pre><code class="lang-js">npm run test:watch
</code></pre>
<figure><img src="https://zellwk.com/images/2019/endpoint-testing/test-fail.png" alt="Output from Terminal. Test fails." width="600" height="400" loading="lazy"></figure>

<p>You can make the test pass by expecting <code>1 === 1</code>.</p>
<pre><code class="lang-js"><span class="hljs-comment">// This passes because 1 === 1</span>
it(<span class="hljs-string">"Testing to see if Jest works"</span>, <span class="hljs-function">() =&gt;</span> {
  expect(<span class="hljs-number">1</span>).toBe(<span class="hljs-number">1</span>);
});
</code></pre>
<figure><img src="https://zellwk.com/images/2019/endpoint-testing/test-pass.png" alt="Output from Terminal. Test successful." width="600" height="400" loading="lazy"></figure>

<p>This is the most basic of tests. It's not useful at all because we haven't testing anything real yet.</p>
<h2 id="heading-asynchronous-tests">Asynchronous tests</h2>
<p>You need to send a request to test an endpoint. Requests are asynchronous, which means you must be able to conduct asynchronous tests.</p>
<p>This is easy with Jest. There are two steps:</p>
<ol>
<li>Add the <code>async</code> keyword</li>
<li>Call <code>done</code> when you're done with your tests</li>
</ol>
<p>Here's what it can look like:</p>
<pre><code class="lang-js">it(<span class="hljs-string">"Async test"</span>, <span class="hljs-keyword">async</span> done =&gt; {
  <span class="hljs-comment">// Do your async tests here</span>

  done();
});
</code></pre>
<p>Note: <a target="_blank" href="https://zellwk.com/blog/async-await">Here's an article</a> on Async/await in JavaScript if you don't know how to use it.</p>
<h2 id="heading-testing-endpoints">Testing Endpoints</h2>
<p>You can use Supertest to test endpoints. First, you need to install Supertest.</p>
<pre><code class="lang-bash">npm install supertest --save-dev
</code></pre>
<p>Before you can test endpoints, you need to setup the server so Supertest can use it in your tests.</p>
<p>Most tutorials teach you to <code>listen</code> to the Express app in the server file, like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> app = express();

<span class="hljs-comment">// Middlewares...</span>
<span class="hljs-comment">// Routes...</span>

app.listen(<span class="hljs-number">3000</span>);
</code></pre>
<p>This doesn't work because it starts listening to one port. If you try to write many test files, you'll get an error that says "port in use".</p>
<p>You want to allow each test file to start a server on their own. To do this, you need to export <code>app</code> without listening to it.</p>
<pre><code class="lang-js"><span class="hljs-comment">// server.js</span>
<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">"express"</span>);
<span class="hljs-keyword">const</span> app = express();

<span class="hljs-comment">// Middlewares...</span>
<span class="hljs-comment">// Routes...</span>

<span class="hljs-built_in">module</span>.exports = app;
</code></pre>
<p>For development or production purposes, you can listen to your <code>app</code> like normal in a different file like <code>start.js</code>.</p>
<pre><code class="lang-js"><span class="hljs-comment">// start.js</span>
<span class="hljs-keyword">const</span> app = <span class="hljs-built_in">require</span>(<span class="hljs-string">"./server.js"</span>);
app.listen(<span class="hljs-number">3000</span>);
</code></pre>
<h3 id="heading-using-supertest">Using Supertest</h3>
<p>To use Supertest, you require your app and supertest in the test file.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> app = <span class="hljs-built_in">require</span>(<span class="hljs-string">"./server"</span>); <span class="hljs-comment">// Link to your server file</span>
<span class="hljs-keyword">const</span> supertest = <span class="hljs-built_in">require</span>(<span class="hljs-string">"supertest"</span>);
<span class="hljs-keyword">const</span> request = supertest(app);
</code></pre>
<p>Once you do this, you get the ability to send GET, POST, PUT, PATCH and DELETE requests. Before we send a request, we need to have an endpoint. Let's say we have a <code>/test</code> endpoint.</p>
<pre><code class="lang-js">app.get(<span class="hljs-string">"/test"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  res.json({ <span class="hljs-attr">message</span>: <span class="hljs-string">"pass!"</span> });
});
</code></pre>
<p>To send a GET request to <code>/test</code>, you use the <code>.get</code> method from Supertest.</p>
<pre><code class="lang-js">it(<span class="hljs-string">"Gets the test endpoint"</span>, <span class="hljs-keyword">async</span> done =&gt; {
  <span class="hljs-comment">// Sends GET Request to /test endpoint</span>
  <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request.get(<span class="hljs-string">"/test"</span>);

  <span class="hljs-comment">// ...</span>
  done();
});
</code></pre>
<p>Supertest gives you a response from the endpoint. You can test both HTTP status and the body (whatever you send through <code>res.json</code>) like this:</p>
<pre><code class="lang-js">it(<span class="hljs-string">"gets the test endpoint"</span>, <span class="hljs-keyword">async</span> done =&gt; {
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> request.get(<span class="hljs-string">"/test"</span>);

  expect(response.status).toBe(<span class="hljs-number">200</span>);
  expect(response.body.message).toBe(<span class="hljs-string">"pass!"</span>);
  done();
});
</code></pre>
<figure><img src="https://zellwk.com/images/2019/endpoint-testing/test-endpoint-pass.png" alt="First endpoint test passes." width="600" height="400" loading="lazy"></figure>


<h2 id="part2">Connecting Jest and Mongoose</h2>

<p>The hard part about testing a backend application is setting up a test database. It can be complicated.</p>
<p>Today, I want to share how I setup Jest and Mongoose.</p>
<h3 id="heading-setting-up-mongoose-with-jest">Setting up Mongoose with Jest</h3>
<p>Jest gives you a warning if you try to use Mongoose with Jest.</p>
<figure><img src="https://zellwk.com/images/2019/jest-and-mongoose/mongoose-jest-warning.png" alt="Warning if you try to use Mongoose with Jest" width="600" height="400" loading="lazy"></figure>

<p>If you don't want to see this error, you need to set <code>testEnvironment</code> to <code>node</code> in your <code>package.json</code> file.</p>
<pre><code class="lang-js"><span class="hljs-string">"jest"</span>: {
  <span class="hljs-string">"testEnvironment"</span>: <span class="hljs-string">"node"</span>
}
</code></pre>
<h3 id="heading-setting-up-mongoose-in-a-test-file">Setting up Mongoose in a test file</h3>
<p>You want to connect to a database before you begin any tests. You can use the <code>beforeAll</code> hook to do so.</p>
<pre><code class="lang-js">beforeAll(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-comment">// Connect to a Mongo DB</span>
});
</code></pre>
<p>To connect to a MongoDB, you can use Mongoose's <code>connect</code> command.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">"mongoose"</span>);
<span class="hljs-keyword">const</span> databaseName = <span class="hljs-string">"test"</span>;

beforeAll(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> url = <span class="hljs-string">`mongodb://127.0.0.1/<span class="hljs-subst">${databaseName}</span>`</span>;
  <span class="hljs-keyword">await</span> mongoose.connect(url, { <span class="hljs-attr">useNewUrlParser</span>: <span class="hljs-literal">true</span> });
});
</code></pre>
<p>This creates a connection to the database named <code>test</code>. You can name your database anything. You'll learn how to clean them up later.</p>
<p>Note: Make sure you have an active local MongoDB Connection before you test. Your tests will fail if you don't have an active local MongoDB Connection. <a target="_blank" href="https://zellwk.com/blog/local-mongodb">Read this</a> to learn how to create a local MongoDB connection.</p>
<h3 id="heading-creating-databases-for-each-test-file">Creating databases for each test file</h3>
<p>When you test, you want to connect to a different database for each test file, because:</p>
<ol>
<li>Jest runs each test file asynchronously. You won't know which file comes first.</li>
<li>You don't want tests to share the same database. You don't want data from one test file to spill over to the next test file.</li>
</ol>
<p>To connect to a different database, you change the name of the database.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Connects to database called avengers</span>
beforeAll(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> url = <span class="hljs-string">`mongodb://127.0.0.1/avengers`</span>;
  <span class="hljs-keyword">await</span> mongoose.connect(url, { <span class="hljs-attr">useNewUrlParser</span>: <span class="hljs-literal">true</span> });
});
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// Connects to database power-rangers</span>
beforeAll(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> url = <span class="hljs-string">`mongodb://127.0.0.1/power-rangers`</span>;
  <span class="hljs-keyword">await</span> mongoose.connect(url, { <span class="hljs-attr">useNewUrlParser</span>: <span class="hljs-literal">true</span> });
});
</code></pre>
<h3 id="heading-sending-a-post-request">Sending a POST request</h3>
<p>Let's say you want to create a user for your app. The user has a name and an email address. Your Mongoose Schema might look like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">"mongoose"</span>);
<span class="hljs-keyword">const</span> Schema = mongoose.Schema;

<span class="hljs-keyword">const</span> userSchema = <span class="hljs-keyword">new</span> Schema({
  <span class="hljs-attr">name</span>: <span class="hljs-built_in">String</span>,
  <span class="hljs-attr">email</span>: {
    <span class="hljs-attr">type</span>: <span class="hljs-built_in">String</span>,
    <span class="hljs-attr">require</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">unique</span>: <span class="hljs-literal">true</span>
  }
});

<span class="hljs-built_in">module</span>.exports = mongoose.model(<span class="hljs-string">"User"</span>, userSchema);
</code></pre>
<p>To create a user, you need to save the <code>name</code> and <code>email</code> into MongoDB. Your route and controller might look like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> User = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../model/User"</span>); <span class="hljs-comment">// Link to your user model</span>

app.post(<span class="hljs-string">"/signup"</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
  <span class="hljs-keyword">const</span> { name, email } = req.body;
  <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">new</span> User({ name, email });
  <span class="hljs-keyword">const</span> ret = <span class="hljs-keyword">await</span> user.save();
  res.json(ret);
});
</code></pre>
<p>To save the user into the database, you can send a POST request to <code>signup</code>. To send a post request, you use the <code>post</code> method. To send data along with the POST request, you use the <code>send</code> method. In your tests, it'll look like this.</p>
<pre><code class="lang-js">it(<span class="hljs-string">"Should save user to database"</span>, <span class="hljs-keyword">async</span> done =&gt; {
  <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request.post(<span class="hljs-string">"/signup"</span>).send({
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Zell"</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">"testing@gmail.com"</span>
  });
  done();
});
</code></pre>
<p>Note: If you run this code two times, you'll get an <code>E1100 duplicate key error</code>. This error occurred because:</p>
<ol>
<li>We said the <code>email</code> should be <code>unique</code> in the Schema above.</li>
<li>We tried to create another user with <code>testing@gmail.com</code>. even though one already exists in the database. (The first one was created when you sent the first request).</li>
</ol>
<figure><img src="https://zellwk.com/images/2019/jest-and-mongoose/duplicate-error.png" alt="Duplicate key error." width="600" height="400" loading="lazy"></figure>

<h2 id="heading-cleaning-up-the-database-between-tests">Cleaning up the database between tests</h2>
<p>You want to remove entries from the database between each test. This ensures you always start with an empty database.</p>
<p>You can do this with the <code>afterEach</code> hook.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Cleans up database between each test</span>
afterEach(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> User.deleteMany();
});
</code></pre>
<p>In this code above, we only cleared the <code>User</code> collection in the database. In a real scenario, you want to clear all collections. You can use the following code to do so:</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">removeAllCollections</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> collections = <span class="hljs-built_in">Object</span>.keys(mongoose.connection.collections);
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> collectionName <span class="hljs-keyword">of</span> collections) {
    <span class="hljs-keyword">const</span> collection = mongoose.connection.collections[collectionName];
    <span class="hljs-keyword">await</span> collection.deleteMany();
  }
}

afterEach(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> removeAllCollections();
});
</code></pre>
<h3 id="heading-testing-the-endpoint">Testing the Endpoint</h3>
<p>Let's begin our tests. In this test, we will send a POST request to the <code>/signup</code> endpoint. We want to make sure:</p>
<ol>
<li>The user gets saved to the database</li>
<li>The returned object contains information about the user</li>
</ol>
<h3 id="heading-checking-if-the-user-was-saved-to-the-database">Checking if the user was saved to the database</h3>
<p>To check whether the user gets saved into the database, you search the database for the user.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> User = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../model/User"</span>); <span class="hljs-comment">// Link to your user model</span>

it(<span class="hljs-string">"Should save user to database"</span>, <span class="hljs-keyword">async</span> done =&gt; {
  <span class="hljs-keyword">const</span> res = <span class="hljs-keyword">await</span> request.post(<span class="hljs-string">"/signup"</span>).send({
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Zell"</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">"testing@gmail.com"</span>
  });

  <span class="hljs-comment">// Searches the user in the database</span>
  <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.findOne({ <span class="hljs-attr">email</span>: <span class="hljs-string">"testing@gmail.com"</span> });

  done();
});
</code></pre>
<p>If you <code>console.log</code> user, you should see something like this:</p>
<figure><img src="https://zellwk.com/images/2019/jest-and-mongoose/user.png" alt="User object from MongoDB." width="600" height="400" loading="lazy"></figure>

<p>This means our user got saved to the database. If we want to confirm the user has a name and an email, we can do <code>expect</code> them to be true.</p>
<pre><code class="lang-js">it(<span class="hljs-string">"Should save user to database"</span>, <span class="hljs-keyword">async</span> done =&gt; {
  <span class="hljs-comment">// Sends request...</span>

  <span class="hljs-comment">// Searches the user in the database</span>
  <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> User.findOne({ <span class="hljs-attr">email</span>: <span class="hljs-string">"testing@gmail.com"</span> });
  expect(user.name).toBeTruthy();
  expect(user.email).toBeTruthy();

  done();
});
</code></pre>
<h4 id="heading-checking-if-the-returned-object-contains-the-information-about-the-user">Checking if the returned object contains the information about the user</h4>
<p>We want to make sure the returned object contains the user's name and email address. To do this, we check the response from the post request.</p>
<pre><code class="lang-js">it(<span class="hljs-string">"Should save user to database"</span>, <span class="hljs-keyword">async</span> done =&gt; {
  <span class="hljs-comment">// Sends request...</span>

  <span class="hljs-comment">// Searches the user in the database...</span>

  <span class="hljs-comment">// Ensures response contains name and email</span>
  expect(res.body.name).toBeTruthy();
  expect(res.body.email).toBeTruthy();
  done();
});
</code></pre>
<p>We're done with our tests now. We want to delete the database from MongoDB.</p>
<h3 id="heading-deleting-the-database">Deleting the database</h3>
<p>To delete the database, you need to ensure there are 0 collections in the database. We can do this by dropping each collection we used.</p>
<p>We'll do after all our tests have run, in the <code>afterAll</code> hook.</p>
<pre><code class="lang-js">afterAll(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-comment">// Removes the User collection</span>
  <span class="hljs-keyword">await</span> User.drop();
});
</code></pre>
<p>To drop all your collections you can use this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">dropAllCollections</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> collections = <span class="hljs-built_in">Object</span>.keys(mongoose.connection.collections);
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> collectionName <span class="hljs-keyword">of</span> collections) {
    <span class="hljs-keyword">const</span> collection = mongoose.connection.collections[collectionName];
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> collection.drop();
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-comment">// This error happens when you try to drop a collection that's already dropped. Happens infrequently.</span>
      <span class="hljs-comment">// Safe to ignore.</span>
      <span class="hljs-keyword">if</span> (error.message === <span class="hljs-string">"ns not found"</span>) <span class="hljs-keyword">return</span>;

      <span class="hljs-comment">// This error happens when you use it.todo.</span>
      <span class="hljs-comment">// Safe to ignore.</span>
      <span class="hljs-keyword">if</span> (error.message.includes(<span class="hljs-string">"a background operation is currently running"</span>))
        <span class="hljs-keyword">return</span>;

      <span class="hljs-built_in">console</span>.log(error.message);
    }
  }
}

<span class="hljs-comment">// Disconnect Mongoose</span>
afterAll(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> dropAllCollections();
});
</code></pre>
<p>Finally, you want to close the Mongoose connection to end the test. Here's how you can do it:</p>
<pre><code class="lang-js">afterAll(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> dropAllCollections();
  <span class="hljs-comment">// Closes the Mongoose connection</span>
  <span class="hljs-keyword">await</span> mongoose.connection.close();
});
</code></pre>
<p>That's everything you need to do to setup Mongoose with Jest!</p>
<h3 id="heading-refactoring">Refactoring</h3>
<p>There's a lot of code that goes into <code>beforeEach</code>, <code>afterEach</code>, and <code>afterAll</code> hooks. We will be using them for every test file. It makes sense to create a setup file for these hooks.</p>
<pre><code class="lang-js"><span class="hljs-comment">// test-setup.js</span>
<span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">"mongoose"</span>);
mongoose.set(<span class="hljs-string">"useCreateIndex"</span>, <span class="hljs-literal">true</span>);
mongoose.promise = <span class="hljs-built_in">global</span>.Promise;

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">removeAllCollections</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> collections = <span class="hljs-built_in">Object</span>.keys(mongoose.connection.collections);
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> collectionName <span class="hljs-keyword">of</span> collections) {
    <span class="hljs-keyword">const</span> collection = mongoose.connection.collections[collectionName];
    <span class="hljs-keyword">await</span> collection.deleteMany();
  }
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">dropAllCollections</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">const</span> collections = <span class="hljs-built_in">Object</span>.keys(mongoose.connection.collections);
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> collectionName <span class="hljs-keyword">of</span> collections) {
    <span class="hljs-keyword">const</span> collection = mongoose.connection.collections[collectionName];
    <span class="hljs-keyword">try</span> {
      <span class="hljs-keyword">await</span> collection.drop();
    } <span class="hljs-keyword">catch</span> (error) {
      <span class="hljs-comment">// Sometimes this error happens, but you can safely ignore it</span>
      <span class="hljs-keyword">if</span> (error.message === <span class="hljs-string">"ns not found"</span>) <span class="hljs-keyword">return</span>;
      <span class="hljs-comment">// This error occurs when you use it.todo. You can</span>
      <span class="hljs-comment">// safely ignore this error too</span>
      <span class="hljs-keyword">if</span> (error.message.includes(<span class="hljs-string">"a background operation is currently running"</span>))
        <span class="hljs-keyword">return</span>;
      <span class="hljs-built_in">console</span>.log(error.message);
    }
  }
}

<span class="hljs-built_in">module</span>.exports = {
  setupDB(databaseName) {
    <span class="hljs-comment">// Connect to Mongoose</span>
    beforeAll(<span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">const</span> url = <span class="hljs-string">`mongodb://127.0.0.1/<span class="hljs-subst">${databaseName}</span>`</span>;
      <span class="hljs-keyword">await</span> mongoose.connect(url, { <span class="hljs-attr">useNewUrlParser</span>: <span class="hljs-literal">true</span> });
    });

    <span class="hljs-comment">// Cleans up database between each test</span>
    afterEach(<span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">await</span> removeAllCollections();
    });

    <span class="hljs-comment">// Disconnect Mongoose</span>
    afterAll(<span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">await</span> dropAllCollections();
      <span class="hljs-keyword">await</span> mongoose.connection.close();
    });
  }
};
</code></pre>
<p>You can import the setup file for each test like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { setupDB } = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../test-setup"</span>);

<span class="hljs-comment">// Setup a Test Database</span>
setupDB(<span class="hljs-string">"endpoint-testing"</span>);

<span class="hljs-comment">// Continue with your tests...</span>
</code></pre>
<p>There's one more thing I want to show you.</p>
<p>When you create tests, you want to seed the database with fake data.</p>
<h3 id="part3">Seeding a database</h3>

<p>When you write tests for the backend, you need to test for four different kinds of operations:</p>
<ol>
<li>Create (for adding things to the database)</li>
<li>Read (for getting things from the database)</li>
<li>Update (for changing the database)</li>
<li>Delete (for deleting things from the database)</li>
</ol>
<p>The easiest type to test for is create operations. You put something into the database and test whether it's there.</p>
<p>For the other three types of operations, you need to put something into the database <em>before</em> you write the test.</p>
<h3 id="heading-putting-things-into-the-database">Putting things into the database</h3>
<p>The process where you add things to a database is called <strong>seeding a database</strong>.</p>
<p>Let's say you want to add three users to the database. These users contain a name and an email address.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> users = [
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Zell"</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">"testing1@gmail.com"</span>
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Vincy"</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">"testing2@gmail.com"</span>
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Shion"</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">"testing3@gmail.com"</span>
  }
];
</code></pre>
<p>You can use your models to seed the database at the start of the test.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> User = <span class="hljs-built_in">require</span>(<span class="hljs-string">"../model/User"</span>); <span class="hljs-comment">// Link to User model</span>

it(<span class="hljs-string">"does something"</span>, <span class="hljs-keyword">async</span> done =&gt; {
  <span class="hljs-comment">// Add users to the database</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> u <span class="hljs-keyword">of</span> users) {
    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">new</span> User(u);
    <span class="hljs-keyword">await</span> user.save();
  }

  <span class="hljs-comment">// Create the rest of your test here</span>
});
</code></pre>
<p>If you need these users for every test, the best way is to add them through the <code>beforeEach</code> hook. The <code>beforeEach</code> hook runs before every <code>it</code> declaration.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Seed the database with users</span>
beforeEach(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">for</span> (u <span class="hljs-keyword">of</span> users) {
    <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">new</span> User(u);
    <span class="hljs-keyword">await</span> user.save();
  }
});
</code></pre>
<p>You can also use Mongoose's <code>create</code> function to do the same thing. It runs <code>new Model()</code> and <code>save()</code>, so the code below and the one above does the same thing.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Seed the database with users</span>
beforeEach(<span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> User.create(users);
});
</code></pre>
<h3 id="heading-create-vs-insertmany">create vs insertMany</h3>
<p>Mongoose has a second method to help you seed the database. This method is called <code>insertMany</code>. <code>insertMany</code> is faster than <code>create</code>, because:</p>
<ul>
<li><code>insertMany</code> sends one operation to the server</li>
<li><code>create</code> sends one operation for each document</li>
</ul>
<p>However, <code>insertMany</code> does not run the <code>save</code> middleware.</p>
<h4 id="heading-is-triggering-the-save-middleware-important">Is triggering the save middleware important?</h4>
<p>This depends on your seed data. If your seed data needs to go through the <code>save</code> middleware, you need to use <code>create</code>. For example, let's say you want to save a user's password into the database. You have this data:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> users = [
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Zell"</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">"testing1@gmail.com"</span>,
    <span class="hljs-attr">password</span>: <span class="hljs-string">"12345678"</span>
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Vincy"</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">"testing2@gmail.com"</span>,
    <span class="hljs-attr">password</span>: <span class="hljs-string">"12345678"</span>
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Shion"</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">"testing3@gmail.com"</span>,
    <span class="hljs-attr">password</span>: <span class="hljs-string">"12345678"</span>
  }
];
</code></pre>
<p>When we save a user's password into the database, we want to hash the password for security reasons. We usually hash the password through the <code>save</code> middleware.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Hashes password automatically</span>
userSchema.pre(<span class="hljs-string">"save"</span>, <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">next</span>) </span>{
  <span class="hljs-keyword">if</span> (!<span class="hljs-built_in">this</span>.isModified(<span class="hljs-string">"password"</span>)) <span class="hljs-keyword">return</span> next();
  <span class="hljs-keyword">const</span> salt = bcrypt.genSaltSync(<span class="hljs-number">10</span>);
  <span class="hljs-keyword">const</span> hashedPassword = bcrypt.hashSync(password, salt);
  <span class="hljs-built_in">this</span>.password = hashedPassword;
});
</code></pre>
<p>If you use <code>create</code>, you'll get users with hashed passwords:</p>
<figure><img src="https://zellwk.com/images/2019/seed-database/create.png" alt="Create runs the save middleware." width="600" height="400" loading="lazy"></figure>

<p>If you use <code>insertMany</code>, you'll get users without hashed passwords:</p>
<figure><img src="https://zellwk.com/images/2019/seed-database/insert-many.png" alt="InsertMany does not run the save middleware." width="600" height="400" loading="lazy"></figure>

<h3 id="heading-when-to-use-create-when-to-use-insertmany">When to use create, when to use insertMany</h3>
<p>Since <code>insertMany</code> is faster than <code>create</code>, you want to use <code>insertMany</code> whenever you can.</p>
<p>Here's how I do it:</p>
<ol>
<li>If seed data does not require the <code>save</code> middleware, use <code>insertMany</code>.</li>
<li>If seed data requires <code>save</code> middleware, use <code>create</code>. Then, overwrite seed data so it no longer requires the <code>save</code> middleware.</li>
</ol>
<p>For the password example above, I would run <code>create</code> first. Then, I copy-paste the hashed password seed data. Then, I'll run <code>insertMany</code> from this point onwards.</p>
<p>If you want to overwrite complicated seed data, you might want to get JSON straight from MongoDB. To do this, you can use <code>mongoexport</code>:</p>
<pre><code class="lang-js">mongoexport --db &lt;databaseName&gt; --collection &lt;collectionName&gt; --jsonArray --pretty --out output.json
</code></pre>
<p>This says:</p>
<ol>
<li>Export <code>&lt;collection&gt;</code> from <code>&lt;databaseName&gt;</code></li>
<li>Creates output as a JSON Array, prettified, in a file called <code>output.json</code>. This file will be placed in the folder where you run the command.</li>
</ol>
<h3 id="heading-seeding-multiple-test-files-and-collections">Seeding multiple test files and collections</h3>
<p>You want a place to store your seed data so you can use them across all your tests and collections. Here's a system I use:</p>
<ol>
<li>I name my seed files according to their models. I seed a <code>User</code> model with the <code>user.seed.js</code> file.</li>
<li>I put my seed files in the <code>seeds</code> folder</li>
<li>I loop through each seed file to seed the database.</li>
</ol>
<p>To loop through each seed file, you need to use the <code>fs</code> module. <code>fs</code> stands for filesystem.</p>
<p>The easiest way to loop through the files is to create an <code>index.js</code> file in the same <code>seeds</code> folder. Once you have the <code>index.js</code> file, you can use the following code to look for all files with <code>*.seed.js</code></p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">"fs"</span>);
<span class="hljs-keyword">const</span> util = <span class="hljs-built_in">require</span>(<span class="hljs-string">"util"</span>);

<span class="hljs-comment">// fs.readdir is written with callbacks.</span>
<span class="hljs-comment">// This line converts fs.readdir into a promise</span>
<span class="hljs-keyword">const</span> readDir = util.promisify(fs.readdir);

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">seedDatabase</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// Gets list of files in the directory</span>
  <span class="hljs-comment">// `__dirname` points to the `seeds/` folder</span>
  <span class="hljs-keyword">const</span> dir = <span class="hljs-keyword">await</span> readDir(__dirname);

  <span class="hljs-comment">// Gets a list of files that matches *.seed.js</span>
  <span class="hljs-keyword">const</span> seedFiles = dir.filter(<span class="hljs-function"><span class="hljs-params">f</span> =&gt;</span> f.endsWith(<span class="hljs-string">".seed.js"</span>));
}
</code></pre>
<p>Once you have a list of seed files, you can loop through each seed file to seed the database. Here, I use a <code>for...of</code> loop to keep things simple.</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">seedDatabase</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> file <span class="hljs-keyword">of</span> seedFiles) {
    <span class="hljs-comment">// Seed the database</span>
  }
}
</code></pre>
<p>To seed the database, we need to find the correct Mongoose model from the name of the seed file. A file called <code>user.seed.js</code> should seed the <code>User</code> model. This means:</p>
<ol>
<li>We must find <code>user</code> from <code>user.seed.js</code></li>
<li>We must capitalize <code>user</code> into <code>User</code></li>
</ol>
<p>Here's a crude version that does what's required. (If you want to, you can make the code more robust with regex instead of <code>split</code>).</p>
<pre><code class="lang-js"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> file <span class="hljs-keyword">of</span> seedFiles) {
  <span class="hljs-keyword">const</span> fileName = file.split(<span class="hljs-string">".seed.js"</span>)[<span class="hljs-number">0</span>];
  <span class="hljs-keyword">const</span> modelName = toTitleCase(fileName);
  <span class="hljs-keyword">const</span> model = mongoose.models[modelName];
}
</code></pre>
<p>Next, we want to make sure each file has a Model that corresponds to it. If the model cannot be found, we want to throw an error.</p>
<pre><code class="lang-js"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> file <span class="hljs-keyword">of</span> seedFiles) {
  <span class="hljs-comment">//...</span>
  <span class="hljs-keyword">if</span> (!model) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`Cannot find Model '<span class="hljs-subst">${modelName}</span>'`</span>);
}
</code></pre>
<p>If there's a corresponding model, we want to seed the database with the contents in the seed file. To do this, we need to read the seed file first. Here, since I used the <code>.js</code> extension, I can simply require the file.</p>
<pre><code class="lang-js"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> file <span class="hljs-keyword">of</span> seedFiles) {
  <span class="hljs-comment">//...</span>
  <span class="hljs-keyword">const</span> fileContents = <span class="hljs-built_in">require</span>(path.join(__dirname, file));
}
</code></pre>
<p>For this to work, my seed files must export an array of data.</p>
<pre><code class="lang-js"><span class="hljs-built_in">module</span>.exports = [
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Zell"</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">"testing1@gmail.com"</span>,
    <span class="hljs-attr">password</span>: <span class="hljs-string">"12345678"</span>
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Vincy"</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">"testing2@gmail.com"</span>,
    <span class="hljs-attr">password</span>: <span class="hljs-string">"12345678"</span>
  },
  {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"Shion"</span>,
    <span class="hljs-attr">email</span>: <span class="hljs-string">"testing3@gmail.com"</span>,
    <span class="hljs-attr">password</span>: <span class="hljs-string">"12345678"</span>
  }
];
</code></pre>
<p>Once I have the contents of the seed file, I can run <code>create</code> or <code>insertMany</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">seedDatabase</span>(<span class="hljs-params">runSaveMiddleware = false</span>) </span>{
  <span class="hljs-comment">// ...</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> file <span class="hljs-keyword">of</span> seedFiles) {
    <span class="hljs-comment">// ...</span>

    runSaveMiddleware
      ? model.create(fileContents)
      : model.insertMany(fileContents);
  }
}
</code></pre>
<p>Here's the whole <code>seedDatabase</code> code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">"fs"</span>);
<span class="hljs-keyword">const</span> util = <span class="hljs-built_in">require</span>(<span class="hljs-string">"util"</span>);
<span class="hljs-keyword">const</span> readDir = util.promisify(fs.readdir).bind(fs);
<span class="hljs-keyword">const</span> path = <span class="hljs-built_in">require</span>(<span class="hljs-string">"path"</span>);
<span class="hljs-keyword">const</span> mongoose = <span class="hljs-built_in">require</span>(<span class="hljs-string">"mongoose"</span>);

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">toTitleCase</span>(<span class="hljs-params">str</span>) </span>{
  <span class="hljs-keyword">return</span> str.replace(<span class="hljs-regexp">/\w\S*/g</span>, <span class="hljs-function"><span class="hljs-params">txt</span> =&gt;</span> {
    <span class="hljs-keyword">return</span> txt.charAt(<span class="hljs-number">0</span>).toUpperCase() + txt.substr(<span class="hljs-number">1</span>).toLowerCase();
  });
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">seedDatabase</span>(<span class="hljs-params">runSaveMiddleware = false</span>) </span>{
  <span class="hljs-keyword">const</span> dir = <span class="hljs-keyword">await</span> readDir(__dirname);
  <span class="hljs-keyword">const</span> seedFiles = dir.filter(<span class="hljs-function"><span class="hljs-params">f</span> =&gt;</span> f.endsWith(<span class="hljs-string">".seed.js"</span>));

  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> file <span class="hljs-keyword">of</span> seedFiles) {
    <span class="hljs-keyword">const</span> fileName = file.split(<span class="hljs-string">".seed.js"</span>)[<span class="hljs-number">0</span>];
    <span class="hljs-keyword">const</span> modelName = toTitleCase(fileName);
    <span class="hljs-keyword">const</span> model = mongoose.models[modelName];

    <span class="hljs-keyword">if</span> (!model) <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">`Cannot find Model '<span class="hljs-subst">${modelName}</span>'`</span>);
    <span class="hljs-keyword">const</span> fileContents = <span class="hljs-built_in">require</span>(path.join(__dirname, file));

    runSaveMiddleware
      ? <span class="hljs-keyword">await</span> model.create(fileContents)
      : <span class="hljs-keyword">await</span> model.insertMany(fileContents);
  }
}
</code></pre>
<h3 id="heading-why-js-not-json">Why JS, not JSON?</h3>
<p>It's the industry norm to use JSON to store data. In this case, I find it easier to use JavaScript objects because:</p>
<ol>
<li>I don't have to write opening and closing double-quotes for each property.</li>
<li>I don't have to use double-quotes at all! (It's easier to write single-quotes because there's no need to press the shift key).</li>
</ol>
<pre><code class="lang-js"><span class="hljs-comment">// Which is easier to write. JavaScript objects or JSON?</span>

<span class="hljs-comment">// JavaScript objects</span>
<span class="hljs-built_in">module</span>.exports = [
  {
    <span class="hljs-attr">objectName</span>: <span class="hljs-string">"property"</span>
  }
][
  <span class="hljs-comment">// JSON</span>
  {
    <span class="hljs-attr">objectName</span>: <span class="hljs-string">"property"</span>
  }
];
</code></pre>
<p>If you want to use JSON, make sure you change <code>seedDatabase</code> to work with JSON. (I'll let you work through the code yourself).</p>
<h2 id="heading-adjusting-the-setupdb-function">Adjusting the setupDB function</h2>
<p>Earlier, I created a <code>setupDB</code> function to help set up databases for my tests. <code>seedDatabase</code> goes into the <code>setupDB</code> function since seeding is part of the setting up process.</p>
<pre><code class="lang-js"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">seedDatabase</span>(<span class="hljs-params">runSaveMiddleware = false</span>) </span>{
  <span class="hljs-comment">// ...</span>
}

<span class="hljs-built_in">module</span>.exports = {
  setupDB(databaseName, runSaveMiddleware = <span class="hljs-literal">false</span>) {
    <span class="hljs-comment">// Connect to Mongoose</span>
    beforeAll(<span class="hljs-comment">/*...*/</span>);

    <span class="hljs-comment">// Seed Data</span>
    beforeEach(<span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">await</span> seedDatabase(runSaveMiddleware);
    });

    <span class="hljs-comment">// Cleans up database between each test</span>
    afterEach(<span class="hljs-comment">/*...*/</span>);

    <span class="hljs-comment">// Disconnect Mongoose</span>
    afterAll(<span class="hljs-comment">/*...*/</span>);
  }
};
</code></pre>
<h3 id="heading-a-github-repository">A Github Repository</h3>
<p>I created a <a target="_blank" href="https://github.com/zellwk/endpoint-testing-example">Github repository</a> to go with this article. I hope this demo code helps you start testing your applications.</p>
<hr>

<p>Thanks for reading. This article was originally posted on <a target="_blank" href="https://zellwk.com/blog/endpoint-testing">my blog</a>. Sign up for <a target="_blank" href="https://zellwk.com">my newsletter</a> if you want more articles to help you become a better frontend developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to add Flexbox fallback to CSS Grid ]]>
                </title>
                <description>
                    <![CDATA[ I shared how to build a calendar with CSS Grid in the previous article. Today, I want to share how to build a Flexbox fallback for the same calendar. How to provide support Generally, there are three ways to provide support when it comes to CSS. Firs... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-add-flexbox-fallback-to-css-grid/</link>
                <guid isPermaLink="false">66c4c739d788a9c53d88d2e2</guid>
                
                    <category>
                        <![CDATA[ CSS Grid ]]>
                    </category>
                
                    <category>
                        <![CDATA[ flexbox ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Thu, 25 Jul 2019 22:41:04 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca138740569d1a4ca4d57.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I shared how to build a calendar with CSS Grid in the <a target="_blank" href="https://zellwk.com/blog/calendar-with-css-grid">previous article</a>. Today, I want to share how to build a Flexbox fallback for the same calendar.</p>
<h2 id="heading-how-to-provide-support">How to provide support</h2>
<p>Generally, there are three ways to provide support when it comes to CSS.</p>
<p><strong>First method:</strong> Write fallback code. Overwrite fallback code.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.selector</span> {
  <span class="hljs-attribute">property</span>: fallback-value;
  <span class="hljs-attribute">property</span>: actual-value;
}
</code></pre>
<p><strong>Second method:</strong> Write fallback code. Overwrite fallback code in CSS Feature Queries (<code>@supports</code>). Reset properties inside <code>@supports</code> if you need.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.selector</span> {
  <span class="hljs-attribute">property</span>: fallback-value;
}

<span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">display:</span> grid) {
  <span class="hljs-selector-tag">property</span>: <span class="hljs-selector-tag">actual-value</span>;
}
</code></pre>
<p><strong>Third method:</strong> Write everything in <code>@supports</code>.</p>
<pre><code class="lang-css"><span class="hljs-keyword">@supports</span> <span class="hljs-keyword">not</span> (<span class="hljs-attribute">display:</span> grid) {
  <span class="hljs-selector-class">.selector</span> {
    <span class="hljs-attribute">property</span>: fallback-value;
  }
}

<span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">display:</span> grid) {
  <span class="hljs-selector-class">.selector</span> {
    <span class="hljs-attribute">property</span>: actual-value;
  }
}
</code></pre>
<p>These three methods are listed in order of decreasing-complexity. (If you need to overwrite code, it's more complicated). This means writing everything in <code>@supports</code> is the simplest of the three.</p>
<p>How you choose to support your project depends on browser support for:</p>
<ol>
<li>The feature</li>
<li>The fallback feature</li>
<li>Support for Feature Queries</li>
</ol>
<h2 id="heading-checking-for-support">Checking for support</h2>
<p>The best place to check for support is <a target="_blank" href="https://caniuse.com">caniuse</a>. Here, I see that support for CSS Grid is decent. Browsers I have to worry about are:</p>
<ol>
<li>Opera Mini: 1.42% global usage</li>
<li>Android Browsers 2.1 to 4.4.4: 0.67% global usage</li>
<li>Blackberry browser: 0.02% global usage (Not gonna worry about this one).</li>
</ol>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/css-grid-support.png" alt="css-grid-support" width="600" height="400" loading="lazy"></figure>

<p>Support for the fallback (Flexbox) is also good.</p>
<p>But we have a problem: Flexbox fallback wouldn't work for Android 2.1 to 4.3 (it doesn't support wrapping). Global usage for Android 2.1 to 4.3 is 0.37%.</p>
<p>Here, I have to decide:</p>
<ol>
<li>Is providing Flexbox fallback for Opera Mini (1.42%), Android 4.4.4 (0.3%), and Blackberry (0.02%) worth the effort?</li>
<li>Should I change fallback from Flexbox to an older feature to support Android 2.1 to 4.3 (another 0.37%)?</li>
</ol>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/flexbox-support.png" alt="flexbox-support" width="600" height="400" loading="lazy"></figure>

<p>Let's assume, for this project, I decide that Flexbox fallback is sufficient. I'm not going to worry about Android 2.1 to 4.3.</p>
<p>Next, I want to check whether browsers support CSS Feature Queries.</p>
<p>Here, I see:</p>
<ol>
<li>Opera Mini supports Feature Queries</li>
<li>Android 4.4.4 supports Feature Queries</li>
<li>Blackberry browser doesn't support Feature Queries</li>
<li>IE 11 does't support Feature Queries</li>
</ol>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/feature-queries-support" alt="feature-queries-support" width="600" height="400" loading="lazy"></figure>

<h2 id="heading-deciding-how-to-write-fallback-code">Deciding how to write fallback code</h2>
<p>Earlier, I mentioned there are three ways to write fallback code for CSS:</p>
<ol>
<li>Write fallback code. Overwrite fallback code.</li>
<li>Write fallback code. Overwrite fallback code in <code>@supports</code>.</li>
<li>Write everything in <code>@supports</code>.</li>
</ol>
<p>If I write everything inside <code>@supports</code>, I can provide support for:</p>
<ol>
<li>Opera Mini (1.43%)</li>
<li>Android 4.4.4 (0.3%)</li>
</ol>
<p>But I lose support for:</p>
<ol>
<li>IE 11 (2.3%)</li>
<li>Blackberry (0.02%)</li>
</ol>
<p>I do not want to forsake the 2.3% of IE users, which means Method 3 (write everything in <code>@supports</code>) is out.</p>
<p>If I use Method 2 (Write fallback code. Overwrite fallback code in <code>@supports</code>), I can provide support for:</p>
<ol>
<li>IE 11 (2.3%)</li>
<li>Opera Mini (1.43%)</li>
<li>Android 4.4.4 (0.3%)</li>
<li>Blackberry browser (0.02%)</li>
</ol>
<p>That's everything I need. That's why I'm gonna go with Method 2.</p>
<p>Note: If you want to code along, you can use <a target="_blank" href="https://codepen.io/zellwk/pen/xNpKwp">demo</a> from <a target="_blank" href="https://zellwk.com/blog/calendar-with-css-grid">my previous article</a> as the starting point.</p>
<h2 id="heading-disabling-grid-code">Disabling Grid code</h2>
<p>First, we park the CSS Grid code under <code>@supports</code> (like we discussed above).</p>
<pre><code class="lang-css"><span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">display:</span> grid) {
  <span class="hljs-selector-class">.day-of-week</span>,
  <span class="hljs-selector-class">.date-grid</span> {
    <span class="hljs-attribute">display</span>: grid;
    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">7</span>, <span class="hljs-number">1</span>fr);
  }

  <span class="hljs-selector-class">.date-grid</span> <span class="hljs-selector-tag">button</span><span class="hljs-selector-pseudo">:first-child</span> {
    <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">6</span>;
  }
}
</code></pre>
<p>We can disable the CSS Grid code by setting <code>display</code> to an invalid value (not <code>grid</code>). This disables the entire block of code.</p>
<p>(Thank Rachel Andrew for this neat trick. I believe I learned it from her ?).</p>
<pre><code class="lang-css"><span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">display:</span> gridx) {
  <span class="hljs-comment">/*...*/</span>
}
</code></pre>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/inital-layout.png" alt="Initial layout." width="600" height="400" loading="lazy"></figure>

<h2 id="heading-writing-flexbox-code">Writing Flexbox code</h2>
<p>We need to build the same seven-column grid with Flexbox. The first thing we need to do is acknowledge that Flexbox and Grid work differently. We won't be able to get a perfect replica, but we can get close.</p>
<p>The first thing is set <code>display</code> to <code>flex</code>.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.day-of-week</span>,
<span class="hljs-selector-class">.date-grid</span> {
  <span class="hljs-attribute">display</span>: flex;
}
</code></pre>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/flexbox-1.png" alt="Results after setting display to flex." width="600" height="400" loading="lazy"></figure>

<p>We need the buttons in <code>.date-grid</code> to wrap, so we set <code>flex-wrap</code> to <code>wrap</code>.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.date-grid</span> {
  <span class="hljs-attribute">flex-wrap</span>: wrap;
}
</code></pre>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/flexbox-2.png" alt="Buttons in date grid wrapped at the edges." width="600" height="400" loading="lazy"></figure>

<p>We need to replicate the seven-column grid. An easy way to do this is calculate the width of the grid according to the width of each button. Here, I have already set each button to 4.5ch. This means the width of the grid should be <code>7 x 4.5ch</code>.</p>
<p>(We can use CSS Calc to do the math for us).</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.day-of-week</span>,
<span class="hljs-selector-class">.date-grid</span> {
  <span class="hljs-attribute">max-width</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">4.5ch</span> * <span class="hljs-number">7</span>);
}
</code></pre>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/flexbox-3.png" alt="Wrapping at 7 columns" width="600" height="400" loading="lazy"></figure>

<p>We need the elements in <code>.day-of-week</code> to spread out across the available width. One simple way is to set <code>justify-content</code> to <code>space-between</code>.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.day-of-week</span> {
  <span class="hljs-attribute">justify-content</span>: space-between;
}
</code></pre>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/flexbox-4.png" alt="After setting space-between." width="600" height="400" loading="lazy"></figure>

<p>Here, we can see that elements in <code>.day-of-week</code> extend past the grid. This extension happens because we let Flexbox calculate <code>flex-basis</code> for us. If we want every element in <code>.day-of-week</code> to be have the same width, we need to set <code>flex-basis</code> ourselves.</p>
<p>In this case, the easiest way is to set <code>flex-basis</code> to the width of one grid item (or <code>4.5ch</code>). Note: I adjusted <code>font-size</code> of each item in <code>.day-of-week</code> to <code>0.7em</code> (for visual aesthetics). We have to account for this change.</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.day-of-week</span> &gt; * {
  <span class="hljs-attribute">flex-basis</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">4.5ch</span> / <span class="hljs-number">0.7</span>);
}
</code></pre>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/flexbox-5.png" alt="Adjusted .day-of-week for size." width="600" height="400" loading="lazy"></figure>

<p>Finally, we need to push the 1 February to Friday. (Five columns). Since column is <code>4.5ch</code>, we simply push it by <code>4.5ch x 5</code>.</p>
<p>(Again, we can use CSS Calc to help us with this).</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.date-grid</span> <span class="hljs-selector-tag">button</span><span class="hljs-selector-pseudo">:first-child</span> {
  <span class="hljs-attribute">margin-left</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">4.5ch</span> * <span class="hljs-number">5</span>);
}
</code></pre>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/flexbox-6.png" alt="Pushed 1 Febuary to Friday" width="600" height="400" loading="lazy"></figure>

<h2 id="heading-fixing-the-css-grid-version">Fixing the CSS Grid version</h2>
<p>We can reactivate the CSS Grid code and make any necessary changes now.</p>
<pre><code class="lang-css"><span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">display:</span> grid) {
  <span class="hljs-comment">/* ... */</span>
}
</code></pre>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/grid-fix-1.png" alt="Activating CSS Grid code" width="600" height="400" loading="lazy"></figure>

<p>Here, we see some values fly far out to the right. This happens because we added <code>margin-left</code> to the first grid item. We need to reset the added margin.</p>
<pre><code class="lang-css"><span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">display:</span> grid) {
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-selector-class">.date-grid</span> <span class="hljs-selector-tag">button</span><span class="hljs-selector-pseudo">:first-child</span> {
    <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">6</span>;
    <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">0</span>;
  }
}
</code></pre>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/grid-fix-2.png" alt="Removed margin-left." width="600" height="400" loading="lazy"></figure>

<p>Another thing: We can remove <code>max-width</code> because we don't need it in the CSS Code. (Even though this doesn't affect the CSS Code, we still want to remove it. Always better to have less properties).</p>
<pre><code class="lang-css"><span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">display:</span> grid) {
  <span class="hljs-selector-class">.day-of-week</span>,
  <span class="hljs-selector-class">.date-grid</span> {
    <span class="hljs-attribute">display</span>: grid;
    <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">7</span>, <span class="hljs-number">1</span>fr);
    <span class="hljs-attribute">max-width</span>: initial;
  }

  <span class="hljs-comment">/* ... */</span>
}
</code></pre>
<p>Here's the visual difference between the Flexbox and CSS Grid versions. Not too bad!</p>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/difference.gif" alt="Visual difference between the Flexbox and CSS Grid code" width="600" height="400" loading="lazy"></figure>

<h2 id="heading-one-fun-thing">One fun thing</h2>
<p>CSS Grid is cool because it follows writing direction. We can easily change the flow from left-to-right to right-to-left.</p>
<p>Note: I don't know if calendars are read from right to left in rtl languages. I just thought it'll fun to mention this ?).</p>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/rtl.gif" alt="Switching between ltr and rtl." width="600" height="400" loading="lazy"></figure>

<p>Our code for CSS Grid supports this behaviour naturally. If you want to support the same behaviour with Flexbox, you need to use <a target="_blank" href="https://css-tricks.com/css-logical-properties/">CSS Logical Properties</a>.</p>
<figure><img src="https://zellwk.com/images/2019/calendar-flexbox/css-logical-properties-support.png" alt="Support for CSS Logical Properties." width="600" height="400" loading="lazy"></figure>

<p>Since support for CSS Logical Properties is not-so-great, we need to provide fallback for it. (Best way is to through Method 1: Write fallback; overwrite fallback).</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.date-grid</span> <span class="hljs-selector-tag">button</span><span class="hljs-selector-pseudo">:first-child</span> {
  <span class="hljs-attribute">margin-left</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">4.5ch</span> * <span class="hljs-number">5</span>);
  <span class="hljs-attribute">margin-inline-start</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">4.5ch</span> * <span class="hljs-number">5</span>);
}

<span class="hljs-keyword">@supports</span> (<span class="hljs-attribute">display:</span> grid) {
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-selector-class">.date-grid</span> <span class="hljs-selector-tag">button</span><span class="hljs-selector-pseudo">:first-child</span> {
    <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">6</span>;
    <span class="hljs-attribute">margin-left</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">margin-inline-start</span>: <span class="hljs-number">0</span>;
  }
}
</code></pre>
<p>That's it! Here's a Codepen for the final code:</p>
<p></p><p>
  <span>See the Pen <a href="https://codepen.io/zellwk/pen/ZNrezV/">
  Building a Calendar with CSS Grid (and fallback with Flexbox)</a> by Zell Liew (<a href="https://codepen.io/zellwk">@zellwk</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p><p></p>


<hr>

<p>Thanks for reading. This article was originally posted on <a target="_blank" href="https://zellwk.com/blog/calendar-flexbox-fallback">my blog</a>. Sign up for <a target="_blank" href="https://zellwk.com">my newsletter</a> if you want more articles to help you become a better frontend developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to build a calendar with CSS Grid ]]>
                </title>
                <description>
                    <![CDATA[ Building a calendar with CSS Grid is actually quite easy. I want to show you how to do it. Here's what you'll create by the end of this article: Creating the HTML You can tell from the image that the calendar contains three parts: The month indica... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-build-a-calendar-with-css-grid/</link>
                <guid isPermaLink="false">66c4c73f1b22d2d8d9040ed7</guid>
                
                    <category>
                        <![CDATA[ CSS Grid ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Wed, 17 Jul 2019 00:15:36 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca16b740569d1a4ca4e77.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Building a calendar with CSS Grid is actually quite easy. I want to show you how to do it.</p>
<p>Here's what you'll create by the end of this article:</p>
<figure><img src="https://zellwk.com/images/2019/calendar-css-grid/calendar-fixed.png" alt="A calendar built with CSS Grid" width="600" height="400" loading="lazy"></figure>

<h1 id="heading-creating-the-html">Creating the HTML</h1>
<p>You can tell from the image that the calendar contains three parts:</p>
<ol>
<li>The month indicator</li>
<li>The weekday/weekend indicator</li>
<li>The dates themselves</li>
</ol>
<figure><img src="https://zellwk.com/images/2019/calendar-css-grid/structure.png" alt="Structure of the calendar" width="600" height="400" loading="lazy"></figure>

<p>The best way to structure the HTML is to go with what feels right. We'll create the HTML according to these three sections:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"calendar"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"month-indicator"</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"day-of-week"</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"date-grid"</span>&gt;</span>...<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>You should also be able to see we need seven columns for the grid.</p>
<figure><img src="https://zellwk.com/images/2019/calendar-css-grid/seven-columns.png" alt="Seven columns required for the grid" width="600" height="400" loading="lazy"></figure>

<p>We'll focus the conversation on <code>.day-of-week</code> and <code>.date-grid</code> since we're only talking about grid.</p>
<h2 id="heading-structuring-the-grid">Structuring the grid</h2>
<p>There are two ways to create the CSS Grid.</p>
<p>The first way is to merge elements within <code>.day-of-week</code> and <code>.date-grid</code> into one selector. If we do this, we can set the selector in <code>display: grid</code>. Here's what the HTML would have looked like if we did this:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"grid"</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- Day of week --&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Su<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Mo<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Tu<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>We<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Th<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Fr<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Sa<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

  <span class="hljs-comment">&lt;!-- Dates --&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">time</span> <span class="hljs-attr">datetime</span>=<span class="hljs-string">"2019-02-01"</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">time</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">time</span> <span class="hljs-attr">datetime</span>=<span class="hljs-string">"2019-02-02"</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">time</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">time</span> <span class="hljs-attr">datetime</span>=<span class="hljs-string">"2019-02-03"</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-name">time</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- ... --&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">time</span> <span class="hljs-attr">datetime</span>=<span class="hljs-string">"2019-02-28"</span>&gt;</span>28<span class="hljs-tag">&lt;/<span class="hljs-name">time</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>I discourage this method because the HTML loses its structural meaning. I prefer keeping <code>.day-of-week</code> and <code>date-grid</code> as separate elements if possible. This makes it easy for me to read/understand the code I've written.</p>
<p>Here's the HTML structure i chose to go with:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"day-of-week"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Su<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Mo<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Tu<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>We<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Th<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Fr<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Sa<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"date-grid"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">time</span> <span class="hljs-attr">datetime</span>=<span class="hljs-string">"2019-02-01"</span>&gt;</span>1<span class="hljs-tag">&lt;/<span class="hljs-name">time</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">time</span> <span class="hljs-attr">datetime</span>=<span class="hljs-string">"2019-02-02"</span>&gt;</span>2<span class="hljs-tag">&lt;/<span class="hljs-name">time</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">time</span> <span class="hljs-attr">datetime</span>=<span class="hljs-string">"2019-02-03"</span>&gt;</span>3<span class="hljs-tag">&lt;/<span class="hljs-name">time</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- ... --&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">time</span> <span class="hljs-attr">datetime</span>=<span class="hljs-string">"2019-02-28"</span>&gt;</span>28<span class="hljs-tag">&lt;/<span class="hljs-name">time</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>The best way to create a CSS Grid with the structure I proposed is to use subgrid. Unfortunately, most browsers don't support subgrid yet. In the meantime, the best way is to create two separate grids—one for <code>.day-of-week</code> and one for <code>.date-grid</code>.</p>
<p>Both <code>.day-of-week</code> and <code>.date-grid</code> can use the same seven-column grid.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* The grid */</span>
<span class="hljs-selector-class">.day-of-week</span>,
<span class="hljs-selector-class">.date-grid</span> {
  <span class="hljs-attribute">display</span>: grid;
  <span class="hljs-attribute">grid-template-columns</span>: <span class="hljs-built_in">repeat</span>(<span class="hljs-number">7</span>, <span class="hljs-number">1</span>fr);
}
</code></pre>
<figure><img src="https://zellwk.com/images/2019/calendar-css-grid/calendar-grid.png" alt="1 Feb 2019 begins on a Friday" width="600" height="400" loading="lazy"></figure>

<h2 id="heading-pushing-the-dates">Pushing the dates</h2>
<p>February 2019 begins on a Friday. If we want the calendar to be correct, we need to make sure:</p>
<ol>
<li>1 Feb 2019 falls on Friday</li>
<li>2 Feb 2019 falls on Saturday</li>
<li>3 Feb 2019 falls on Sunday</li>
<li>And so on...</li>
</ol>
<p>With CSS Grid, this part is easy.</p>
<p>CSS Grid has placement algorithm that kinda follows the following rules (if you didn't set <code>grid-auto-flow</code> to <code>dense</code>):</p>
<ol>
<li>Place items that has explicit <code>grid-column</code> or <code>grid-row</code> first</li>
<li>Fill in the rest according to the last-placed item</li>
</ol>
<p>What this means is:</p>
<ol>
<li>If the first item falls on column 6</li>
<li>The second item will be placed in column 7.</li>
<li>The third item will be placed on the next row, in column 1 (because there are only seven columns).</li>
<li>The fourth item will be placed in column 2,</li>
<li>And so on...</li>
</ol>
<p>So, if we position 1 February on the sixth column (friday), the rest of the dates will be placed correctly.</p>
<p>Simple as that!</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Positioning the first day on a Friday */</span>
<span class="hljs-selector-class">.date-grid</span> <span class="hljs-selector-tag">button</span><span class="hljs-selector-pseudo">:first-child</span> {
  <span class="hljs-attribute">grid-column</span>: <span class="hljs-number">6</span>;
}
</code></pre>
<figure><img src="https://zellwk.com/images/2019/calendar-css-grid/calendar-fixed.png" alt="1 Feb 2019 begins on a Friday" width="600" height="400" loading="lazy"></figure>

<p>Here's a codepen for you to play with:</p>
<p></p><p>
  <span>See the Pen <a href="https://codepen.io/zellwk/pen/xNpKwp/">
  Building a Calendar with CSS Grid</a> by Zell Liew (<a href="https://codepen.io/zellwk">@zellwk</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p><p></p>


<h2 id="heading-want-to-learn-more">Want to learn more?</h2>
<p>This article contains one fraction of a component (a datepicker) from Learn JavaScript. There's so much more I want to show you. (But they're mostly JavaScript related topics).</p>
<p>For example, in Learn JavaScript, I show you how to:</p>
<ol>
<li>Build a calendar for any month (and any year)</li>
<li>Add a previous/next button to switch between months</li>
<li>Click on each date to display a date</li>
</ol>
<p>Here's what it looks like:</p>
<figure><img src="https://zellwk.com/images/2019/calendar-css-grid/datepicker.gif" alt="Example of the datepicker in action" width="600" height="400" loading="lazy"></figure>

<hr>

<p>Thanks for reading. This article was originally posted on <a target="_blank" href="https://zellwk.com/blog/calendar-with-css-grid">my blog</a>. Sign up for <a target="_blank" href="https://zellwk.com">my newsletter</a> if you want more articles to help you become a better frontend developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Stages of learning ]]>
                </title>
                <description>
                    <![CDATA[ Over time, I realized there are five stages of learning. Awareness Panic Avoidance Acceptance Learning Awareness "Oh! This is possible?!" "Ah, so that's how you solve this". "This is good. I need to learn this". In the awareness stage, you learn ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/stages-of-learning/</link>
                <guid isPermaLink="false">66c4c79c1b22d2d8d9040ee5</guid>
                
                    <category>
                        <![CDATA[ learning ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Wed, 03 Jul 2019 17:50:37 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca1ba740569d1a4ca504f.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Over time, I realized there are five stages of learning.</p>
<ol>
<li>Awareness</li>
<li>Panic</li>
<li>Avoidance</li>
<li>Acceptance</li>
<li>Learning</li>
</ol>
<h2 id="heading-awareness">Awareness</h2>
<ul>
<li>"Oh! This is possible?!"</li>
<li>"Ah, so that's how you solve this".</li>
<li>"This is good. I need to learn this".</li>
</ul>
<p>In the awareness stage, you learn about a problem. And you realize you need to find a solution.</p>
<h2 id="heading-panic">Panic</h2>
<p>Panic might come to some people. This depends on how much pressure you put on yourself. If you pressure yourself hard, you'll get into panic mode.</p>
<p>If you set a deadline for learning, you're giving yourself pressure. Most people don't realize this. They set an ambitious deadline for themselves and they fail hard.</p>
<p>If you set a deadline to learn something, that deadline you set is probably ambitious. It's ambitious because learning usually takes more time and effort than you account for.</p>
<p>If you put too much pressure on yourself, you may get overwhelmed. You may look for shortcuts instead of actually learning what you're supposed to learn.</p>
<h2 id="heading-avoidance">Avoidance</h2>
<p>When panic/overwhelm sets in, we tend to avoid what we're doing.</p>
<ul>
<li>"I can't do this right now"</li>
<li>"I'm not smart enough"</li>
<li>"I need a break"</li>
<li>"Life happens"</li>
</ul>
<p>We give ourselves <span class="strikeout"> excuses </span> permission to drop the thing we're learning.</p>
<p>It's okay to pause for a breather if you can't catch your breath. We all need a breather sometimes. But it's not okay to give up. (Unless you decide it's something you never wanted to do for the rest of your life. In which case, giving up is a good choice).</p>
<p>The unfortunate thing is: Some people never realize they're avoiding. They search the internet, hoping to find "good tutorials" that'll teach them everything they need to know. And they use "I can't find any good tutorials" as an excuse not to learn.</p>
<h2 id="heading-acceptance">Acceptance</h2>
<p>This is where you accept you bit off more than you can chew, and decide to chew it anyway. You accept the tough challenge ahead. And you prepare to face it head-on.</p>
<p>For most people, it's when they say "I'm going to fucking learn this no matter what".</p>
<p>This is when we dedicate the necessary resources, time, and energy to learn the thing we need to learn.</p>
<p>If you get into this mode, anything you learn stays with you for a long time. Before this stage, you don't actually learn. You may remember something for a short while, but you'll forget about it quickly.</p>
<h2 id="heading-learning">Learning</h2>
<p>And so learning begins.</p>
<p>We read everything we need to read.</p>
<p>We do everything we need to do.</p>
<p>We code if we have to.</p>
<p>We think if we have to.</p>
<p>We get our hands dirty if we have to.</p>
<p>Learning is like a marathon. There's no best pace. All we have is the pace we're comfortable with. And the pace changes according to our states.</p>
<ul>
<li>If we go too slow, we get bored.</li>
<li>If we go too fast, we get into an overwhelmed or panic state.</li>
</ul>
<p>So what's important is to pace yourself. Take it step by step. Go slow if you're running out of breath, and run faster if you're getting bored.</p>
<p>At a certain point, we may decide we learned enough.</p>
<p>And learning stops.</p>
<h2 id="heading-mastery">Mastery</h2>
<p>Mastery is a continuous process where you learn more and more things about the same subject. You get deeper into the subject and you're able to sieve out the nuances.</p>
<p>Mastery comes with repeated learning. It comes with going through the five stages over and over again.</p>
<ol>
<li>Awareness</li>
<li>Panic</li>
<li>Avoidance</li>
<li>Acceptance</li>
<li>Learning</li>
</ol>
<p>With enough time, you'll become a master one thing.</p>
<hr>

<p>This article was originally posted on <a target="_blank" href="https://zellwk.com/blog/stages-of-learning">my blog</a>. Sign up for <a target="_blank" href="https://zellwk.com">my newsletter</a> if you want more articles to help you become a better frontend developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Shutting down Fridays with Zell ]]>
                </title>
                <description>
                    <![CDATA[ If you stuck around for a while, you might have noticed I used to post a video (and an audio) every Friday for most of 2018. I call them "Fridays with Zell". In 2019, I decided to stop making videos. I want to share why I decided to stop making ]]>
                </description>
                <link>https://www.freecodecamp.org/news/https-zellwk-com-blog-shutting-down-fridays-with-zell/</link>
                <guid isPermaLink="false">66c4c781d788a9c53d88d2e9</guid>
                
                    <category>
                        <![CDATA[ podcast ]]>
                    </category>
                
                    <category>
                        <![CDATA[ thoughts ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Wed, 26 Jun 2019 23:31:28 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca1d5740569d1a4ca50fa.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you stuck around for a while, you might have noticed I used to post a video (and an audio) every Friday for most of 2018. I call them "Fridays with Zell".</p>
<p>In 2019, I decided to stop making videos. I want to share why I decided to stop making videos.</p>
<h2 id="heading-why-i-started-making-videos">Why I started making videos</h2>
<p>I started making videos because of three reasons:</p>
<ol>
<li>I thought it would be fun.</li>
<li>It would be good practice if I want to release video-based courses in    the future.</li>
<li>I heard good things about video helping to bring more subscribers</li>
</ol>
<p>I finally got a chance to try making videos at the start of 2018. I committed for one year (and made 44 videos in total). That's approximately 1 video per week.</p>
<h2 id="heading-why-im-shutting-down-fridays-with-zell">Why I'm shutting down Fridays with Zell.</h2>
<p>Two reasons:</p>
<ol>
<li>Videos don't bring me additional subscribers</li>
<li>Video-making is not fun for me</li>
</ol>
<p>I should probably say more about each statement, so here we go.</p>
<h3 id="heading-videos-dont-bring-me-additional-subscribers">Videos don't bring me additional subscribers</h3>
<p>Here's a chart of subscribers in 2018 and in 2019.
Green bars indicate the number of new subscribers.</p>
<figure><img src="https://zellwk.com/images/2019/shutting-fridays-with-zell/subs.png" alt="Subscriber count hovered around 250 a week with or without videos" width="600" height="400" loading="lazy"></figure>

<p>The number of new subscribers hovered around 250 per week from 1st January 2018 to 22 May 2019. I stopped posting videos in January 2019, but the number of subscribers remained at 250 per week.</p>
<p>This tells me the videos didn't bring in new subscribers. My videos were mostly watched by people who are already following me.</p>
<h3 id="heading-video-making-is-not-fun">Video-making is not fun</h3>
<p>A lot of work goes into creating videos.</p>
<ol>
<li>I had to put myself in front of the camera</li>
<li>Speak in a manner that doesn't feel too fake</li>
<li>Edit the hell out of what I spoke (the hard part)</li>
<li>Write an article that goes along with the video</li>
</ol>
<p>Points 3 and 4 are killers.</p>
<p>I loathe the editing process. I hate scrubbing and trimming the audio. This process is not fun at all. I would rather do ANYTHING else than edit a video.</p>
<p>Plus, converting a video into an article takes a hell lot of work too. I have to write a transcript of what transpired in the video, create images, and write an article that flows.</p>
<p>It's not fun.</p>
<p>It's too much work.</p>
<p>I got burned out.</p>
<p>So I decided to stop.</p>
<h2 id="heading-will-i-ever-make-videos-again">Will I ever make videos again?</h2>
<p>I can't say for sure. Maybe I will make videos again when the dread fades away. But if I ever start making videos again, I'll do it in a different way.</p>
<h2 id="heading-final-words">Final words</h2>
<p>You won't know whether you should (or shouldn't) do something until you've done it.</p>
<p>Give it a try.</p>
<p>You can always walk away if it's not for you.</p>
<p>If you walk away, you'll know why it's not for you. You'll have a better idea about what you want/don't want to do. And you can focus better on the next thing.</p>
<p>Sometimes, what's right for you now doesn't mean it's always going to be right for you.</p>
<p>Keep experimenting, and continue to challenge your assumptions.</p>
<hr>

<p>Thanks for reading. This article was originally posted on <a target="_blank" href="https://zellwk.com/blog/shutting-down-fridays-with-zell">my blog</a>. Sign up for <a target="_blank" href="https://zellwk.com">my newsletter</a> if you want more articles to help you become a better frontend developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Use Standard with VSCode ]]>
                </title>
                <description>
                    <![CDATA[ I use Visual Studio Code as my text editor. When I write JavaScript, I follow JavaScript Standard Style.   There's an easy way to integrate Standard in VS Code—with the vscode-standardjs plugin. I made a video for this some time ago if you're interes... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/https-zellwk-com-blog-standard-with-vscode/</link>
                <guid isPermaLink="false">66c4c78326a77d9936ef0a8a</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Visual Studio Code ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Fri, 14 Jun 2019 04:58:21 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca207740569d1a4ca5214.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>I use <a target="_blank" href="https://code.visualstudio.com/">Visual Studio Code</a> as my text editor. When I write JavaScript, I follow <a target="_blank" href="https://standardjs.com">JavaScript Standard Style</a>.  </p>
<p>There's an easy way to integrate Standard in VS Code—with the <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=chenxsan.vscode-standardjs">vscode-standardjs</a> plugin. I made a <a target="_blank" href="https://youtu.be/Hv8FgxJyI9Y">video</a> for this some time ago if you're interested in setting it up.  </p>
<p>But, if you follow the instructions in the video (or on vscode-standardjs's readme file), you'll come to notice there's one small detail that needs to be ironed out.  </p>
<p>Try writing a <code>function</code> the old way, and save it repeatedly. VS code will toggle between having and not having a space before the left-parenthesis of the function.</p>
<figure><img src="https://zellwk.com/images/2019/vscode-standard/functions.gif" alt="VS code toggles between having and not having a space before '('." width="600" height="400" loading="lazy"></figure>

<p>You get the same problem when you write methods with the ES6 method shorthands:</p>
<figure><img src="https://zellwk.com/images/2019/vscode-standard/methods.gif" alt="Same problem happens when you create methods with ES6 method shorthands." width="600" height="400" loading="lazy"></figure>

<p>There's a quick way to fix this issue. What you need to do is set <code>javascript.format.enable</code> to <code>false</code>. This disables VS Code's default Javascript formatter (and lets vscode-standandjs does the formatting work).</p>
<p>So the minimum configuration you need to get Standard and VS Code to work together is:</p>
<pre><code>{
  <span class="hljs-comment">// Prevents VS Code from formatting JavaScript with the default linter</span>
  <span class="hljs-string">"javascript.format.enable"</span>: <span class="hljs-literal">false</span>,

  <span class="hljs-comment">// Prevents VS Code linting JavaScript with the default linter</span>
  <span class="hljs-string">"javascript.validate.enable"</span>: <span class="hljs-literal">false</span>,

  <span class="hljs-comment">// Lints with Standard JS</span>
  <span class="hljs-string">"standard.enable"</span>: <span class="hljs-literal">true</span>,

  <span class="hljs-comment">// Format files with Standard whenever you save the file</span>
  <span class="hljs-string">"standard.autoFixOnSave"</span>: <span class="hljs-literal">true</span>,

  <span class="hljs-comment">// Files to validate with Standard JS</span>
  <span class="hljs-string">"standard.validate"</span>: [
    <span class="hljs-string">"javascript"</span>,
    <span class="hljs-string">"javascriptreact"</span>
  ]
}
</code></pre><hr>
<p><em>This article was originally posted on <a target="_blank" href="https://zellwk.com/blog/standard-with-vscode">my blog</a>.</em><br><em>Sign up for my <a target="_blank" href="https://zellwk.com/">newsletter</a> if you want more articles to help you become a better frontend developer.</em></p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to go through the job application process—an interview with Chris Lienert ]]>
                </title>
                <description>
                    <![CDATA[ "Do you have any advice on finding a job as a developer?" Many people have asked me that question, but I can’t give a proper answer because I have never been hired as a developer before. What I did was: Wriggled my way into a Wordpress dev role in a... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-go-through-the-job-application-process-an-interview-with-chris-lienert-2/</link>
                <guid isPermaLink="false">66c4c754bd556981b1bdc474</guid>
                
                    <category>
                        <![CDATA[ interview ]]>
                    </category>
                
                    <category>
                        <![CDATA[ job ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Thu, 06 Jun 2019 03:25:00 +0000</pubDate>
                <media:content url="https://cdn-media-2.freecodecamp.org/w1280/5f9ca22a740569d1a4ca52f8.jpg" medium="image" />
                <content:encoded>
                    <![CDATA[ <div class="embed-wrapper"><iframe height="200px" width="100%" src="https://player.simplecast.com/ee1dd3d6-1f4c-43a2-a4e3-dd502550c629?dark=false" title="Embedded content" loading="lazy"></iframe></div>

<p>"Do you have any advice on finding a job as a developer?"</p>
<p>Many people have asked me that question, but I can’t give a proper answer because I have never been hired as a developer before. What I did was:</p>
<ol>
<li>Wriggled my way into a Wordpress dev role in an admin-based internship</li>
<li>Freelanced</li>
<li>Run my own company</li>
</ol>
<p>So I'm horribly inadequate at answering a question about finding a job. </p>
<p>But Chris Lienert is an expert at it. Chris has experience hiring and building teams of excellent developers. (A fun aside: He used to co-run CSS Singapore, which is a monthly CSS Meetup in Singapore). </p>
<p>I managed to grab Chris (before he left Singapore for good) and asked him to talk about the job application process. You'll hear golden advice in this interview from Chris, like:</p>
<ol>
<li>Chris' opinions about the hiring process. </li>
<li>How to improve your chances of getting an interview</li>
<li>What to do if you don't get a job</li>
<li>How you should write your CV </li>
<li>What to do during the actual interview</li>
<li>What questions to ask during the interview </li>
<li>How to answer any tricky questions you get</li>
</ol>
<p>Note: We jumped around a lot in this 1.5 chat because Chris has so much to say about this topic. I highly recommend you listen to the audio version if you can. </p>
<p>To make it easier for you to digest, I also summarized what we talked about into three stages:</p>
<ol>
<li>Preparing your CV/Resume</li>
<li>Before you apply for a job</li>
<li>The interview process</li>
</ol>

<h2 id="heading-your-cv-resume">Your CV / Resume</h2>
<p>It's hard to write a CV. On one hand, you want to pad it with enough information to make you attractive. On the other hand, you want to keep it short enough for recruiters to not hate you. </p>
<p>(Note: I use the word "recruiter" to describe anyone who participates in the hiring process). </p>
<p>We'll first talk about three keys to writing a CV before we talk about the structure of the CV. The three keys are: </p>
<ol>
<li>The Crayon Test </li>
<li>Keywords</li>
<li>Differentiate yourself</li>
</ol>
<h3 id="heading-the-crayon-test">The Crayon Test</h3>
<p>Recruiters are busy. They have to go through hundreds of applications for each job opening. </p>
<p><strong>This means recruiters will scan through your CV</strong> quickly. They'll put away your CV immediately if there are any spelling errors. They will also put away your CV if you miss out any important information (like your email or phone number). </p>
<p>Chris calls this The Crayon Test. (Because it tests whether the candidate is able to fulfil  basic requirements like spelling their name correctly). </p>
<p>What you should do is <strong>make sure your CV is clear and understandable</strong>. It should not have any spelling mistakes. It should contain the necessary information a recruiter needs to contact you. </p>
<h3 id="heading-keywords">Keywords</h3>
<p><strong>Make sure you have the right keywords</strong> for the position you want to apply for. For example, if the job ad is for a "React Developer", make sure you have "React" somewhere on your Resume. </p>
<p>You need to do this because people (and machines) scan your CVs for keywords. If you don't have the necessary keyword(s) in your CV, you'll get passed over for someone else EVEN before you get an interview. </p>
<p>Back to the "React Developer" example. If you don't have enough confidence in React, you still need to find a way to put React in your CV. Good ways to include keywords (if you don't have the skill) is to put them under Job Experience or Community. More on this in the CV structure below. </p>
<h3 id="heading-differentiate-yourself">Differentiate yourself</h3>
<p>What makes you different from thousands of other applicants out there? </p>
<p>If you're a fresh graduate, the answer is nothing. </p>
<p>You need to make it SOMETHING. </p>
<p>There are a variety of ways to talk about your passion and experience in this industry (even if you haven't got a job yet). Some ways include: </p>
<ol>
<li>Notable Codepen projects</li>
<li>Your projects on Github</li>
<li>Things you built before (on your own, not by following tutorials!). </li>
<li>Articles you've written </li>
<li>Contributing to open source </li>
</ol>
<p>Most of these can go into the "Community" section of your CV. More on this later. </p>
<h3 id="heading-length-of-your-cv">Length of your CV</h3>
<p>Your CV should be short. Keep it to 1-2 pages if you're starting out. </p>
<p>As you gain more experience and want to switch to more senior roles, your CV can go beyond 2 pages. (Chris' CV is four pages longs. It needs to be that long to show he has the qualifications for a job at his level). </p>
<h3 id="heading-the-structure-of-your-cv">The structure of your CV</h3>
<p>The structure we're proposing here is drawn from Chris' experience. You may find conflicting information elsewhere on the internet. Take what you need. </p>
<p>Your CV should contain the following things: </p>
<ol>
<li>Contact Details </li>
<li>Summary </li>
<li>Skills</li>
<li>Experience </li>
<li>Education</li>
<li>Community</li>
<li>References</li>
</ol>
<p><strong>Contact Details</strong>: This section should contain information about yourself. You need to have these three items to pass the Crayon Test: </p>
<ol>
<li>Your name</li>
<li>Your email address</li>
<li>Your phone number</li>
</ol>
<p><strong>Summary</strong>: Summary is a one-liner of what you're looking for. You want to be clear here. For example, "I'm looking to be a frontend developer in a great team" is a good one-liner. </p>
<p><strong>Skills</strong>: This is where you showcase 5-10 skills you're good at. No need to put version numbers because they're irrelevant. Example: </p>
<ol>
<li>HTML </li>
<li>CSS</li>
<li>JavaScript</li>
<li>Node</li>
<li>Making simple web animations</li>
</ol>
<p>There's no need to list your years of experience on a skill. It doesn't matter. If you work hard, you can become great in 12 months.</p>
<p>Don't lie about your skills. Only put the ones you're confident in because you may get questions on each of them. </p>
<p><strong>Experience</strong>: This is where you write about your job experience. For each job experience, you should have: </p>
<ol>
<li>The company name </li>
<li>A one-liner explaining what they do</li>
<li>When and the duration you worked on this job </li>
<li>3 bullet points of what you learned from this job that's relevant for the position you're applying for. </li>
</ol>
<p>It's a good pattern to have at least 18 months to 2 years per job experience. </p>
<p>If you have a time-gap between jobs, you want to state what you did during the gap. Freelancing, backpacking, etc. Stating this gives insight into how you developed yourself since school. </p>
<p>If your experience is not relevant to the job (like if you're a waiter/waitress), then simply say that and move on. </p>
<p>Please DO NOT LIST the things you DON'T want to do. It might get you the job, but you'll be miserable in it. </p>
<p><strong>Education</strong>: This is where you list your education experience.  Create some bullet points if you have experience that's relevant to the position you apply for. Otherwise, just list your certification and move on. </p>
<p><strong>Community</strong>: This is where you can stand out if you don't have prior job experience. Here, you want to talk about what you do for/in the web community. You can include things like: </p>
<ol>
<li>Attending conferences</li>
<li>Attending meetups </li>
<li>Talks you gave </li>
<li>Articles you wrote (that's not on your own blog) </li>
<li>Videos you made </li>
</ol>
<p>One way to game the keywords (if you need to) is to include the keyword in the title of your talk/article/video. </p>
<p><strong>References</strong>: References are people who vouch for you. They can be hard to get in the early days of your career. Omit if you don't have any. </p>
<h3 id="heading-your-cover-letter">Your cover letter</h3>
<p>Some companies require a cover letter. Keep it short if you need to write one. You don't need an essay for our industry. </p>
<p>Your cover letter should contain these three paragraphs (in your own words): </p>
<ul>
<li>Paragraph 1: "Hi, I'm X. I saw your job. It looks good and I want to apply". </li>
<li>Paragraph 2: Why you fit the role</li>
<li>Paragraph 3: You can reach me at [this number]. </li>
</ul>
<h2 id="heading-before-you-apply">Before you apply</h2>
<p>Most job requirements seem daunting. Everyone is looking for some JavaScript experience. Everyone want React Developers. Some even want Full Stack developers. </p>
<p>What can you do? </p>
<p>We'll talk about four important things you need to understand. Some may create a paradigm shift for you. They are: </p>
<ol>
<li>Why some job ads suck</li>
<li>Imposter Syndrome and minorities</li>
<li>The "Full Stack" developer </li>
<li>Keep applying</li>
</ol>
<h3 id="heading-why-some-job-ads-suck">Why some job ads suck</h3>
<p>The person who hires for the person and the person who crafts the job ad may be different people. This is especially true in large companies. </p>
<p>If the person who crafts the job ad knows nothing about the industry, they may require "10 years of React experience" even though React has been out only for 6. This is why you see jokes about bad job requirements all over the place. </p>
<p>To put your bias aside, people do try to improve their job ads. Chris, for example, does this. </p>
<p>In the interview, Chris shared about an experience where he rewrote a job ad. And he gave the HR strict instructions to post the job as it is. But when Chris looked at the actual advertisement, he didn't recognize the ad. It was butchered badly. </p>
<p>The key takeaway here is: Don't be too concerned about what's written on the job ad. It might have been inflated with unreasonable demands. </p>
<h3 id="heading-imposter-syndrome-and-minorities">Imposter Syndrome and minorities</h3>
<p>If you feel like a minority, you've labeled yourself as a minority. It doesn't matter if you're a white male, or a black woman, or an Asian, or anything else. Chris, for example, is a white male that feels like a minority because he doesn’t feel like he easily fits with anyone else.</p>
<p>The thing about minorities is minorities have high rates of Imposter Syndrome. </p>
<ul>
<li>They wonder if they're qualified for the job. </li>
<li>They wonder why people should pick them over so many qualified candidates out there. </li>
</ul>
<p>As a result, most minorities only apply to when they feel they're qualified for the job. This means apply to jobs if they can meet 80% of the job requirement. (On the other hand, majority candidates apply for a job if they meet 30% of the job requirements). </p>
<p>This is insane. </p>
<p>Minorities are usually better candidates because they have to fight through lots of barriers. They have better skills, better attitude, they work harder, and they know more about they're doing. </p>
<p>What this means is: If you're a minority candidate, please apply to more jobs. Apply to jobs even if you don't meet 80% (or 100%!) of the requirements. </p>
<p>Don't worry about meeting the requirements. Apply if you are confident you'll be able to do the job (and you're able to learn on the job). </p>
<p>Job ads are often inflated. Remember that.</p>
<h3 id="heading-the-full-stack-developer">The Full-stack developer</h3>
<p>Many jobs require a "Full Stack" developer experience. This puts pressure on developers to learn the "Full" stack (and it makes them feel inadequate in the process). </p>
<p>But how full is a "Full Stack"? Do you need to know databases? Do you need to know how to write server code? Design? Draw? UX? There's no concrete definition for a Full-stack developer. </p>
<p>Most companies don't actually want to look for a full-stack developer. They <em>think</em> they want to look for a full-stack developer based on what they know. </p>
<p>They'll only interview you if your CV matches what they think is "Full Stack". They might be wrong. And they might not even know what they need. </p>
<p>What this means is: Don't worry about getting a full-stack experience. Read the job description, apply, and ask questions during the interview (more on this later). </p>
<h3 id="heading-keep-applying">Keep applying</h3>
<p>It can be dispiriting to apply for jobs. You'll get rejected (many times without even knowing). It sucks. </p>
<p>It doesn't matter where you are in your career. If you're looking for jobs, the same thing will happen. You'll still get rejected. </p>
<p>Chris is a top qualified candidate in what he does. He shared with me that during his recent job search process, he applied for 16 jobs, but only heard back from 3. </p>
<p>Even Chris can't get interviews at places. (I thought Chris wouldn't have a problem with finding jobs). But this just shows how messy the hiring process can be. </p>
<p>It's hard to get over a rejection. You're emotionally invested in the process, so it becomes especially hard. </p>
<p>But you got to keep applying for jobs. You have to continue to review your CV and Cover letter. </p>
<p>Don't give up. You'll get a job eventually if you keep it up. </p>
<h2 id="heading-during-the-interview">During the interview</h2>
<p>Interviews are nerve-racking. We'll talk about five things in this section:  </p>
<ol>
<li>Feeling nervous </li>
<li>Whiteboard interviews</li>
<li>Answering tricky questions</li>
<li>Questions to ask</li>
<li>Be honest </li>
</ol>
<h3 id="heading-feeling-nervous">Feeling nervous</h3>
<p>You are going to be nervous. You're going to be frightened out of your mind. It's normal because you're getting tested. </p>
<p>You will stumble as you answer questions. You will get something wrong during the interview (only to remember the actual answer later on). </p>
<p>It's okay to be nervous and mess because everyone will be nervous and mess. </p>
<p>Hopefully, this makes you feel better. The more relaxed you can be, the better. But don't stress yourself to be relaxed. </p>
<h3 id="heading-whiteboard-interviews">Whiteboard interviews</h3>
<p>Whiteboard interviews suck because people test you on the wrong things. You won't be writing code on the whiteboard in your job, so it makes no sense to create a whiteboard interview. </p>
<p>Chris argues that interviewers should mirror the person's job as much as possible during the interview. If you're hiring a developer, you'd want to put a laptop in front of them. </p>
<p>If you want to observe what they do, you can mirror the laptop onto a screen so you can observe from afar. This way, the developer can focus on coding. </p>
<p>We didn't answer how to tackle a whiteboard interview during the chat, but you might want to take what Chris said in mind. Maybe you can request for the interviewer to put you in a comfortable space to perform? It's not always possible, but it might make you stand out in the right way :). </p>
<h3 id="heading-answering-tricky-questions">Answering tricky questions</h3>
<p>You will face at least three tricky questions during most interviews. They are: </p>
<ol>
<li>What's your strengths and weaknesses?</li>
<li>Where do you see yourself in 3-5 years?</li>
<li>Why did you leave your previous job? </li>
</ol>
<p>You'd want to prepare answers for these questions (and any others you can find). Chris has some thoughts on how you should answer. </p>
<p><strong>What's your strengths and weaknesses?</strong></p>
<p>There are <em>no good answers</em> for this question. What you want to do is avoid any bad answers that can skew what the interviewer thinks of you. </p>
<p>The key is to be honest while being tactful. You can't be boastful because they'll take note. </p>
<p>When you answer the question about your weakness, you want to say what you're doing about it and explain why you're good for the job. </p>
<p>Here's an example Chris gave: </p>
<p>I was a team leader for 10 years. In the first five years, I didn't understand what being a team leader was about. I focused on myself. It took me a while to realize that the benefit I provide as a leader is what we produce as a team and not what I produce as an individual. </p>
<p>My weakness then was I was too focused on the individual and not very a good leader. And I did something about it. </p>
<p>My weakness now is: I'm not technically as strong as I used to be, because I spend more time making sure everyone is doing their job properly and happily than focusing on my technical side. </p>
<p>(This weakness makes a great manager). </p>
<p><strong>Where do you see yourself in 3-5 years time?</strong> </p>
<p>This question gives an insight into what you're looking for. If you say something along the lines of moving up the career ladder, it hints that you're not interested in the job itself. </p>
<p>If you're looking to be a frontend developer, a good example is to say you see yourself coding for the company. Keep it direct and straightforward. </p>
<p>Example from Chris: "My focus then is a job where I can code. My focus now is to make the company I'm working for succeed. I'm going to code really well and lead the team really well. </p>
<p><strong>Why did you leave your previous job?</strong></p>
<p>If you left your job because it's a toxic environment, you want to be specific about what made it toxic. </p>
<p>We didn't tackle this question any further in the chat I had with Chris, so I don't have concrete answers for you if you got bored and simply wanted to switch. </p>
<h3 id="heading-standing-out">Standing out</h3>
<p>You need to sell yourself during an interview so you stand out. You can do this by answering questions the interviewer has not asked. </p>
<p>Tell them the things you listed on your CV. Tell them about contributing to open source, attending meetups, conferences, blogging, and anything you can think of that helps you stand out. </p>
<p>It is the nature of our industry to think creatively. If you managed to solve a problem in a useful way before, talk about it. It'll put you in a good light. The more you've done this, the more you're of a right employee. </p>
<h3 id="heading-questions-to-ask">Questions to ask</h3>
<p>As much as the interview is interviewing you, you're also interviewing the interviewer. Remember this. </p>
<p>Chris says he'd ask two questions: </p>
<ol>
<li>What will I be doing if you sit me down at my desk and put a computer in front of me? </li>
<li>What are the skeletons in your closest?</li>
</ol>
<p><strong>What will I be doing if you sit me down at my desk and put a computer in front of me?</strong></p>
<p>This question tells about the work you'll do day-to-day with the company. If they say something concrete about the work that you align with, good! </p>
<p>But be aware that expectations don't always line up to reality. If this happens, Start applying for another job.</p>
<p><strong>What are the skeletons in your closest?</strong> </p>
<p>This question means: What are the dirty things I should know about your company? To me, this question flips the "What's your weakness" question back to the company. </p>
<p>You'd want to hear what they want to hide. You want to test their honesty as well. If they say everything is perfect, they're lying. </p>
<p>Everyone will try to sell you the job if they're interested in you. They'll tell you about shiny frameworks and greenfield projects. But when you show up, they might ask you to work on legacy systems. </p>
<h3 id="heading-be-honest">Be honest</h3>
<p>Always be honest. It's not going to work if you bluff. </p>
<p>The worst part about lying is you might get the job. And then you're screwed because you're expected to perform. </p>
<h2 id="heading-final-words-from-chris">Final words from Chris</h2>
<p>So much about finding a job is not cutting yourself out of the process. </p>
<p>They're only looking for one person for the job. The odds are, you're not going to get the job. So how do you NOT get eliminated? How do you move on to the next stage and meet the next boss? </p>
<p>You'll feel awful if you get rejected, and you're going to get rejected a lot. You'll also get interviewers who are awful and you come out of it feeling awful. But if you don't apply, you'll never get anywhere.</p>
<p>You nothing much to distinguish yourself from other candidates at the start. It boils down to your luck. You have to play your odds. If possible, get someone in the industry to check your CV for you. It helps. </p>
<p>Good luck. </p>
<p>Please thank Chris Lienert for spending his time with us if this helped you. <a target="_blank" href="https://twitter.com/cliener">You can reach him through Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to deal with nested callbacks and avoid “callback hell” ]]>
                </title>
                <description>
                    <![CDATA[ JavaScript is a strange language. Once in a while, you have to deal with a callback that’s in another callback that’s in yet another callback. People affectionately call this pattern the callback hell. It kinda looks like this: firstFunction(args, fu... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-deal-with-nested-callbacks-and-avoid-callback-hell-1bc8dc4a2012/</link>
                <guid isPermaLink="false">66c4c74c99f22436b71945f0</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ technology ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Thu, 23 May 2019 15:22:38 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*csqpgoE3UUyh-aUsqycOfw.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>JavaScript is a strange language. Once in a while, you have to deal with a callback that’s in another callback that’s in yet another callback.</p>
<p>People affectionately call this pattern the <em>callback hell</em>.</p>
<p>It kinda looks like this:</p>
<pre><code class="lang-javascript">firstFunction(args, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
  secondFunction(args, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    thirdFunction(args, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
      <span class="hljs-comment">// And so on…</span>
    });
  });
});
</code></pre>
<p>This is JavaScript for you. It’s mind-boggling to see nested callbacks, but I don’t think it’s a “hell”. The “hell” can be manageable if you know what to do with it.</p>
<h3 id="heading-on-callbacks">On callbacks</h3>
<p>I assume you know what callbacks are if you’re reading this article. If you don’t, please read <a target="_blank" href="https://zellwk.com/blog/callbacks/">this article</a> for an introduction to callbacks before continuing. There, we talk about what callbacks are and why you use them in JavaScript.</p>
<h3 id="heading-solutions-to-callback-hell">Solutions to callback hell</h3>
<p>There are four solutions to callback hell:</p>
<ol>
<li>Write comments</li>
<li>Split functions into smaller functions</li>
<li>Using Promises</li>
<li>Using Async/await</li>
</ol>
<p>Before we dive into the solutions, let’s construct a callback hell together. Why? Because it’s too abstract to see <code>firstFunction</code>, <code>secondFunction</code>, and <code>thirdFunction</code>. We want to make it concrete.</p>
<h3 id="heading-constructing-a-callback-hell">Constructing a callback hell</h3>
<p>Let’s imagine we’re trying to make a burger. To make a burger, we need to go through the following steps:</p>
<ol>
<li>Get ingredients (we’re gonna assume it’s a beef burger)</li>
<li>Cook the beef</li>
<li>Get burger buns</li>
<li>Put the cooked beef between the buns</li>
<li>Serve the burger</li>
</ol>
<p>If these steps are synchronous, you’ll be looking at a function that resembles this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> makeBurger = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> beef = getBeef();
  <span class="hljs-keyword">const</span> patty = cookBeef(beef);
  <span class="hljs-keyword">const</span> buns = getBuns();
  <span class="hljs-keyword">const</span> burger = putBeefBetweenBuns(buns, beef);
  <span class="hljs-keyword">return</span> burger;
};

<span class="hljs-keyword">const</span> burger = makeBurger();
serve(burger);
</code></pre>
<p>However, in our scenario, let’s say we can’t make the burger ourselves. We have to instruct a helper on the steps to make the burger. After we instruct the helper, we have to <em>WAIT</em> for the helper to finish before we begin the next step.</p>
<p>If we want to wait for something in JavaScript, we need to use a callback. To make the burger, we have to get the beef first. We can only cook the beef after we get the beef.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> makeBurger = <span class="hljs-function">() =&gt;</span> {
  getBeef(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">beef</span>) </span>{
    <span class="hljs-comment">// We can only cook beef after we get it.</span>
  });
};
</code></pre>
<p>To cook the beef, we need to pass <code>beef</code> into the <code>cookBeef</code> function. Otherwise, there’s nothing to cook! Then, we have to wait for the beef to get cooked.</p>
<p>Once the beef gets cooked, we get buns.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> makeBurger = <span class="hljs-function">() =&gt;</span> {
  getBeef(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">beef</span>) </span>{
    cookBeef(beef, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">cookedBeef</span>) </span>{
      getBuns(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">buns</span>) </span>{
        <span class="hljs-comment">// Put patty in bun</span>
      });
    });
  });
};
</code></pre>
<p>After we get the buns, we need to put the patty between the buns. This is where a burger gets formed.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> makeBurger = <span class="hljs-function">() =&gt;</span> {
  getBeef(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">beef</span>) </span>{
    cookBeef(beef, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">cookedBeef</span>) </span>{
      getBuns(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">buns</span>) </span>{
        putBeefBetweenBuns(buns, beef, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">burger</span>) </span>{
            <span class="hljs-comment">// Serve the burger</span>
        });
      });
    });
  });
};
</code></pre>
<p>Finally, we can serve the burger! But we can’t return <code>burger</code> from <code>makeBurger</code> because it’s asynchronous. We need to accept a callback to serve the burger.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> makeBurger = <span class="hljs-function"><span class="hljs-params">nextStep</span> =&gt;</span> {
  getBeef(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">beef</span>) </span>{
    cookBeef(beef, <span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">cookedBeef</span>) </span>{
      getBuns(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">buns</span>) </span>{
        putBeefBetweenBuns(buns, beef, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">burger</span>) </span>{
          nextStep(burger)
        })
      })
    })
  })
}

<span class="hljs-comment">// Make and serve the burger</span>
makeBurger(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params">burger</span>) =&gt; </span>{
  serve(burger)
})
</code></pre>
<p>(I had fun making this callback hell example ?).</p>
<h3 id="heading-first-solution-to-callback-hell-write-comments">First solution to callback hell: Write comments</h3>
<p>The <code>makeBurger</code> callback hell is simple to understand. We can read it. It just… doesn’t look nice.</p>
<p>If you’re reading <code>makeBurger</code> for the first time, you may think “Why the hell do we need so many callbacks to make a burger? It doesn’t make sense!”.</p>
<p>In such a case, you’d want to leave comments to explain your code.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Makes a burger</span>
<span class="hljs-comment">// makeBurger contains four steps:</span>
<span class="hljs-comment">//   1. Get beef</span>
<span class="hljs-comment">//   2. Cook the beef</span>
<span class="hljs-comment">//   3. Get buns for the burger</span>
<span class="hljs-comment">//   4. Put the cooked beef between the buns</span>
<span class="hljs-comment">//   5. Serve the burger (from the callback)</span>
<span class="hljs-comment">// We use callbacks here because each step is asynchronous.</span>
<span class="hljs-comment">//   We have to wait for the helper to complete the one step</span>
<span class="hljs-comment">//   before we can start the next step</span>

<span class="hljs-keyword">const</span> makeBurger = <span class="hljs-function"><span class="hljs-params">nextStep</span> =&gt;</span> {
  getBeef(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">beef</span>) </span>{
    cookBeef(beef, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">cookedBeef</span>) </span>{
      getBuns(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">buns</span>) </span>{
        putBeefBetweenBuns(buns, beef, <span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params">burger</span>) </span>{
          nextStep(burger);
        });
      });
    });
  });
};
</code></pre>
<p>Now, instead of thinking “wtf?!” when you see the callback hell, you get an understanding of why it has to be written this way.</p>
<h3 id="heading-second-solution-to-callback-hell-split-the-callbacks-into-different-functions">Second solution to callback hell: Split the callbacks into different functions</h3>
<p>Our callback hell example is already an example of this. Let me show you the step-by-step imperative code and you’ll see why.</p>
<p>For <code>getBeef</code>, our first callback, we have to go to the fridge to get the beef. There are two fridges in the kitchen. We need to go to the right fridge.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> getBeef = <span class="hljs-function"><span class="hljs-params">nextStep</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> fridge = leftFright;
  <span class="hljs-keyword">const</span> beef = getBeefFromFridge(fridge);
  nextStep(beef);
};
</code></pre>
<p>To cook beef, we need to put the beef into an oven; turn the oven to 200 degrees, and wait for twenty minutes.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> cookBeef = <span class="hljs-function">(<span class="hljs-params">beef, nextStep</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> workInProgress = putBeefinOven(beef);
  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
    nextStep(workInProgress);
  }, <span class="hljs-number">1000</span> * <span class="hljs-number">60</span> * <span class="hljs-number">20</span>);
};
</code></pre>
<p>Now imagine if you have to write each of these steps in <code>makeBurger</code>… you’ll probably faint from the sheer amount of code!</p>
<p>For a concrete example on splitting callbacks into smaller functions, you can read <a target="_blank" href="https://zellwk.com/blog/callbacks#callback-hell">this small section</a> in my callback article.</p>
<h3 id="heading-third-solution-to-callback-hell-use-promises">Third solution to callback hell: Use promises</h3>
<p>I’m going to assume you know what promises are. If you don’t, please <a target="_blank" href="https://zellwk.com/blog/js-promises/">read this article</a>.</p>
<p>Promises can make callback hell much easier to manage. Instead of the nested code you see above, you’ll have this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> makeBurger = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> getBeef()
    .then(<span class="hljs-function"><span class="hljs-params">beef</span> =&gt;</span> cookBeef(beef))
    .then(<span class="hljs-function"><span class="hljs-params">cookedBeef</span> =&gt;</span> getBuns(beef))
    .then(<span class="hljs-function"><span class="hljs-params">bunsAndBeef</span> =&gt;</span> putBeefBetweenBuns(bunsAndBeef));
};

<span class="hljs-comment">// Make and serve burger</span>
makeBurger().then(<span class="hljs-function"><span class="hljs-params">burger</span> =&gt;</span> serve(burger));
</code></pre>
<p>If you take advantage of the single-argument style with promises, you can tweak the above to this:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> makeBurger = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> getBeef()
    .then(cookBeef)
    .then(getBuns)
    .then(putBeefBetweenBuns);
};

<span class="hljs-comment">// Make and serve burger</span>
makeBurger().then(serve);
</code></pre>
<p>Much easier to read and manage.</p>
<p>But the question is how do you convert callback-based code into promise-based code.</p>
<h4 id="heading-converting-callbacks-to-promises">Converting callbacks to promises</h4>
<p>To convert callbacks into promises, we need to create a new promise for each callback. We can <code>resolve</code> the promise when the callback is successful. Or we can <code>reject</code> the promise if the callback fails.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> getBeefPromise = <span class="hljs-function"><span class="hljs-params">_</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> fridge = leftFright;
  <span class="hljs-keyword">const</span> beef = getBeefFromFridge(fridge);

  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (beef) {
      resolve(beef);
    } <span class="hljs-keyword">else</span> {
      reject(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(“No more beef!”));
    }
  });
};

<span class="hljs-keyword">const</span> cookBeefPromise = <span class="hljs-function"><span class="hljs-params">beef</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> workInProgress = putBeefinOven(beef);

  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve, reject</span>) =&gt;</span> {
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function"><span class="hljs-keyword">function</span>(<span class="hljs-params"></span>) </span>{
      resolve(workInProgress);
    }, <span class="hljs-number">1000</span> * <span class="hljs-number">60</span> * <span class="hljs-number">20</span>);
  });
};
</code></pre>
<p>In practice, callbacks would probably be written for you already. If you use Node, each function that contains a callback will have the same syntax:</p>
<ol>
<li>The callback would be the last argument</li>
<li>The callback will always have two arguments. And these arguments are in the same order. (Error first, followed by whatever you’re interested in).</li>
</ol>
<pre><code class="lang-javascript"><span class="hljs-comment">// The function that’s defined for you</span>
<span class="hljs-keyword">const</span> functionName = <span class="hljs-function">(<span class="hljs-params">arg1, arg2, callback</span>) =&gt;</span> {
  <span class="hljs-comment">// Do stuff here</span>
  callback(err, stuff);
};

<span class="hljs-comment">// How you use the function</span>
functionName(arg1, arg2, <span class="hljs-function">(<span class="hljs-params">err, stuff</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (err) {
  <span class="hljs-built_in">console</span>.error(err);
  }
  <span class="hljs-comment">// Do stuff</span>
});
</code></pre>
<p>If your callback has the same syntax, you can use libraries like <a target="_blank" href="https://www.npmjs.com/package/es6-promisify">ES6 Promisify</a> or <a target="_blank" href="https://www.npmjs.com/package/denodeify">Denodeify</a> (de-node-ify) that callback into a promise. If you use Node v8.0 and above, you can use <a target="_blank" href="https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original">util.promisify</a>.</p>
<p>All three of them work. You can choose any library to work with. There are slight nuances between each method, though. I’ll leave you to check their documentation for how-tos.</p>
<h3 id="heading-fourth-solution-to-callback-hell-use-asynchronous-functions">Fourth solution to callback hell: Use asynchronous functions</h3>
<p>To use asynchronous functions, you need to know two things first:</p>
<ol>
<li>How to convert callbacks into promises (read above)</li>
<li>How to use asynchronous functions (<a target="_blank" href="https://zellwk.com/blog/async-await">read this</a> if you need help).</li>
</ol>
<p>With asynchronous functions, you can write <code>makeBurger</code> as if it’s synchronous again!</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> makeBurger = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> beef = <span class="hljs-keyword">await</span> getBeef();
  <span class="hljs-keyword">const</span> cookedBeef = <span class="hljs-keyword">await</span> cookBeef(beef);
  <span class="hljs-keyword">const</span> buns = <span class="hljs-keyword">await</span> getBuns();
  <span class="hljs-keyword">const</span> burger = <span class="hljs-keyword">await</span> putBeefBetweenBuns(cookedBeef, buns);
  <span class="hljs-keyword">return</span> burger;
};

<span class="hljs-comment">// Make and serve burger</span>
makeBurger().then(serve);
</code></pre>
<p>There’s one improvement we can make to the <code>makeBurger</code> here. You can probably get two helpers to <code>getBuns</code> and <code>getBeef</code> at the same time. This means you can <code>await</code> them both with <code>Promise.all</code>.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> makeBurger = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">const</span> [beef, buns] = <span class="hljs-keyword">await</span> <span class="hljs-built_in">Promise</span>.all(getBeef, getBuns);
  <span class="hljs-keyword">const</span> cookedBeef = <span class="hljs-keyword">await</span> cookBeef(beef);
  <span class="hljs-keyword">const</span> burger = <span class="hljs-keyword">await</span> putBeefBetweenBuns(cookedBeef, buns);
  <span class="hljs-keyword">return</span> burger;
};

<span class="hljs-comment">// Make and serve burger</span>
makeBurger().then(serve);
</code></pre>
<p>(Note: You can do the same with Promises… but the syntax isn’t as nice and as clear as async/await functions).</p>
<h3 id="heading-wrapping-up">Wrapping up</h3>
<p>Callback hell isn’t as hellish as you think. There are four easy ways to manage callback hell:</p>
<ol>
<li>Write comments</li>
<li>Split functions into smaller functions</li>
<li>Using Promises</li>
<li>Using Async/await</li>
</ol>
<p>This article was originally posted on <a target="_blank" href="https://zellwk.com/blog/nested-callbacks">my blog</a>.<br>Sign up for my <a target="_blank" href="https://zellwk.com/">newsletter</a> if you want more articles to help you become a better frontend developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ JavaScript async and await in loops ]]>
                </title>
                <description>
                    <![CDATA[ Basic async and await is simple. Things get a bit more complicated when you try to use await in loops. In this article, I want to share some gotchas to watch out for if you intend to use await in loops. Before you begin I'm going to assume you know ]]>
                </description>
                <link>https://www.freecodecamp.org/news/javascript-async-and-await-in-loops-30ecc5fb3939/</link>
                <guid isPermaLink="false">66c4c786d788a9c53d88d2eb</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Tue, 21 May 2019 23:04:26 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*p2upvpYKRT0-qtTP61LOYg.gif" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Basic <code>async</code> and <code>await</code> is simple. Things get a bit more complicated when you try to use <code>await</code> in loops.</p>
<p>In this article, I want to share some gotchas to watch out for if you intend to use <code>await</code> in loops.</p>
<h3 id="heading-before-you-begin"><strong>Before you begin</strong></h3>
<p>I'm going to assume you know how to use <code>async</code> and <code>await</code>. If you don't, read the <a target="_blank" href="https://zellwk.com/blog/async-await">previous article</a> to familiarize yourself before continuing.</p>
<h3 id="heading-preparing-an-example"><strong>Preparing an example</strong></h3>
<p>For this article, let's say you want to get the number of fruits from a fruit basket.</p>
<pre><code><span class="hljs-keyword">const</span> fruitBasket = {
 <span class="hljs-attr">apple</span>: <span class="hljs-number">27</span>,
 <span class="hljs-attr">grape</span>: <span class="hljs-number">0</span>,
 <span class="hljs-attr">pear</span>: <span class="hljs-number">14</span>
};
</code></pre><p>You want to get the number of each fruit from the fruitBasket. To get the number of a fruit, you can use a <code>getNumFruit</code> function.</p>
<pre><code><span class="hljs-keyword">const</span> getNumFruit = <span class="hljs-function"><span class="hljs-params">fruit</span> =&gt;</span> {
 <span class="hljs-keyword">return</span> fruitBasket[fruit];
};

<span class="hljs-keyword">const</span> numApples = getNumFruit(“apple”);
<span class="hljs-built_in">console</span>.log(numApples); <span class="hljs-comment">// 27</span>
</code></pre><p>Now, let's say <code>fruitBasket</code> lives on a remote server. Accessing it takes one second. We can mock this one-second delay with a timeout. (Please refer to the <a target="_blank" href="https://zellwk.com/blog/async-await">previous article</a> if you have problems understanding the timeout code).</p>
<pre><code><span class="hljs-keyword">const</span> sleep = <span class="hljs-function"><span class="hljs-params">ms</span> =&gt;</span> {
 <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function"><span class="hljs-params">resolve</span> =&gt;</span> <span class="hljs-built_in">setTimeout</span>(resolve, ms));
};

<span class="hljs-keyword">const</span> getNumFruit = <span class="hljs-function"><span class="hljs-params">fruit</span> =&gt;</span> {
 <span class="hljs-keyword">return</span> sleep(<span class="hljs-number">1000</span>).then(<span class="hljs-function"><span class="hljs-params">v</span> =&gt;</span> fruitBasket[fruit]);
};

getNumFruit(“apple”).then(<span class="hljs-function"><span class="hljs-params">num</span> =&gt;</span> <span class="hljs-built_in">console</span>.log(num)); <span class="hljs-comment">// 27</span>
</code></pre><p>Finally, let's say you want to use <code>await</code> and <code>getNumFruit</code> to get the number of each fruit in asynchronous function.</p>
<pre><code><span class="hljs-keyword">const</span> control = <span class="hljs-keyword">async</span> _ =&gt; {
 <span class="hljs-built_in">console</span>.log(“Start”);

<span class="hljs-keyword">const</span> numApples = <span class="hljs-keyword">await</span> getNumFruit(“apple”);
 <span class="hljs-built_in">console</span>.log(numApples);

<span class="hljs-keyword">const</span> numGrapes = <span class="hljs-keyword">await</span> getNumFruit(“grape”);
 <span class="hljs-built_in">console</span>.log(numGrapes);

<span class="hljs-keyword">const</span> numPears = <span class="hljs-keyword">await</span> getNumFruit(“pear”);
 <span class="hljs-built_in">console</span>.log(numPears);

<span class="hljs-built_in">console</span>.log(“End”);
};
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/n5Qv0F00AiCZqsRsu7NPh3S3HFp-ZWXYTwuH" alt="Image" width="980" height="284" loading="lazy">
<em>Console shows ‘Start’. One second later, it logs 27. Another second later, it logs 0. One more second later, it logs 14, and ‘End’</em></p>
<p>With this, we can begin looking at <code>await</code> in loops.</p>
<h3 id="heading-await-in-a-for-loop"><strong>Await in a for loop</strong></h3>
<p>Let's say we have an array of fruits we want to get from the fruit basket.</p>
<pre><code><span class="hljs-keyword">const</span> fruitsToGet = [“apple”, “grape”, “pear”];
</code></pre><p>We are going to loop through this array.</p>
<pre><code><span class="hljs-keyword">const</span> forLoop = <span class="hljs-keyword">async</span> _ =&gt; {
 <span class="hljs-built_in">console</span>.log(“Start”);

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> index = <span class="hljs-number">0</span>; index &lt; fruitsToGet.length; index++) {
 <span class="hljs-comment">// Get num of each fruit</span>
 }

<span class="hljs-built_in">console</span>.log(“End”);
};
</code></pre><p>In the for-loop, we will use <code>getNumFruit</code> to get the number of each fruit. We'll also log the number into the console.</p>
<p>Since <code>getNumFruit</code> returns a promise, we can <code>await</code> the resolved value before logging it.</p>
<pre><code><span class="hljs-keyword">const</span> forLoop = <span class="hljs-keyword">async</span> _ =&gt; {
 <span class="hljs-built_in">console</span>.log(“Start”);

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> index = <span class="hljs-number">0</span>; index &lt; fruitsToGet.length; index++) {
 <span class="hljs-keyword">const</span> fruit = fruitsToGet[index];
 <span class="hljs-keyword">const</span> numFruit = <span class="hljs-keyword">await</span> getNumFruit(fruit);
 <span class="hljs-built_in">console</span>.log(numFruit);
 }

<span class="hljs-built_in">console</span>.log(“End”);
};
</code></pre><p>When you use <code>await</code>, you expect JavaScript to pause execution until the awaited promise gets resolved. This means <code>await</code>s in a for-loop should get executed in series.</p>
<p>The result is what you'd expect.</p>
<pre><code>“Start”;
“Apple: <span class="hljs-number">27</span>”;
“Grape: <span class="hljs-number">0</span>”;
“Pear: <span class="hljs-number">14</span>”;
“End”;
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/sU0OzGuNuH5BwMoYmNcmNLfQzcexW0m7e08K" alt="Image" width="980" height="284" loading="lazy">
<em>Console shows ‘Start’. One second later, it logs 27. Another second later, it logs 0. One more second later, it logs 14, and ‘End’</em></p>
<p>This behavior works with most loops (like <code>while</code> and <code>for-of</code> loops)...</p>
<p>But it won't work with loops that require a callback. Examples of such loops that require a fallback include <code>forEach</code>, <code>map</code>, <code>filter</code>, and <code>reduce</code>. We'll look at how <code>await</code> affects <code>forEach</code>, <code>map</code>, and <code>filter</code> in the next few sections.</p>
<h3 id="heading-await-in-a-foreach-loop"><strong>Await in a forEach loop</strong></h3>
<p>We'll do the same thing as we did in the for-loop example. First, let's loop through the array of fruits.</p>
<pre><code><span class="hljs-keyword">const</span> forEachLoop = <span class="hljs-function"><span class="hljs-params">_</span> =&gt;</span> {
 <span class="hljs-built_in">console</span>.log(“Start”);

fruitsToGet.forEach(<span class="hljs-function"><span class="hljs-params">fruit</span> =&gt;</span> {
 <span class="hljs-comment">// Send a promise for each fruit</span>
 });

<span class="hljs-built_in">console</span>.log(“End”);
};
</code></pre><p>Next, we'll try to get the number of fruits with <code>getNumFruit</code>. (Notice the <code>async</code> keyword in the callback function. We need this <code>async</code> keyword because <code>await</code> is in the callback function).</p>
<pre><code><span class="hljs-keyword">const</span> forEachLoop = <span class="hljs-function"><span class="hljs-params">_</span> =&gt;</span> {
 <span class="hljs-built_in">console</span>.log(“Start”);

fruitsToGet.forEach(<span class="hljs-keyword">async</span> fruit =&gt; {
 <span class="hljs-keyword">const</span> numFruit = <span class="hljs-keyword">await</span> getNumFruit(fruit);
 <span class="hljs-built_in">console</span>.log(numFruit);
 });

<span class="hljs-built_in">console</span>.log(“End”);
};
</code></pre><p>You might expect the console to look like this:</p>
<pre><code>“Start”;
“<span class="hljs-number">27</span>”;
“<span class="hljs-number">0</span>”;
“<span class="hljs-number">14</span>”;
“End”;
</code></pre><p>But the actual result is different. JavaScript proceeds to call <code>console.log('End')</code> before the promises in the forEach loop gets resolved.</p>
<p>The console logs in this order:</p>
<pre><code>‘Start’
‘End’
‘<span class="hljs-number">27</span>’
‘<span class="hljs-number">0</span>’
‘<span class="hljs-number">14</span>’
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/DwUgo9TAK8PXNLIAv3-27UZMSrEkfNx778hS" alt="Image" width="800" height="231" loading="lazy">
<em>Console logs ‘Start’ and ‘End’ immediately. One second later, it logs 27, 0, and 14.</em></p>
<p>JavaScript does this because <code>forEach</code> is not promise-aware. It cannot support <code>async</code> and <code>await</code>. You <strong>cannot</strong> use <code>await</code> in <code>forEach</code>.</p>
<h3 id="heading-await-with-map"><strong>Await with map</strong></h3>
<p>If you use <code>await</code> in a <code>map</code>, <code>map</code> will always return an array of promise. This is because asynchronous functions always return promises.</p>
<pre><code><span class="hljs-keyword">const</span> mapLoop = <span class="hljs-keyword">async</span> _ =&gt; {
 <span class="hljs-built_in">console</span>.log(“Start”);

<span class="hljs-keyword">const</span> numFruits = <span class="hljs-keyword">await</span> fruitsToGet.map(<span class="hljs-keyword">async</span> fruit =&gt; {
 <span class="hljs-keyword">const</span> numFruit = <span class="hljs-keyword">await</span> getNumFruit(fruit);
 <span class="hljs-keyword">return</span> numFruit;
 });

<span class="hljs-built_in">console</span>.log(numFruits);

<span class="hljs-built_in">console</span>.log(“End”);
};

“Start”;
“[<span class="hljs-built_in">Promise</span>, <span class="hljs-built_in">Promise</span>, <span class="hljs-built_in">Promise</span>]”;
“End”;
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/JD3o7BUxILoFP-hVwv5920JtHJPB8l6IrMNs" alt="Image" width="800" height="163" loading="lazy">
<em>Console logs ‘<code>Start</code>’, ‘[Promise, Promise, Promise]’, and ‘End’ immediately</em></p>
<p>Since <code>map</code> always return promises (if you use <code>await</code>), you have to wait for the array of promises to get resolved. You can do this with <code>await Promise.all(arrayOfPromises)</code>.</p>
<pre><code><span class="hljs-keyword">const</span> mapLoop = <span class="hljs-keyword">async</span> _ =&gt; {
 <span class="hljs-built_in">console</span>.log(“Start”);

<span class="hljs-keyword">const</span> promises = fruitsToGet.map(<span class="hljs-keyword">async</span> fruit =&gt; {
 <span class="hljs-keyword">const</span> numFruit = <span class="hljs-keyword">await</span> getNumFruit(fruit);
 <span class="hljs-keyword">return</span> numFruit;
 });

<span class="hljs-keyword">const</span> numFruits = <span class="hljs-keyword">await</span> <span class="hljs-built_in">Promise</span>.all(promises);
 <span class="hljs-built_in">console</span>.log(numFruits);

<span class="hljs-built_in">console</span>.log(“End”);
};
</code></pre><p>Here's what you get:</p>
<pre><code>“Start”;
“[<span class="hljs-number">27</span>, <span class="hljs-number">0</span>, <span class="hljs-number">14</span>]”;
“End”;
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/Clz579WsPZ0Tv4iiA5rN1960VP0xx4x66dAz" alt="Image" width="800" height="163" loading="lazy">
<em>Console logs ‘Start’. One second later, it logs ‘[27, 0, 14] and ‘End’</em></p>
<p>You can manipulate the value you return in your promises if you wish to. The resolved values will be the values you return.</p>
<pre><code><span class="hljs-keyword">const</span> mapLoop = <span class="hljs-keyword">async</span> _ =&gt; {
 <span class="hljs-comment">// …</span>
 <span class="hljs-keyword">const</span> promises = fruitsToGet.map(<span class="hljs-keyword">async</span> fruit =&gt; {
 <span class="hljs-keyword">const</span> numFruit = <span class="hljs-keyword">await</span> getNumFruit(fruit);
 <span class="hljs-comment">// Adds onn fruits before returning</span>
 <span class="hljs-keyword">return</span> numFruit + <span class="hljs-number">100</span>;
 });
 <span class="hljs-comment">// …</span>
};

“Start”;
“[<span class="hljs-number">127</span>, <span class="hljs-number">100</span>, <span class="hljs-number">114</span>]”;
“End”;
</code></pre><h3 id="heading-await-with-filter"><strong>Await with filter</strong></h3>
<p>When you use <code>filter</code>, you want to filter an array with a specific result. Let's say you want to create an array with more than 20 fruits.</p>
<p>If you use <code>filter</code> normally (without await), you'll use it like this:</p>
<pre><code><span class="hljs-comment">// Filter if there’s no await</span>
<span class="hljs-keyword">const</span> filterLoop = <span class="hljs-function"><span class="hljs-params">_</span> =&gt;</span> {
 <span class="hljs-built_in">console</span>.log(‘Start’)

<span class="hljs-keyword">const</span> moreThan20 = <span class="hljs-keyword">await</span> fruitsToGet.filter(<span class="hljs-function"><span class="hljs-params">fruit</span> =&gt;</span> {
 <span class="hljs-keyword">const</span> numFruit = fruitBasket[fruit]
 <span class="hljs-keyword">return</span> numFruit &gt; <span class="hljs-number">20</span>
 })

<span class="hljs-built_in">console</span>.log(moreThan20)
 <span class="hljs-built_in">console</span>.log(‘End’)
}
</code></pre><p>You would expect <code>moreThan20</code> to contain only apples because there are 27 apples, but there are 0 grapes and 14 pears.</p>
<pre><code>“Start”[“apple”];
(“End”);
</code></pre><p><code>await</code> in <code>filter</code> doesn't work the same way. In fact, it doesn't work at all. You get the unfiltered array back...</p>
<pre><code><span class="hljs-keyword">const</span> filterLoop = <span class="hljs-function"><span class="hljs-params">_</span> =&gt;</span> {
 <span class="hljs-built_in">console</span>.log(‘Start’)

<span class="hljs-keyword">const</span> moreThan20 = <span class="hljs-keyword">await</span> fruitsToGet.filter(<span class="hljs-keyword">async</span> fruit =&gt; {
 <span class="hljs-keyword">const</span> numFruit = getNumFruit(fruit)
 <span class="hljs-keyword">return</span> numFruit &gt; <span class="hljs-number">20</span>
 })

<span class="hljs-built_in">console</span>.log(moreThan20)
 <span class="hljs-built_in">console</span>.log(‘End’)
}

“Start”[(“apple”, “grape”, “pear”)];
(“End”);
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/xI8y6n2kvda8pz9i7f5ffVu92gs7ISj7My9M" alt="Image" width="800" height="129" loading="lazy">
<em>Console loggs ‘Start’, ‘[‘apple’, ‘grape’, ‘pear’]’, and ‘End’ immediately</em></p>
<p>Here's why it happens.</p>
<p>When you use <code>await</code> in a <code>filter</code> callback, the callback always a promise. Since promises are always truthy, everything item in the array passes the filter. Writing <code>await</code> in a <code>filter</code> is like writing this code:</p>
<pre><code><span class="hljs-comment">// Everything passes the filter…</span>
<span class="hljs-keyword">const</span> filtered = array.filter(<span class="hljs-literal">true</span>);
</code></pre><p>There are three steps to use <code>await</code> and <code>filter</code> properly:</p>
<ol>
<li><p>Use <code>map</code> to return an array promises</p>
</li>
<li><p><code>await</code> the array of promises</p>
</li>
<li><p><code>filter</code> the resolved values</p>
</li>
</ol>
<pre><code><span class="hljs-keyword">const</span> filterLoop = <span class="hljs-keyword">async</span> _ =&gt; {
 <span class="hljs-built_in">console</span>.log(“Start”);

<span class="hljs-keyword">const</span> promises = <span class="hljs-keyword">await</span> fruitsToGet.map(<span class="hljs-function"><span class="hljs-params">fruit</span> =&gt;</span> getNumFruit(fruit));
 <span class="hljs-keyword">const</span> numFruits = <span class="hljs-keyword">await</span> <span class="hljs-built_in">Promise</span>.all(promises);

<span class="hljs-keyword">const</span> moreThan20 = fruitsToGet.filter(<span class="hljs-function">(<span class="hljs-params">fruit, index</span>) =&gt;</span> {
 <span class="hljs-keyword">const</span> numFruit = numFruits[index];
 <span class="hljs-keyword">return</span> numFruit &gt; <span class="hljs-number">20</span>;
 });

<span class="hljs-built_in">console</span>.log(moreThan20);
 <span class="hljs-built_in">console</span>.log(“End”);
};

Start[“apple”];
End;
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/KbvkmmX4K77pSq29OVj8jhK0KNdyCYQsH1Sn" alt="Image" width="800" height="163" loading="lazy">
<em>Console shows ‘Start’. One second later, console logs ‘[‘apple’]’ and ‘End’</em></p>
<h3 id="heading-await-with-reduce"><strong>Await with reduce</strong></h3>
<p>For this case, let's say you want to find out the total number of fruits in the fruitBastet. Normally, you can use <code>reduce</code> to loop through an array and sum the number up.</p>
<pre><code><span class="hljs-comment">// Reduce if there’s no await</span>
<span class="hljs-keyword">const</span> reduceLoop = <span class="hljs-function"><span class="hljs-params">_</span> =&gt;</span> {
 <span class="hljs-built_in">console</span>.log(“Start”);

<span class="hljs-keyword">const</span> sum = fruitsToGet.reduce(<span class="hljs-function">(<span class="hljs-params">sum, fruit</span>) =&gt;</span> {
 <span class="hljs-keyword">const</span> numFruit = fruitBasket[fruit];
 <span class="hljs-keyword">return</span> sum + numFruit;
 }, <span class="hljs-number">0</span>);

<span class="hljs-built_in">console</span>.log(sum);
 <span class="hljs-built_in">console</span>.log(“End”);
};
</code></pre><p>You'll get a total of 41 fruits. (27 + 0 + 14 = 41).</p>
<pre><code>“Start”;
“<span class="hljs-number">41</span>”;
“End”;
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/1cHrIKZU2x4bt0Cl6NmnrNA9eYed0-3n4SIq" alt="Image" width="800" height="154" loading="lazy">
<em>Console logs ‘Start’, ‘41’, and ‘End’ immediately</em></p>
<p>When you use <code>await</code> with reduce, the results get extremely messy.</p>
<pre><code><span class="hljs-comment">// Reduce if we await getNumFruit</span>
<span class="hljs-keyword">const</span> reduceLoop = <span class="hljs-keyword">async</span> _ =&gt; {
 <span class="hljs-built_in">console</span>.log(“Start”);

<span class="hljs-keyword">const</span> sum = <span class="hljs-keyword">await</span> fruitsToGet.reduce(<span class="hljs-keyword">async</span> (sum, fruit) =&gt; {
 <span class="hljs-keyword">const</span> numFruit = <span class="hljs-keyword">await</span> getNumFruit(fruit);
 <span class="hljs-keyword">return</span> sum + numFruit;
 }, <span class="hljs-number">0</span>);

<span class="hljs-built_in">console</span>.log(sum);
 <span class="hljs-built_in">console</span>.log(“End”);
};

“Start”;
“[object <span class="hljs-built_in">Promise</span>]<span class="hljs-number">14</span>”;
“End”;
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/vziO1ieaUzFZNE1p3FlaOBJLEQtAL21CYDKw" alt="Image" width="800" height="163" loading="lazy">
<em>Console logs ‘Start’. One second later, it logs ‘[object Promise]14’ and ‘End’</em></p>
<p>What?! <code>[object Promise]14</code>?!</p>
<p>Dissecting this is interesting.</p>
<ul>
<li>In the first iteration, <code>sum</code> is <code>0</code>. <code>numFruit</code> is 27 (the resolved value from <code>getNumFruit(‘apple’)</code>). <code>0 + 27</code> is 27.</li>
<li>In the second iteration, <code>sum</code> is a promise. (Why? Because asynchronous functions always return promises!) <code>numFruit</code> is 0. A promise cannot be added to an object normally, so the JavaScript converts it to <code>[object Promise]</code> string. <code>[object Promise] + 0</code> is <code>[object Promise]0</code></li>
<li>In the third iteration, <code>sum</code> is also a promise. <code>numFruit</code> is <code>14</code>. <code>[object Promise] + 14</code> is <code>[object Promise]14</code>.</li>
</ul>
<p>Mystery solved!</p>
<p>This means, you can use <code>await</code> in a <code>reduce</code> callback, but you have to remember to <code>await</code> the accumulator first!</p>
<pre><code><span class="hljs-keyword">const</span> reduceLoop = <span class="hljs-keyword">async</span> _ =&gt; {
 <span class="hljs-built_in">console</span>.log(“Start”);

<span class="hljs-keyword">const</span> sum = <span class="hljs-keyword">await</span> fruitsToGet.reduce(<span class="hljs-keyword">async</span> (promisedSum, fruit) =&gt; {
 <span class="hljs-keyword">const</span> sum = <span class="hljs-keyword">await</span> promisedSum;
 <span class="hljs-keyword">const</span> numFruit = <span class="hljs-keyword">await</span> getNumFruit(fruit);
 <span class="hljs-keyword">return</span> sum + numFruit;
 }, <span class="hljs-number">0</span>);

<span class="hljs-built_in">console</span>.log(sum);
 <span class="hljs-built_in">console</span>.log(“End”);
};

“Start”;
“<span class="hljs-number">41</span>”;
“End”;
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/a3ZEbODMdVmob-31Qh0qfFugbLJoNZudoPwM" alt="Image" width="980" height="200" loading="lazy">
<em>Console logs ‘Start’. Three seconds later, it logs ‘41’ and ‘End’</em></p>
<p>But... as you can see from the gif, it takes pretty long to <code>await</code> everything. This happens because <code>reduceLoop</code> needs to wait for the <code>promisedSum</code> to be completed for each iteration.</p>
<p>There's a way to speed up the reduce loop. (I found out about this thanks to <a target="_blank" href="https://twitter.com/timkevinoxley">Tim Oxley</a>. If you <code>await getNumFruits(</code>) first before <code>await promisedSum</code>, the <code>reduceLoop</code> takes only one second to complete:</p>
<pre><code><span class="hljs-keyword">const</span> reduceLoop = <span class="hljs-keyword">async</span> _ =&gt; {
 <span class="hljs-built_in">console</span>.log(“Start”);

<span class="hljs-keyword">const</span> sum = <span class="hljs-keyword">await</span> fruitsToGet.reduce(<span class="hljs-keyword">async</span> (promisedSum, fruit) =&gt; {
 <span class="hljs-comment">// Heavy-lifting comes first.</span>
 <span class="hljs-comment">// This triggers all three getNumFruit promises before waiting for the next iteration of the loop.</span>
 <span class="hljs-keyword">const</span> numFruit = <span class="hljs-keyword">await</span> getNumFruit(fruit);
 <span class="hljs-keyword">const</span> sum = <span class="hljs-keyword">await</span> promisedSum;
 <span class="hljs-keyword">return</span> sum + numFruit;
 }, <span class="hljs-number">0</span>);

<span class="hljs-built_in">console</span>.log(sum);
 <span class="hljs-built_in">console</span>.log(“End”);
};
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/Vm9olChpCbbEgBmub6OuOS2r0QD5SwwW9y9i" alt="Image" width="800" height="163" loading="lazy">
<em>Console logs ‘Start’. One second later, it logs ‘41’ and ‘End’</em></p>
<p>This works because <code>reduce</code> can fire all three <code>getNumFruit</code> promises before waiting for the next iteration of the loop. However, this method is slightly confusing since you have to be careful of the order you <code>await</code> things.</p>
<p>The simplest (and most efficient way) to use <code>await</code> in reduce is to:</p>
<ol>
<li><p>Use <code>map</code> to return an array promises</p>
</li>
<li><p><code>await</code> the array of promises</p>
</li>
<li><p><code>reduce</code> the resolved values</p>
</li>
</ol>
<pre><code><span class="hljs-keyword">const</span> reduceLoop = <span class="hljs-keyword">async</span> _ =&gt; {
 <span class="hljs-built_in">console</span>.log(“Start”);

<span class="hljs-keyword">const</span> promises = fruitsToGet.map(getNumFruit);
 <span class="hljs-keyword">const</span> numFruits = <span class="hljs-keyword">await</span> <span class="hljs-built_in">Promise</span>.all(promises);
 <span class="hljs-keyword">const</span> sum = numFruits.reduce(<span class="hljs-function">(<span class="hljs-params">sum, fruit</span>) =&gt;</span> sum + fruit);

<span class="hljs-built_in">console</span>.log(sum);
 <span class="hljs-built_in">console</span>.log(“End”);
};
</code></pre><p>This version is simple to read and understand, and takes one second to calculate the total number of fruits.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/rAN2FodB3Ff8FmQvMLy4R3mii1Kt41jRszkE" alt="Image" width="800" height="163" loading="lazy">
<em>Console logs ‘Start’. One second later, it logs ‘41’ and ‘End’</em></p>
<h3 id="heading-key-takeaways"><strong>Key Takeaways</strong></h3>
<ol>
<li><p>If you want to execute <code>await</code> calls in series, use a <code>for-loop</code> (or any loop without a callback).</p>
</li>
<li><p>Don't ever use <code>await</code> with <code>forEach</code>. Use a <code>for-loop</code> (or any loop without a callback) instead.</p>
</li>
<li><p>Don't <code>await</code> inside <code>filter</code> and <code>reduce</code>. Always <code>await</code> an array of promises with <code>map</code>, then <code>filter</code> or <code>reduce</code> accordingly.</p>
</li>
</ol>
<p>This article was originally posted on <a target="_blank" href="https://zellwk.com/blog/async-await-in-loops/"><em>my blog</em></a><em>.</em><br>Sign up for my <a target="_blank" href="https://zellwk.com/">newsletter</a> if you want more articles to help you become a better frontend developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to publish packages that can be used in browsers and Node ]]>
                </title>
                <description>
                    <![CDATA[ When you create a package for others to use, you have to consider where your user will use your package. Will they use it in a browser-based environment (or frontend JavaScript)? Will they use it in Node (or backend JavaScript)? Or both? If you want ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-publish-packages-that-can-be-used-in-browsers-and-node-c51274dca77c/</link>
                <guid isPermaLink="false">66c4c762d788a9c53d88d2e7</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Node.js ]]>
                    </category>
                
                    <category>
                        <![CDATA[ npm ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Thu, 02 May 2019 15:49:27 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*bpaO04etYhqF8-OFxen63w.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>When you create a package for others to use, you have to consider where your user will use your package. Will they use it in a browser-based environment (or frontend JavaScript)? Will they use it in Node (or backend JavaScript)? Or both?</p>
<p>If you want to create a package that’s usable in both browsers and Node, this article is here to help.</p>
<p>You’ll learn:</p>
<ol>
<li><p>How to write packages for use in browsers</p>
</li>
<li><p>How to write packages for use in Node</p>
</li>
<li><p>How to publish your packages for use in both browsers and Node</p>
</li>
</ol>
<h3 id="heading-writing-a-package-for-use-in-browsers"><strong>Writing a package for use in browsers</strong></h3>
<p>If you want to include a library in frontend JavaScript, you have to link the library first with a <code>script</code> tag. You can use the library anytime after you link it.</p>
<pre><code>&lt;!-- This is html --&gt;
</code></pre><pre><code>&lt;script src=<span class="hljs-string">"link-to-jquery.js"</span>&gt;&lt;/script&gt;
</code></pre><pre><code>&lt;script&gt;  <span class="hljs-comment">// You can use jQuery anytime after you link to it  console.log(jQuery)&lt;/script&gt;</span>
</code></pre><p>This works because JavaScript in browsers shares one global scope. It doesn’t matter how many JavaScript files you link to. They behave as if they’re one big JavaScript file.</p>
<p>With this information, we can begin writing a library for use in the frontend world.</p>
<p>Let’s say you want to create a library called <code>peachBlossom</code>. <code>peachBlossom</code> has a <code>bloom</code> function. You write this <code>bloom</code> function in a separate JavaScript file, <code>peach-blossom.js</code>.</p>
<pre><code><span class="hljs-comment">// This is js</span>
</code></pre><pre><code><span class="hljs-comment">// peach-blossom.jsfunction bloom () {  console.log('Bloom!')}</span>
</code></pre><p>You can include <code>peachBlossom</code> in your frontend JavaScript by linking to the <code>peach-blossom.js</code> file. Once you do this, you can use <code>bloom</code> anywhere.</p>
<pre><code>&lt;!-- This is html --&gt;
</code></pre><pre><code>&lt;script src=<span class="hljs-string">"peach-blossom.js"</span>&gt;&lt;<span class="hljs-regexp">/script&gt;&lt;script src="main.js"&gt;&lt;/</span>script&gt;
</code></pre><pre><code><span class="hljs-comment">// This is js</span>
</code></pre><pre><code><span class="hljs-comment">// main.jsbloom() // Bloom!</span>
</code></pre><p>Libraries usually have more than one piece of code. We don’t want to pollute the global scope with little variables. What we can do is wrap the functions we want to expose in an immediately-invoked function expression (IIFE).</p>
<p>This means:</p>
<ol>
<li>We create a function and run it immediately  </li>
<li>We return the library from within the function so we can use the library later.</li>
</ol>
<p>In code, it looks somewhat like this:</p>
<pre><code><span class="hljs-comment">// This is js</span>
</code></pre><pre><code><span class="hljs-comment">// peach-blossom.js const peachBlossom = (function () {  // Write as much code as you want here</span>
</code></pre><pre><code><span class="hljs-comment">// Return what others can use  return {    bloom: function () {      console.log('Bloom!')    }  }})()</span>
</code></pre><p>You can then use <code>bloom</code> anywhere by writing <code>peachBlossom.bloom</code>.</p>
<pre><code><span class="hljs-comment">// This is js</span>
</code></pre><pre><code><span class="hljs-comment">// main.jspeachBlossom.bloom() // Bloom!</span>
</code></pre><p>This is the basics of writing a frontend library.</p>
<p>Now, let’s talk about writing a library for Node.</p>
<h3 id="heading-writing-a-package-for-node"><strong>Writing a package for Node</strong></h3>
<p>Adding a library to Node is different from adding a library to browsers. This is because Node doesn’t have HTML files and <code>&lt;scri</code>pt&gt; tags.</p>
<p>Let’s make sure you know how to run Node before we begin writing a library for Node.</p>
<h4 id="heading-running-node">Running Node</h4>
<p>First, you need to make sure you have Node installed on your computer. You can install Node from <a target="_blank" href="https://nodejs.org/en/">Node’s website</a> if you don’t have it installed already.</p>
<p>Once you have Node installed, you’ll want to create a folder to store your Node project. In this case, let’s call it “node-project”.</p>
<p>The command to create a folder is this:</p>
<pre><code># This is bash
</code></pre><pre><code>mkdir node-project
</code></pre><p>Then, you need to navigate to the <code>node-project</code> directory. You can do it with <code>cd</code>:</p>
<pre><code># This is bashcd node-project
</code></pre><p>If you’re having problems with the command line, you can use <a target="_blank" href="https://zellwk.com/blog/fear-of-command-line/">this guide</a> to help you out.</p>
<p>Next, we want to create a file. This will be a JavaScript file. (We will run Node on this file). Let’s call it <code>index.js</code>.</p>
<pre><code># This is bash
</code></pre><pre><code>touch index.js
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/f0BgtmtrZh4oc2U58UuNiCxOVxx-ibcLd4nE" alt="Image" width="650" height="72" loading="lazy"></p>
<p>In <code>index.js</code>, we’re going to write a <code>console.log</code> statement. This is for us to know if we run the file.</p>
<pre><code><span class="hljs-comment">// This is js</span>
</code></pre><pre><code><span class="hljs-comment">// index.jsconsole.log('Running index.js!')</span>
</code></pre><p>Finally, you can use <code>node</code> to run <code>index.js</code>. Here’s the command:</p>
<pre><code># This is bash
</code></pre><pre><code>node index.js
</code></pre><p>Once you run <code>index.js</code>, you should see the <code>console.log</code> in the terminal. That’s how we know the file has run.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/b-KuiWqcDHmAGXKBJ6uVsJPwU6bdeRYTCow9" alt="Image" width="740" height="106" loading="lazy"></p>
<h4 id="heading-adding-libraries-to-node">Adding libraries to Node</h4>
<p>To add libraries to Node, you have to use the <code>require</code> statement. Once you add a library, you can use the library anywhere in the same JavaScript file.</p>
<p>Here’s an example:</p>
<pre><code><span class="hljs-comment">// This is js</span>
</code></pre><pre><code><span class="hljs-keyword">const</span> fs = <span class="hljs-built_in">require</span>(<span class="hljs-string">'fs'</span>)<span class="hljs-built_in">console</span>.log(fs)
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/tuH9M9aEGONU-7bU7OlXhK4knqSm0h7WLmN3" alt="Image" width="800" height="206" loading="lazy"></p>
<p>When you use <code>require</code>, Node looks for the library you specified in three places:</p>
<p>First, it checks whether the library is built into Node. In this example, <code>fs</code> is built directly into Node. You can use <code>fs</code> anytime if you use Node.</p>
<p>Second, it checks whether the library exists in the <code>node_modules</code> folder. These are user-installed libraries. You can add a library to the <code>node_modules</code> folder by running <code>npm install</code>.</p>
<p>Here’s an example where we install <code>express</code>, then require express in Node:</p>
<pre><code># This is bash
</code></pre><pre><code># Run <span class="hljs-built_in">this</span> <span class="hljs-keyword">in</span> the command linenpm install express
</code></pre><pre><code><span class="hljs-comment">// This is js</span>
</code></pre><pre><code><span class="hljs-comment">// Index.js const express = require('express')console.log(express)</span>
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/bcyHIXmeoXF45Sr4heQfBSnhFRiTMscQ1iIr" alt="Image" width="800" height="230" loading="lazy"></p>
<p>Third, if you add <code>./</code> to <code>require</code>, Node will look for a file located in the current directory. This is where we can begin writing the <code>peach-blossom</code> library.</p>
<h4 id="heading-writing-your-first-library-for-node">Writing your first library for Node</h4>
<p>Let’s start by creating a <code>peach-blossom.js</code> file. This file should be in the same directory as <code>index.js</code>.</p>
<pre><code><span class="hljs-comment">// This is js</span>
</code></pre><pre><code>touch peach-blossom.js
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/vHap18-jDq8MyfYna0XkLMbHFqeVF7EPQmXP" alt="Image" width="778" height="160" loading="lazy"></p>
<p>We can add <code>peach-blossom.js</code> to <code>index.js</code> by using <code>require</code>. Here’s what it looks like:</p>
<pre><code><span class="hljs-comment">// This is js</span>
</code></pre><pre><code><span class="hljs-keyword">const</span> peachBlossom = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./peach-blossom'</span>)
</code></pre><p>In Node, there’s no concept of a shared global scope. Each file has its own scope. So, if you write <code>peach-blossom.js</code> as if it’s used for frontend JavaScript, you won’t be able to use it. You’ll get an error.</p>
<pre><code><span class="hljs-comment">// This is js</span>
</code></pre><pre><code><span class="hljs-comment">// peach-blossom.js const peachBlossom = (function () { // Write as much code as you want here</span>
</code></pre><pre><code><span class="hljs-comment">// Return what others can use return { bloom: function () { console.log(‘Bloom!’) } }})()</span>
</code></pre><pre><code><span class="hljs-comment">// This is js</span>
</code></pre><pre><code><span class="hljs-comment">// index.js const peachBlossom = require(‘./peach-blossom’)</span>
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/DeVVpx8tTDzGn56qpevFYrfJnDX1RzQTIBcy" alt="Image" width="800" height="240" loading="lazy"></p>
<p>To pass variables from one file to another in Node, you have to write <code>module.exports</code>. Variables passed to <code>module.exports</code> can be retrieved from another file.</p>
<p>This means we must write <code>module.exports</code> in <code>peach-blossom.js</code>.</p>
<pre><code><span class="hljs-comment">// This is js</span>
</code></pre><pre><code><span class="hljs-comment">// Write as much code as you want here const peachBlossom = { bloom () { console.log(‘Bloom!’) }}</span>
</code></pre><pre><code><span class="hljs-comment">// Exports peachBlossom for use in other filesmodule.exports = peachBlossom</span>
</code></pre><p>Once we have exported <code>peachBlossom</code>, we can use it in other files:</p>
<pre><code><span class="hljs-comment">// This is js</span>
</code></pre><pre><code><span class="hljs-comment">// index.js const peachBlossom = require('./peach-blossom')peachBlossom.bloom() // Bloom!</span>
</code></pre><pre><code>
This format <span class="hljs-keyword">of</span> passing variables around <span class="hljs-keyword">in</span> Node <span class="hljs-keyword">with</span> <span class="hljs-string">`require`</span> and <span class="hljs-string">`module.exports`</span> is called **CommonJS**.

#### Publishing your library <span class="hljs-keyword">as</span> an npm package

In short, to make your <span class="hljs-built_in">module</span> work <span class="hljs-keyword">in</span> Node, you have to <span class="hljs-keyword">export</span> a variable <span class="hljs-keyword">with</span> <span class="hljs-string">`module.exports`</span>. Other people can then <span class="hljs-string">`require`</span> <span class="hljs-built_in">this</span> <span class="hljs-built_in">module</span> <span class="hljs-keyword">in</span> their code.

At <span class="hljs-built_in">this</span> point, you can move <span class="hljs-string">`peach-blossom`</span> into a separate project folder and publish it <span class="hljs-keyword">as</span> an npm package. You can use [<span class="hljs-built_in">this</span> guide](https:<span class="hljs-comment">//zellwk.com/blog/publish-to-npm/) to find out more about publishing the process.</span>

### Writing modules that are usable <span class="hljs-keyword">in</span> both frontend and backend JavaScript

Let’s take a moment to reconcile what we know.

To write a library <span class="hljs-keyword">for</span> the frontend, we need to declare it <span class="hljs-keyword">as</span> a variable. As much <span class="hljs-keyword">as</span> possible, we want to expose one variable only.
</code></pre><p>// This is js</p>
<pre><code>
</code></pre><p>const peachBlossom = (function () {  // Write as much code as you want here</p>
<pre><code>
</code></pre><p>// Return what others can use  return {    bloom: function () {      console.log('Bloom!')    }  }})()</p>
<pre><code>
To write a library <span class="hljs-keyword">for</span> the Node, we need to <span class="hljs-keyword">export</span> the variable <span class="hljs-keyword">with</span> <span class="hljs-string">`module.exports`</span>. Here, we only expose one variable.
</code></pre><p>// This is js// Write as much code as you want here const peachBlossom = {  bloom () {    console.log('Bloom!')  }}</p>
<pre><code>
</code></pre><p>// Exports peachBlossom for use in other filesmodule.exports = peachBlossom</p>
<pre><code>
But these are two completely different formats! How can we write a library once and use it <span class="hljs-keyword">in</span> both contexts?

Enter UMD.

#### UMD

[UMD (Universal Module Definition](https:<span class="hljs-comment">//github.com/umdjs/umd)) is a block of code we can use to wrap around our library. This block of code makes it possible to use a library both on the frontend and in Node.</span>

It kinda looks like <span class="hljs-built_in">this</span>:
</code></pre><p>// This is js</p>
<pre><code>
</code></pre><p>(function (root, factory) {    if (typeof define === 'function' &amp;&amp; define.amd) {        // AMD. Register as an anonymous module.        define(['b'], factory);    } else if (typeof module === 'object' &amp;&amp; module.exports) {        // Node.        module.exports = factory(require('b'));    } else {        // Browser globals (root is window)        root.returnExports = factory(root.b);    }}(typeof self !== 'undefined' ? self : this, function (b) {    // Use b in some fashion.</p>
<pre><code>
</code></pre><p>// Just return a value to define the module export.    // This example returns an object, but the module    // can return a function as the exported value.    return {};}));
```</p>
<p>Whoa! This is confusing! Hold up!</p>
<p>In practice, we don’t have to know how to UMD-ify our code by ourselves. Many tools, like Webpack and Parcel, gives us the ability to UMD-ify our code through them.</p>
<p>Here are some examples (and their relevant setup instructions):</p>
<ol>
<li><a target="_blank" href="https://github.com/eduardolundgren/gulp-umd">Gulp-umd</a>  </li>
<li><a target="_blank" href="https://webpack.js.org/guides/author-libraries/">Webpack</a>  </li>
<li><a target="_blank" href="https://parceljs.org/cli.html#expose-modules-as-umd">Parcel</a>  </li>
<li><a target="_blank" href="https://rollupjs.org/guide/en">Rollup</a></li>
</ol>
<p>This, means you have to set up these tools if you want to write packages that can be used for both Frontend JavaScript and in Node. Yes, it complicates the authoring process, but there’s nothing much we can do about it at this point.</p>
<h3 id="heading-wrapping-up">Wrapping up</h3>
<p>If you want your library to work both on Frontend JavaScript and in Node, you need to wrap your module with UMD (Universal Module Definition).</p>
<p>If you want to UMD-ify your code, you need to use a build tool when you author your package. This makes the authoring process more complicated. But the tradeoff can be worth it for providing users with an option to use your library anywhere.</p>
<p>This article was originally posted on <a target="_blank" href="https://zellwk.com/blog/publishing-npm-packages-that-can-be-used-in-browsers-and-node"><em>my blog</em></a>.<br>Sign up for my <a target="_blank" href="https://zellwk.com/">newsletter</a> if you want more articles to help you become a better frontend developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to ignore files from your npm package ]]>
                </title>
                <description>
                    <![CDATA[ You can decide what files people get when they download your npm package in three ways: With the .gitignore file With the .npmignore file With the files property We’ll look at each method and discuss which methods you should (or shouldn’t) be using... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-ignore-files-from-your-npm-package-4724e6d9575d/</link>
                <guid isPermaLink="false">66c4c7574173ed342943d0b5</guid>
                
                    <category>
                        <![CDATA[ npm ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Mon, 22 Apr 2019 16:02:00 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*F6R34rqTupBQxrVe7GS4fw.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>You can decide what files people get when they download your npm package in three ways:</p>
<ol>
<li>With the <code>.gitignore</code> file</li>
<li>With the <code>.npmignore</code> file</li>
<li>With the <code>files</code> property</li>
</ol>
<p>We’ll look at each method and discuss which methods you should (or shouldn’t) be using.</p>
<h3 id="heading-excluding-files-with-gitignore">Excluding files with gitignore</h3>
<p>First, npm will check your repository for a <code>.gitignore</code> file. If there is a <code>.gitignore</code> file, npm will ignore files according to what’s listed in the <code>.gitignore</code> file.</p>
<p>This is the most common way package authors prevent people from downloading extra files.</p>
<p>Let’s go through a simple example. Say you have the following directory structure.</p>
<pre><code>- project-name/   |- index.js   |- package.json   |- node_modules/
</code></pre><p>Let’s say you don’t want people to download the <code>node_modules</code> folder. You also don’t want to save the <code>node_modules</code> in the Git repository.</p>
<p>What you’ll do is create a <code>.gitignore</code> file.</p>
<pre><code># .gitignore node_modules
</code></pre><p>In this case, both Git and npm ignore the <code>node_modules</code> folder.</p>
<h3 id="heading-blacklisting-files-with-npmignore">Blacklisting files with npmignore</h3>
<p>A second way is to blacklist files with a <code>.npmignore</code> file. The <code>.npmignore</code> file works the same way as a <code>.gitignore</code> file. If a file is listed in the <code>.npmignore</code> file, the file will be excluded from the package.</p>
<p><strong>Important note:</strong> If you have a <code>.npmignore</code> file, npm will use the <code>.npmignore</code> file. <strong>npm will ignore the <code>.gitignore</code> file</strong> altogether. (Many developers mistakenly believe npm will use both <code>.npmignore</code> and <code>.gitignore</code> files. Don’t make the same mistake!)</p>
<p>You can use this method if you want to exclude files from the package but still keep them in the Git repository.</p>
<p>Let’s walk through another example. Let’s say you’ve written tests for your package and you put them all in a <code>tests</code> folder. This is your directory structure:</p>
<pre><code>- project-name/  |- index.js |- package.json |- node_modules/ |- tests/
</code></pre><p>You want to exclude <code>node_modules</code> from both your Git repository and your package.</p>
<p>You want to include <code>tests</code> in your Git repository, but exclude it from the package.</p>
<p>If you opt for the <code>npmignore</code> file method, you can write these in your <code>.gitignore</code> and <code>.npmignore</code> files:</p>
<pre><code># .gitignore node_modules
</code></pre><pre><code># .npmignore node_modules tests
</code></pre><h3 id="heading-whitelisting-files-with-the-files-property">Whitelisting files with the files property</h3>
<p>A third method is to <strong>whitelist</strong> files you want to be <strong>included</strong> in the <code>package.json</code> file, under the <code>files</code> property.</p>
<p>Note: npm will prioritize this method over other methods mentioned above. This is the easiest method to limit what files others download.</p>
<p>This approach is pretty simple. What you need is to create a <code>files</code> property in the <code>package.json</code> file. Then, provide a list of files you’d like to include.</p>
<p>Here’s an example:</p>
<pre><code>{   <span class="hljs-string">"files"</span>: [      <span class="hljs-string">"index.js"</span>   ] }
</code></pre><p>Note: Some files, like <code>package.json</code>, are <a target="_blank" href="https://docs.npmjs.com/files/package.json">always included</a> in a package. You don’t have to write these files in the <code>files</code> property.</p>
<h3 id="heading-which-method-to-use">Which method to use?</h3>
<p>All three methods work. Pick the one you’re most comfortable with. For simple projects, the <code>.gitignore</code> file method should suffice.</p>
<p>If your project is more advanced, you might want to blacklist files with <code>.npmignore</code> or whitelist files with the <code>files</code> property. Pick one. There’s no need for both.</p>
<h3 id="heading-a-quick-tip">A quick tip</h3>
<p>You can use <code>npm pack</code> to generate a package. This package includes files other people will get.</p>
<pre><code>npm pack
</code></pre><p>Try it!</p>
<p>Thanks for reading. Did this article help you out? If it did, I hope you consider <a target="_blank" href="https://twitter.com/share?text=How%20to%20ignore%20files%20from%20your%20npm%20package%20by%20@zellwk%20?%20&amp;url=https://zellwk.com/blog/ignoring-files-from-npm-package/">sharing it</a>. You might help someone else out. Thanks so much!</p>
<p>This article was originally posted on <a target="_blank" href="https://zellwk.com/blog/ignoring-files-from-npm-package/"><em>my blog</em></a><em>.</em><br>Sign up for my <a target="_blank" href="https://zellwk.com/">newsletter</a> if you want more articles to help you become a better front-end developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to publish packages to npm (the way the industry does things) ]]>
                </title>
                <description>
                    <![CDATA[ It’s simple to publish a package onto npm. There are two steps: Create your package. Publish the package. But publishing packages the way the industry does it? Not so simple. There are more steps. We’ll go through what steps are required, and I’ll ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-publish-packages-to-npm-the-way-the-industry-does-things-2077ec34d7e8/</link>
                <guid isPermaLink="false">66c4c7651b22d2d8d9040edf</guid>
                
                    <category>
                        <![CDATA[ coding ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ npm ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Tue, 09 Apr 2019 15:17:00 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/0*Nhf9jeZDYfGdX6N6.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>It’s simple to publish a package onto npm. There are two steps:</p>
<ol>
<li>Create your package.</li>
<li>Publish the package.</li>
</ol>
<p>But publishing packages the way the industry does it? Not so simple. There are more steps. We’ll go through what steps are required, and I’ll show you an easy way to publish and update your package.</p>
<h3 id="heading-creating-your-first-package">Creating your first package</h3>
<p>This section is for you if you haven’t published a package to npm before. Feel free to skip to the next section if you published one before.</p>
<p>To publish your first package to npm, you need to go through these steps:</p>
<p><strong>First, you need to have an npm account</strong>. Create one <a target="_blank" href="https://www.npmjs.com/signup">here</a> if you don’t have one yet.</p>
<p><strong>Second, you need to login to your npm account through the command line</strong>. (You need to have Node and npm installed on your system before you perform this step. Install them <a target="_blank" href="https://nodejs.org/en/">here</a>).</p>
<p>To sign in, you use <code>npm login</code>.</p>
<pre><code>npm login
</code></pre><p>You’ll be prompted to enter your username, password, and email address.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/JHhisobcBkv-CepU3oB0sjvuGJ3lpkQbqixh" alt="Image" width="800" height="233" loading="lazy"></p>
<p><strong>Third, you need to create a package</strong>. To do so, create a folder somewhere on your computer and navigate to it. The command line version is:</p>
<pre><code># Creating a folder named how-to-publish-to-npm mkdir how-to-publish-to-npm # Navigating into the folder cd how-to-publish-to-npm
</code></pre><p>Next, you want to begin the project with the <code>npm init</code> command.</p>
<pre><code>npm init
</code></pre><p>This command runs you through a few questions and creates a <code>package.json</code> file for you at the end. This <code>package.json</code> file contains the bare necessities you need to publish your project. (Feel free to skip questions that don’t make sense).</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/zkzI4ZMLfqEMMIfD2aFF6zfpxKpT54w5gU1Z" alt="Image" width="800" height="216" loading="lazy"></p>
<p><strong>The final step is to publish your package</strong> with the <code>npm publish</code> command.</p>
<pre><code>npm publish
</code></pre><p>If the package already exists on npm (because your package has the same name as another package on npm), you won’t be able to publish it. You’ll get an error.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/q8cTyrCM2nFMivMgtaW2Gi9Jcno1zquqViBU" alt="Image" width="800" height="498" loading="lazy"></p>
<p>You’ll need to change your package name.</p>
<p>To change your package name, you change the <code>name</code> property in the <code>package.json</code> file. Here, I changed it to <code>publishing-to-npm</code>.</p>
<p>(You can check for naming collisions by doing a search on npm, or through the <code>npm search</code> command).</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Gp-SPyfzY0nyDVKNJXa3GpFEahjKVuAfV8PD" alt="Image" width="800" height="204" loading="lazy"></p>
<p>It’s also a good idea to update the folder name as well for consistency. Here’s the command line equivalent.</p>
<pre><code># Command to change folder names by moving everything mv how-to-publish-to-npm publishing-to-npm
</code></pre><p>Try the <code>publish</code> command again. You should get a success message now.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/ASGCDDVtEEjdKoPqzdvA2Ux32pgXsdcE98xE" alt="Image" width="800" height="430" loading="lazy"></p>
<h3 id="heading-what-to-do-if-every-name-you-came-up-with-is-taken-already">What to do if every name you came up with is taken already</h3>
<p>This is a common problem since many people create packages on npm. It’s difficult to get the package name you desire sometimes. (It’s like how I can <em>never</em> find a good <code>.com</code> domain).</p>
<p>To combat this problem, npm lets you publish to a scope. This means you can publish the package under your own username (or npm organization), so you’re free from naming problems.</p>
<p>To publish to a scope, you can either:</p>
<ol>
<li>Change the <code>name</code> to <code>@username/package-name</code> manually in <code>package.json</code></li>
<li>Run <code>npm init --scope=username</code> instead of <code>npm init</code></li>
</ol>
<p>If your repository has a scope, you need to adjust the publish command slightly:</p>
<pre><code>npm publish --access public
</code></pre><p>That’s all you need to do to publish a package to npm.</p>
<p>Now, let’s move on to how the industry publishes packages.</p>
<p>Consider a popular framework like React. If you dig around React, you’ll notice a few things:</p>
<p>First, React has a <a target="_blank" href="https://github.com/facebook/react">Github repository</a>.</p>
<p>Second, React is <a target="_blank" href="https://www.npmjs.com/package/react">published on</a> npm.</p>
<p>Third, React follows <a target="_blank" href="https://zellwk.com/blog/semantic-versioning/">Semantic versioning</a> (Semver for short).</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/uwwUruPCdcFdhAmArNB-nBtUYcL7yb3x2J6R" alt="Image" width="800" height="617" loading="lazy"></p>
<p>Fourth, each update to React has a git tag associated with it. This git tag follows Semver as well.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/wZuV9GG8e9pkllgcdjrVIGmjK84bDs-atDeU" alt="Image" width="708" height="600" loading="lazy"></p>
<p>Fifth, there are <a target="_blank" href="https://github.com/facebook/react/releases">release notes</a> for every React update.</p>
<p>This means publishing a package involves many steps. At the very least, you need to:</p>
<ol>
<li>Run tests (if there are any)</li>
<li>Update <code>version</code> in <code>package.json</code> according to Semver</li>
<li>Create a git tag according to Semver</li>
<li>Push the package to Github</li>
<li>Push the package to npm</li>
<li>Create release notes for every update</li>
</ol>
<p>It’s common to forget one of these things when we’re ready to push. Sometimes we <code>npm publish</code> and we enjoy a break. When we’re back, we screw ourselves for forgetting.</p>
<p>There’s an easier way. It’s with a tool called <code>np</code>.</p>
<h3 id="heading-np">np</h3>
<p><a target="_blank" href="https://github.com/sindresorhus/np">np</a> (created by <a target="_blank" href="https://github.com/sindresorhus">Sindre Sorhus</a>) makes it easier for us to publish packages without missing any of the steps I detailed above.</p>
<h3 id="heading-installing-np">Installing np</h3>
<p>To install <code>np</code>, you can run the following command:</p>
<pre><code>npm install np
</code></pre><p>This works. But I prefer installing <code>np</code> globally on my computer so I can run the <code>np</code> command anywhere.</p>
<pre><code>sudo npm install --<span class="hljs-built_in">global</span> np
</code></pre><h3 id="heading-before-using-np">Before using np</h3>
<p>Before you use <code>np</code> you need to make sure:</p>
<ol>
<li>Your project is a Git repository</li>
<li>It needs to have a remote</li>
<li>You must have pushed to the remote at least once.</li>
<li>You also need to make sure your working directory is clean.</li>
</ol>
<pre><code># Initialize Git git init # Adds a remote repository git remote add origin some-url # Commit changes git add . git commit -m <span class="hljs-string">"Initial Commit"</span>
</code></pre><p>If your project is not a Git repository, you’ll get this error:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/7NrM2CyehgdU8hCtwioMAAIjFY1XD8yKfYYz" alt="Image" width="800" height="210" loading="lazy"></p>
<p>If your project doesn’t have remote, you’ll get this error (at a later part of the checks).</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/3Pb4qxEzdXr-Uu8xk6o84aTg1CbhPKff1aBT" alt="Image" width="800" height="234" loading="lazy"></p>
<p>If your working directory is dirty, you’ll get this error:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/OS9Wo5PaEyUDlmWh7ZWtig0Joik0GwRgnh6s" alt="Image" width="800" height="260" loading="lazy"></p>
<p>If you haven’t pushed to the Git remote at least once, <code>np</code> will just hang and do nothing.</p>
<h3 id="heading-using-npm">Using npm</h3>
<p>To use <code>np</code>, you run the <code>np</code> command.</p>
<pre><code>np
</code></pre><p><code>np</code> will prompt you to enter a Semver number.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/RD-MA-FOfYfODX9M8CemmsQRfNfGzoJfykQt" alt="Image" width="800" height="315" loading="lazy"></p>
<p>Choose a number and <code>np</code> will ask you to confirm your choice.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Kli5Ll2K9rNaLOQ1OokDMpEGoEoqxJ-kzDSZ" alt="Image" width="800" height="68" loading="lazy"></p>
<p><code>np</code> then does the rest of the publishing stuff for you.</p>
<h3 id="heading-error-with-running-tests">Error with running tests</h3>
<p><code>np</code> runs the <code>npm test</code> command as part of its checks.</p>
<p>If you followed the tutorial up to this point, you would get an error that looks like this:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/sORwnhnEitrpcWBx9JBa5zfkwk3jdx3eIhQE" alt="Image" width="800" height="306" loading="lazy"></p>
<p>This happens because our <code>npm test</code> command results in an error. You can try it yourself:</p>
<pre><code>npm test
</code></pre><p><img src="https://cdn-media-1.freecodecamp.org/images/QQ28caWQvveRLIwk3jwcUkBhbLFDUMSy3Qe1" alt="Image" width="800" height="189" loading="lazy"></p>
<p>To fix this error, we need to change the <code>test</code> script in <code>package.json</code> file.</p>
<p>Right now it looks like this:</p>
<pre><code><span class="hljs-string">"scripts"</span>: {     <span class="hljs-string">"test"</span>: <span class="hljs-string">"echo \"Error: no test specified\" &amp;&amp; exit 1"</span>},
</code></pre><p>Change it to this:</p>
<pre><code><span class="hljs-string">"scripts"</span>: {     <span class="hljs-string">"test"</span>: <span class="hljs-string">"echo \"No test specified\""</span>},
</code></pre><p>This change works because <code>exit 1</code> creates an error.</p>
<p>With this change, <code>np</code> should complete the publishing process. (Remember to commit the change before running <code>np</code>).</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/NFPTeC5esUzD1vLJczEy-meWcFJb1qPCEi8o" alt="Image" width="800" height="371" loading="lazy"></p>
<p>At the end of the process, <code>np</code> launches a browser window for you to write your release notes.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/Erm2uLF-N8B4b6jCa5C0AkgwqMfD5sbqZIjf" alt="Image" width="800" height="312" loading="lazy"></p>
<p>In short, <code>np</code> makes publishing packages much simpler!</p>
<p>Thanks for reading. Did this article help you out? If it did, I hope you consider <a target="_blank" href="https://twitter.com/share?text=How%20to%20publish%20packages%20to%20npm%20(the%20way%20the%20industry%20does%20things)%20by%20@zellwk%20?%20&amp;url=https://zellwk.com/blog/publish-to-npm/">sharing it</a>. You might help someone else out. Thanks so much!</p>
<p>This article was originally posted at <a target="_blank" href="https://zellwk.com/blog/publish-to-npm"><em>my blog</em></a>.<br>Sign up for my <a target="_blank" href="https://zellwk.com/">newsletter</a> if you want more articles to help you become a better frontend developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to use JSDelivr ]]>
                </title>
                <description>
                    <![CDATA[ Easily download JavaScript libraries from npm and GitHub The most newbie-friendly way to add a library to a project is to: Search for the library Look for the source file Copy the source file Paste what you copied into the project. This works, but ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-jsdelivr-e64e5590f66e/</link>
                <guid isPermaLink="false">66c4c77e99f22436b71945fc</guid>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Productivity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Mon, 08 Apr 2019 15:54:55 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*q1qvRLnBI5meBDrgpZW-BQ.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <h4 id="heading-easily-download-javascript-libraries-from-npm-and-github">Easily download JavaScript libraries from npm and GitHub</h4>
<p>The most newbie-friendly way to add a library to a project is to:</p>
<ol>
<li>Search for the library</li>
<li>Look for the source file</li>
<li>Copy the source file</li>
<li>Paste what you copied into the project.</li>
</ol>
<p>This works, but it’s a painful process. It’s easier if you use CDNs like JSDelivr.</p>
<h3 id="heading-what-is-a-cdn">What is a CDN?</h3>
<p>CDN stands for content delivery network. Its main purpose is to let users download files faster. Read <a target="_blank" href="https://www.fastly.com/blog/why-you-should-use-content-delivery-network">this article</a> by Fastly if you’re wondering whether you should use a CDN.</p>
<p>CDNS let users download files faster by placing datacenters all over the world. When the browser sees a CDN link, they’ll serve up the library from the datacenter closest to the user. This is how CDNs work.</p>
<h3 id="heading-what-is-jsdelivr">What is JSDelivr?</h3>
<p>JSDelivr is a special kind of CDN. It’s built to let users download JavaScript libraries that are hosted on npm and Github. (You can also load Wordpress plugins if they’re hosted on Wordpress.org).</p>
<p>If you use JSDelivr (or any other CDN that serves JavaScript libraries), you don’t need to copy-paste the source files into your project. You can use a link like this:</p>
<pre><code>&lt;script src=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/package-name"</span>&gt;&lt;;/script&gt;
</code></pre><p>JSDelivr lets you specify the version of a library you want to download. If you want to specify a version, you add the version number after an <code>@</code>, like this:</p>
<pre><code>&lt;script src=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/[email protected]"</span>&gt;&lt;;/script&gt;
</code></pre><h3 id="heading-how-i-use-jsdelivr">How I use JSDelivr</h3>
<p><strong>I use JSDelivr more like a package manager</strong> since JSDelivr lets you specify the version of a library. I can upgrade or downgrade the library by changing a number. There’s no need to copy-paste the original source into my project.</p>
<p>However, <strong>I rarely use JSDelivr nowadays</strong> because I already have a build process that uses Webpack. Webpack lets you <code>require</code> libraries into frontend JavaScript. It lets you use npm as a package manager.</p>
<p><strong>I only use JSDelivr for projects that:</strong></p>
<ol>
<li>Require a library</li>
<li>The library exists on JSDelivr (or other CDNs)</li>
<li>The project doesn’t have Webpack (or similar tools installed)</li>
</ol>
<p>One example of such a project is the 20 components in <a target="_blank" href="https://learnjavascript.today/">Learn JavaScript</a>.</p>
<p>Here’s why.</p>
<p>Students who’re enrolled in Learn JavaScript are trying to learn JavaScript. I don’t want to distract them by making them learn Webpack.</p>
<p>Instead, I want to help them focus on what they’re here for — learning JavaScript. I do this by removing complexity from projects we build together. I strip everything down to plain old HTML, CSS, and JavaScript.</p>
<p>We’ve talked about what is JSDelivr, why use it, and when to use it. Let’s dive into the details of using it now.</p>
<p>For the rest of the article, we’ll use a library called <a target="_blank" href="https://github.com/zellwk/zl-fetch">zl-fetch</a> as an example.</p>
<h3 id="heading-installing-a-library">Installing a library</h3>
<p>To install a library, you need to add a <code>&lt;scri</code>pt&gt; tag that points to the library on JSDelivr. You can load the library from npm or Github, depending on your preferences.</p>
<p>I tend to load libraries from npm.</p>
<pre><code>&lt;script src=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/package-name"</span>&gt;&lt;;/script&gt;
</code></pre><p>You need to change <code>package-name</code> to the name of the library you’re installing. In this case, it’s <code>zl-fetch</code>.</p>
<pre><code>&lt;script src=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/zl-fetch"</span>&gt;&lt;;/script&gt;
</code></pre><p>If you’re unsure of the name of the library, you can search on <a target="_blank" href="https://www.npmjs.com/">npm</a>, or directly on <a target="_blank" href="https://www.jsdelivr.com/">JSDelivr</a>.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/CndXOzCC03uVBwhf73T-AjP5qZxSjOLKzH4F" alt="Image" width="800" height="113" loading="lazy"></p>
<h3 id="heading-specifying-a-version">Specifying a version</h3>
<p>By default, JSDelivr downloads the latest version of a library.</p>
<p>I don’t recommend you use the latest version because authors may update their library. If they update their library, your code may break.</p>
<p><strong>You always want to specify a version number.</strong> You can add a version number by adding <code>@</code>, followed by the version number after the package name, like this:</p>
<pre><code>&lt;script src=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/[email protected]"</span>&gt;&lt;;/script&gt;
</code></pre><p><strong>Version numbers follow a <a target="_blank" href="https://zellwk.com/blog/semantic-versioning/">Semver</a> format.</strong> You can tell what versions are available by checking the available tags on Github.</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/DvX7KL57jCAeQmDTJLSuhyMjtGTlyabzYuPv" alt="Image" width="720" height="1174" loading="lazy"></p>
<p>In our case, the current version of <code>zl-fetch</code> is <code>2.1.9</code>:</p>
<pre><code>&lt;script src=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/[email protected]"</span>&gt;&lt;;/script&gt;
</code></pre><h3 id="heading-loading-a-specific-file">Loading a specific file</h3>
<p>JSDelivr relies on authors to specify a default file for the above format to work. <strong>If the default file is not specified, you need to point to the correct file.</strong></p>
<pre><code>&lt;script src=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/[email protected]/path-to-file"</span>&gt;&lt;;/script&gt;
</code></pre><p>There are two ways to know what files are available.</p>
<p>First, you can search for the package on JSDelivr. You’ll see a list of files and folders you can point to:</p>
<p><img src="https://cdn-media-1.freecodecamp.org/images/mK4mbrhilqZjV1wau0pffsmFst5cQXWIug0n" alt="Image" width="800" height="497" loading="lazy"></p>
<p>Second, if you know about npm, you can use npm to install the package somewhere on your computer. Then use your Finder (or Explorer) to browse through the files.</p>
<p>In this case, let’s say the default file is not specified, and we want the <code>dist/index.js</code> file. Here’s what you’ll write:</p>
<pre><code>&lt;script src=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/[email protected]/dist/index.js"</span>&gt;&lt;;/script&gt;
</code></pre><h3 id="heading-loading-a-minified-version">Loading a minified version</h3>
<p>Minified files are usually smaller in size. Users will be able to download the minified files faster than an unminified file.</p>
<p>JSDelivr minifies files automatically if you use the <code>.min.js</code> extension.</p>
<pre><code>&lt;script src=<span class="hljs-string">"https://cdn.jsdelivr.net/npm/[email protected]/dist/index.min.js"</span>&gt;&lt;;/script&gt;
</code></pre><h3 id="heading-wrapping-up">Wrapping up</h3>
<p>I hope this article gives you a good overview of what JSDelivr can do.</p>
<p>Thanks for reading. Did this article help you out? If it did, I hope you consider <a target="_blank" href="https://twitter.com/share?text=How%20to%20use%20JSDelivr%20by%20@zellwk%20?%20&amp;url=https://zellwk.com/blog/jsdelivr/">sharing it</a>. You might help someone else out. Thanks so much!</p>
<p>This article was originally posted at <a target="_blank" href="https://zellwk.com/blog/jsdelivr"><em>my blog.</em></a><br>Sign up for my <a target="_blank" href="https://zellwk.com/">newsletter</a> if you want more articles to help you become a better frontend developer.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How I style my websites with my favorite CSS resets ]]>
                </title>
                <description>
                    <![CDATA[ Many frontend developers begin styling their websites with Normalize. Some developers have personal preferences that they add on to Normalize.css. I have my preferences, too. In this article, I want to share these preferences with you, my personal CS... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-i-style-my-websites-with-my-favorite-css-resets-7ace41dbc43d/</link>
                <guid isPermaLink="false">66c4c736bd556981b1bdc46a</guid>
                
                    <category>
                        <![CDATA[ CSS ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ General Programming ]]>
                    </category>
                
                    <category>
                        <![CDATA[ tech  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zell Liew ]]>
                </dc:creator>
                <pubDate>Mon, 25 Mar 2019 18:05:27 +0000</pubDate>
                <media:content url="https://cdn-media-1.freecodecamp.org/images/1*cHZLhJhJgiRK48Dzhem5-w.jpeg" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Many frontend developers begin styling their websites with Normalize. Some developers have personal preferences that they add on to Normalize.css. I have my preferences, too.</p>
<p>In this article, I want to share these preferences with you, my personal CSS reset (that I use in addition to Normalize.css).</p>
<p>I categorize the resets into 8 categories:</p>
<ol>
<li><p>Box sizing</p>
</li>
<li><p>Removing margins and paddings</p>
</li>
<li><p>Lists</p>
</li>
<li><p>Forms and buttons</p>
</li>
<li><p>Images and embeds</p>
</li>
<li><p>Tables</p>
</li>
<li><p>The hidden attribute</p>
</li>
<li><p>Noscript</p>
</li>
</ol>
<h1 id="heading-box-sizing">Box Sizing</h1>
<p>The <code>box-sizing</code> property changes how the CSS Box model works. It changes how <code>width</code>, <code>height</code>, <code>padding</code>, <code>border</code>, and <code>margin</code> properties are calculated.</p>
<p>The default setting for <code>box-sizing</code> is <code>content-box</code>. I prefer changing this to <code>border-box</code> because it’s easier for me to style <code>padding</code> and <code>width</code>.</p>
<p>For more info on Box Sizing, you might be interested in “<a target="_blank" href="https://zellwk.com/blog/understanding-css-box-sizing/">Understanding Box sizing</a>”.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">html</span> {
  <span class="hljs-attribute">box-sizing</span>: border-box;
}
*,
*<span class="hljs-selector-pseudo">::before</span>,
*<span class="hljs-selector-pseudo">::after</span> {
  <span class="hljs-attribute">box-sizing</span>: inherit;
}
</code></pre>
<h1 id="heading-removing-margins-and-paddings">Removing margins and paddings</h1>
<p>Browsers set different margins and paddings for different elements. These default settings throw me off when I’m not aware. When I code, I prefer to set all margins and paddings myself.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Reset margins and paddings on most elements */</span>
<span class="hljs-selector-tag">body</span>,
<span class="hljs-selector-tag">h1</span>,
<span class="hljs-selector-tag">h2</span>,
<span class="hljs-selector-tag">h3</span>,
<span class="hljs-selector-tag">h4</span>,
<span class="hljs-selector-tag">h5</span>,
<span class="hljs-selector-tag">h6</span>,
<span class="hljs-selector-tag">ul</span>,
<span class="hljs-selector-tag">ol</span>,
<span class="hljs-selector-tag">li</span>,
<span class="hljs-selector-tag">p</span>,
<span class="hljs-selector-tag">pre</span>,
<span class="hljs-selector-tag">blockquote</span>,
<span class="hljs-selector-tag">figure</span>,
<span class="hljs-selector-tag">hr</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
}
</code></pre>
<h1 id="heading-lists">Lists</h1>
<p>I use unordered lists in many situations, and I don’t need a <code>disc</code> style in most of them. Here, I set <code>list-style</code> to none. When I need the <code>disc</code>style, I set it back manually on the specific <code>&lt;ul&gt;</code>.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* Removes discs from ul */</span>
<span class="hljs-selector-tag">ul</span> {
  <span class="hljs-attribute">list-style</span>: none;
}
</code></pre>
<h1 id="heading-forms-and-buttons">Forms and buttons</h1>
<p>Browsers don’t inherit typography for forms and buttons. They set <code>font</code> to <code>400 11px system-ui</code>. I find this mind-boggling and weird. I always have to make them inherit from ancestor elements manually.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">input</span>,
<span class="hljs-selector-tag">textarea</span>,
<span class="hljs-selector-tag">select</span>,
<span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">color</span>: inherit; 
  <span class="hljs-attribute">font</span>: inherit; 
  <span class="hljs-attribute">letter-spacing</span>: inherit; 
}
</code></pre>
<p>Different browsers have styled the borders for forms elements and buttons differently. I dislike these default styles, and would prefer to set them to <code>1px solid gray</code>.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">button</span> {
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">0</span>; 
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.75em</span> <span class="hljs-number">1em</span>;
  <span class="hljs-attribute">background-color</span>: transparent;
}
</code></pre>
<p>I made a few more adjustments to buttons:</p>
<ol>
<li>Set button padding to <code>0.75em</code> and <code>1em</code> because they seem like sensible defaults from my experience.</li>
<li>Removed the default <code>border-radius</code> that’s applied to buttons.</li>
<li>Forced background color to be transparentbutton {   border-radius: 0;    padding: 0.75em 1em;   background-color: transparent; }</li>
</ol>
<p>Finally, I set <code>pointer-events: none</code> to elements within a button. This is mainly used for JavaScript interaction.</p>
<p>(When users click on something in a button, <code>event.target</code> is the thing they clicked on, not the button. This style makes it easier to work with <code>click</code> events if there are HTML elements inside a button).</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">css</span> <span class="hljs-selector-tag">button</span> * {   <span class="hljs-attribute">pointer-events</span>: none; }
</code></pre>
<p>Media elements include images, videos, objects, iframes, and embed. I tend to let these elements conform to the width of their containers.</p>
<p>I also set these elements to <code>display: block</code> because <code>inline-block</code>creates unwanted whitespace at the bottom of the element.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">embed</span>,
<span class="hljs-selector-tag">iframe</span>,
<span class="hljs-selector-tag">img</span>,
<span class="hljs-selector-tag">object</span>,
<span class="hljs-selector-tag">video</span> {
  <span class="hljs-attribute">display</span>: block;
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">100%</span>;
}
</code></pre>
<h1 id="heading-tables">Tables</h1>
<p>I rarely use tables, but they may be useful sometimes. Here’s the default styles I’ll begin with:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">table</span> {
  <span class="hljs-attribute">table-layout</span>: fixed;
  <span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
}
</code></pre>
<p>When an element has a <code>hidden</code> attribute, they should be hidden from view. Normalize.css does this for us already.</p>
<pre><code class="lang-css"><span class="hljs-selector-attr">[hidden]</span> {
  <span class="hljs-attribute">display</span>: none;
}
</code></pre>
<p>The problem with this style is its low specificity.</p>
<p>I often add <code>hidden</code> to other elements I style with a class. A class’s specificity is high than an attribute, and the <code>display: none</code> property doesn’t work.</p>
<p>This is why I opt to bump up <code>[hidden]</code>'s specificity with <code>!important</code>.</p>
<pre><code class="lang-css"><span class="hljs-selector-attr">[hidden]</span> {
  <span class="hljs-attribute">display</span>: none <span class="hljs-meta">!important</span>;
}
</code></pre>
<h1 id="heading-noscript">Noscript</h1>
<p>If a component requires JavaScript to work, I’ll add a <code>&lt;noscript&gt;</code> tag to let users know (if they’ve disabled JavaScript).</p>
<p>This creates default styles for the <code>&lt;noscript&gt;</code> tag.</p>
<pre><code class="lang-css"><span class="hljs-comment">/* noscript styles */</span>
<span class="hljs-selector-tag">noscript</span> {
  <span class="hljs-attribute">display</span>: block;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">1em</span>;
  <span class="hljs-attribute">margin-top</span>: <span class="hljs-number">1em</span>;
}
</code></pre>
<h1 id="heading-wrapping-up">Wrapping up</h1>
<p>Everyone begins their projects differently. Please feel free to use any of these styles I mentioned. Here’s a <a target="_blank" href="https://github.com/zellwk/css-reset">Github repo</a> of my personal CSS Resets.</p>
<p>Do you have any recommendations that would help improve this CSS Reset file? If you do, feel free to reach out and let me know!</p>
<p>Thanks for reading. Did this article help you out? If it did, I hope you consider <a target="_blank" href="https://twitter.com/share?text=My%20CSS%20reset%20by%20@zellwk%20%F0%9F%91%87%20&amp;url=https://zellwk.com/blog/css-reset/">sharing it</a>. You might help someone else out. Thanks so much!</p>
<hr>
<p>This article was originally posted at <a target="_blank" href="https://zellwk.com/blog/css-reset">my blog</a>. Sign up for my <a target="_blank" href="https://zellwk.com/">newsletter</a> if you want more articles to help you become a better frontend developer.</p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
