<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Abdullah Atta</title>
    <description>The latest articles on DEV Community by Abdullah Atta (@thecodrr).</description>
    <link>https://dev.to/thecodrr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F350056%2Fc4592e92-5aae-499b-b7d3-f06ed26ca95e.jpeg</url>
      <title>DEV Community: Abdullah Atta</title>
      <link>https://dev.to/thecodrr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/thecodrr"/>
    <language>en</language>
    <item>
      <title>Notesnook is now open source!</title>
      <dc:creator>Abdullah Atta</dc:creator>
      <pubDate>Sat, 03 Sep 2022 17:10:40 +0000</pubDate>
      <link>https://dev.to/thecodrr/notesnook-is-now-open-source-2i93</link>
      <guid>https://dev.to/thecodrr/notesnook-is-now-open-source-2i93</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Hi! I am Abdullah Atta, the co-founder of Notesnook. I am &lt;em&gt;really, really&lt;/em&gt; excited to share this news with the dev.to community. We have officially open sourced all of our client apps (sync server to be open sourced soon) on GitHub. We'd love if the community chimes in &amp;amp; support us on this new journey!&lt;/p&gt;
&lt;/blockquote&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/streetwriters" rel="noopener noreferrer"&gt;
        streetwriters
      &lt;/a&gt; / &lt;a href="https://github.com/streetwriters/notesnook" rel="noopener noreferrer"&gt;
        notesnook
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A fully open source &amp;amp; end-to-end encrypted note taking alternative to Evernote.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/streetwriters/notesnook./resources/icon.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fstreetwriters%2Fnotesnook.%2Fresources%2Ficon.png" alt="Notesnook Logo" width="100"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Notesnook&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;An end-to-end encrypted note taking alternative to Evernote.&lt;/h3&gt;
&lt;/div&gt;

&lt;p&gt;
&lt;a href="https://notesnook.com/" rel="nofollow noopener noreferrer"&gt;Website&lt;/a&gt; | &lt;a href="https://notesnook.com/about" rel="nofollow noopener noreferrer"&gt;About us&lt;/a&gt; | &lt;a href="https://notesnook.com/roadmap" rel="nofollow noopener noreferrer"&gt;Roadmap&lt;/a&gt; | &lt;a href="https://notesnook.com/downloads" rel="nofollow noopener noreferrer"&gt;Downloads&lt;/a&gt; | &lt;a href="https://twitter.com/@notesnook" rel="nofollow noopener noreferrer"&gt;Twitter&lt;/a&gt; | &lt;a href="https://discord.gg/5davZnhw3V" rel="nofollow noopener noreferrer"&gt;Discord&lt;/a&gt;
&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Overview&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;Notesnook is a free (as in speech) &amp;amp; open-source note-taking app focused on user privacy &amp;amp; ease of use. To ensure zero knowledge principles, Notesnook encrypts everything on your device using &lt;code&gt;XChaCha20-Poly1305&lt;/code&gt; &amp;amp; &lt;code&gt;Argon2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Notesnook is our &lt;strong&gt;proof&lt;/strong&gt; that privacy does &lt;em&gt;not&lt;/em&gt; (always) have to come at the cost of convenience. We aim to provide users peace of mind &amp;amp; 100% confidence that their notes are safe and secure. The decision to go fully open source is one of the most crucial steps towards that.&lt;/p&gt;

&lt;p&gt;This repository contains all the code required to build &amp;amp; use the Notesnook web, desktop &amp;amp; mobile clients. If you are looking for a full feature list or screenshots, please check the &lt;a href="https://notesnook.com/" rel="nofollow noopener noreferrer"&gt;website&lt;/a&gt;.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Developer guide&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Technologies &amp;amp; languages&lt;/h3&gt;

&lt;/div&gt;

&lt;p&gt;Notesnook is built…&lt;/p&gt;
&lt;/div&gt;


&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/streetwriters/notesnook" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;


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

&lt;p&gt;&lt;a href="https://notesnook.com/" rel="noopener noreferrer"&gt;Notesnook&lt;/a&gt; started out as a passion project back in 2019 (3 years after Standard Notes) after I got really frustrated by the lack of good, usable &amp;amp; privacy note taking apps in the market. It might not sound like a pain point to you but privacy is a critical issue in today's digital world &amp;amp; my notes contain my most private thoughts. If you don't share this opinion, I don't blame you.&lt;/p&gt;

&lt;p&gt;Google has popularized the "100% free" concept in almost all markets. Look at Google Keep, Gmail, Calendar, Maps &amp;amp; the whole GSuite. Most of it is offered free of charge. Why? Are they crazy? It makes no sense until you realize that Google is primarily an Ads company. They thrive on user data.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If it's free, you are paying with your data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Notesnook is our take on how note taking &lt;em&gt;should&lt;/em&gt; be done. It features 100% end-to-end encrypted sync (free &amp;amp; unlimited for all), encrypted attachments (unlimited storage for as low as $0.99/mo) &amp;amp; encrypted publishing of notes (again free for all). It is a fully cross-platform app built using React &amp;amp; React Native with a primary focus on feature parity. In fact, all our clients have 99% feature parity (something no other note taking app can claim).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkn6d21tzw3vqwx0tzz6n.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkn6d21tzw3vqwx0tzz6n.jpg" alt="A first look at Notesnook web client"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why open source? Why now?
&lt;/h2&gt;

&lt;p&gt;The truth is that we are late to the party. Notesnook was our first rodeo &amp;amp; we didn't realize how important open sourcing is for our users to inspire trust &amp;amp; confidence until much, much later. Better late than never though, right?&lt;/p&gt;

&lt;p&gt;Our mission is to make Notesnook a quality product in the open source space like Docker, Nginx, PostHog etc. When we started out Notesnook, we asked ourselves 1 question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Is it possible to create a privacy respecting note taking service without compromising on convenience &amp;amp; usability?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And here is our proof.&lt;/p&gt;

&lt;h2&gt;
  
  
  What kind of open source?
&lt;/h2&gt;

&lt;p&gt;We are open sourcing Notesnook under &lt;code&gt;(A)GPL-3.0-or-later&lt;/code&gt;. We will not tolerate any compromise on our users' freedom, privacy &amp;amp; peace of mind.&lt;/p&gt;

&lt;p&gt;We open sourced Notesnook on September 1 and the response has been huge so far. I summarized our overall experienced in this tweet (would love if you give a follow!)&lt;/p&gt;

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

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



&lt;/p&gt;

&lt;h2&gt;
  
  
  How can you help?
&lt;/h2&gt;

&lt;p&gt;We are a small company based in Pakistan entirely self-funded without any VC backing us. We don't have thousands of dollars for ad revenue or influential patrons who'll push us to the edge. All we have is platforms like these.&lt;/p&gt;

&lt;p&gt;We'd love if you can &lt;a href="https://github.com/streetwriters/notesnook" rel="noopener noreferrer"&gt;star our GitHub repo&lt;/a&gt;, become a contributor, spread the word of privacy &amp;amp; tell others about your experience with Notesnook. If you have a platform (podcast, blog, etc.), we'd love to get featured. If you'd like to collaborate with us, we are listening.&lt;/p&gt;

&lt;p&gt;That's all. I hope Notesnook will make a difference.&lt;/p&gt;

&lt;p&gt;— &lt;em&gt;May privacy reign&lt;/em&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>javascript</category>
      <category>react</category>
      <category>reactnative</category>
    </item>
    <item>
      <title>Constants In JavaScript (and all that bulls**t)</title>
      <dc:creator>Abdullah Atta</dc:creator>
      <pubDate>Wed, 18 Mar 2020 17:10:00 +0000</pubDate>
      <link>https://dev.to/thecodrr/constants-in-javascript-and-all-that-bulls-t-481k</link>
      <guid>https://dev.to/thecodrr/constants-in-javascript-and-all-that-bulls-t-481k</guid>
      <description>&lt;p&gt;If you have been programming in JavaScript for a little while you'd have noticed that &lt;code&gt;const&lt;/code&gt; in JavaScript does not mean you can't change it. There's also no memory, performance or any other benefit. WTF!&lt;/p&gt;

&lt;p&gt;Okay, okay. Look at this piece of code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toastStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;burnt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// why though?&lt;/span&gt;
&lt;span class="c1"&gt;// let's change this&lt;/span&gt;
&lt;span class="nx"&gt;toastStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;not ok&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You will be expecting that it will give an error, right? Yup. You are right. It does give this error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;Uncaught TypeError: Assignment to constant variable.&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So far so good. Let's say we want to give an &lt;code&gt;id&lt;/code&gt; to the toast status:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toast&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;da_best_toast&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;burnt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And something happens and this toast suddenly becomes unburnt (accidentally of course):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all ok&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You'd be an expecting the same old error, right? But guess what? No error. Not even a hint. It's all okay (as the toast said). WTF! Same is the case with any &lt;code&gt;Object&lt;/code&gt; (i.e. Arrays, Objects, Classes, Functions etc. etc.)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;WTF!!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Okay, okay. I guess that's a good enough rant for now. SO what's the problem?&lt;/p&gt;
&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;Nothing is immutable in JavaScript. Nothing is unchangable in JavaScript. Anything can become anything in JavaScript. That's why you have TypeScript but even then there are some quirks in JavaScript that will make you pull your hair out.&lt;/p&gt;

&lt;p&gt;So what do we do if we want perfect immutability? Such that no one can change the object. At all?&lt;/p&gt;

&lt;p&gt;You could use a third-party library like: &lt;code&gt;Immutable-Js&lt;/code&gt; or &lt;code&gt;immer&lt;/code&gt;. But why? Why, why, why? When JavaScript can do it but for some reason doesn't do it by default (via the &lt;code&gt;const&lt;/code&gt; keyword)?&lt;/p&gt;

&lt;p&gt;If you haven't noticed by now: Objects are extensible in JavaScript. Meaning you can add, delete or edit without any restriction. Any Object. Even the standard ones like &lt;code&gt;global&lt;/code&gt; or &lt;code&gt;window&lt;/code&gt;. Now, I understand that that is a cool thing and all but it has many, many disadvantages. So let's try to make our objects...constant.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Solution..s
&lt;/h2&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Object.freeze&lt;/code&gt;:
&lt;/h3&gt;

&lt;p&gt;From MDN:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The Object.freeze() method freezes an object. A frozen object can no longer be changed; freezing an object prevents new properties from being added to it, existing properties from being removed, prevents changing the enumerability, configurability, or writability of existing properties, and prevents the values of existing properties from being changed. In addition, freezing an object also prevents its prototype from being changed. freeze() returns the same object that was passed in.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I think you got the point. It makes your object unchangable. Forever.&lt;/p&gt;

&lt;p&gt;Here's the same example as above:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;toast&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;da_best_toast&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;burnt&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Now if you wanted to change the status like this:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;all ok&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;It will give this error (be a good kid and turn on &lt;code&gt;strict mode&lt;/code&gt;):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;TypeError: Cannot assign to read only property 'done' of object '#&amp;lt;Object&amp;gt;'&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And later if you accidentally add another property:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bread&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;baba bread&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

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

&lt;/div&gt;


&lt;p&gt;It will give another error:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;TypeError: Cannot add property bread, object is not extensible&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And then if you try and delete the &lt;code&gt;status&lt;/code&gt; (accidentally, of course):&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You'd get:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;TypeError: Cannot delete property 'done' of #&amp;lt;Object&amp;gt;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this way you can make any Object immutable. You could also write a utility function like this, to make it a bit flashier:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;im&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// and then use it like so:&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;immutable&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;im&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;some_data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And if you wanted to check whether an object is frozen, simply do:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isFrozen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;toast&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// === true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;Now what if you wanted to only disallow new properties from being added/deleted but allow existing properties from being changed. In other words, what if you wanted "partial" immutability?&lt;/p&gt;

&lt;p&gt;Well, for that you have:&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Object.seal&lt;/code&gt;:
&lt;/h3&gt;

&lt;p&gt;From MDN:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;Object.seal()&lt;/code&gt; method seals an object, preventing new properties from being added to it and marking all existing properties as non-configurable. Values of present properties can still be changed as long as they are writable.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So basically, it will only allow existing properties from being edited (not deleted). Let's see an example.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;seal&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;stable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;speed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;50mbps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;connected&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// let's suppose, the network is disconnected suddenly, you'd simply do:&lt;/span&gt;
&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;disconnected&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// however if you wanted to add upstream speed, it will throw:&lt;/span&gt;
&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;upstream&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;25mbps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// or if you try and delete, it will also throw.&lt;/span&gt;
&lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You can easily check if an object is sealed or not using:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isSealed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;network&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// === true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;So far so good. But what if you wanted to disallow only additions but allow edits and deletions? For that you have &lt;code&gt;Object.preventExtensions&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  &lt;code&gt;Object.preventExtensions&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;From MDN:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The &lt;code&gt;Object.preventExtensions()&lt;/code&gt; method prevents new properties from ever being added to an object (i.e. prevents future extensions to the object).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's see an example:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;preventExtensions&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Baker Yota&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;35&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="c1"&gt;// now let's say you wanted to add a new property, it will throw.&lt;/span&gt;
&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;father&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Samhil Yota&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;

&lt;span class="c1"&gt;// But you can edit the age:&lt;/span&gt;
&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// And delete it too:&lt;/span&gt;
&lt;span class="k"&gt;delete&lt;/span&gt; &lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;age&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And if you wanted to check whether an object is extensible or not, simply do:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isExtensible&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;person&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// === false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;So there you have it: &lt;strong&gt;Immutability in JavaScript&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Notes:
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Objects that are manipulated in this way do not have their references altered. So &lt;code&gt;frozen_object === real_object&lt;/code&gt; gives &lt;code&gt;true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;You can put in any kind of &lt;code&gt;Object&lt;/code&gt;. Be it an &lt;code&gt;Array&lt;/code&gt;, &lt;code&gt;Function&lt;/code&gt;, &lt;code&gt;Class&lt;/code&gt; etc.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  Conclusion:
&lt;/h2&gt;

&lt;p&gt;Javascript is a nice language but it does have some wacky areas a beginner would not be expecting. Hopefully, this little lesson in immutability will have made you understood that area of "science". Now don't be annoying and give me a reaction. :D Just joking. But seriously, do leave a comment with your thoughts.&lt;/p&gt;

&lt;p&gt;Thanks for reading,&lt;br&gt;
thecodrr&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;P.S. Here is my latest project in case you are interested:&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/thecodrr"&gt;
        thecodrr
      &lt;/a&gt; / &lt;a href="https://github.com/thecodrr/fdir"&gt;
        fdir
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      ⚡ The fastest directory crawler &amp;amp; globbing library for NodeJS. Crawls 1m files in &amp;lt; 1s
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/thecodrr/fdir/raw/master/assets/fdir.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_ENzsgHc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/thecodrr/fdir/raw/master/assets/fdir.gif" width="75%"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;h1&gt;
The Fastest Directory Crawler &amp;amp; Globber for NodeJS&lt;/h1&gt;
&lt;p&gt;
  &lt;a href="https://www.npmjs.com/package/fdir" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/d5d650d2c29186d3e71f0dd7a39b9a23dd6ff7652fac00a16fe8c3935b9af2e1/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://www.npmjs.com/package/fdir" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/c6171a944893b44b385a98811d98e0da9a6e4ea11e2512707c6683d215c4b6b6/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64742f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://codeclimate.com/github/thecodrr/fdir/maintainability" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/2430092f400cbe8d54418e8df60e02d125700a13014c07323a0953113134d2b9/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636c696d6174652f6d61696e7461696e6162696c6974792d70657263656e746167652f746865636f6472722f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://coveralls.io/github/thecodrr/fdir?branch=master" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/08d6a6f56bc0bbd13d8bd4b5ce080466685406f24d4badd81d75d7355ee3038f/68747470733a2f2f696d672e736869656c64732e696f2f636f766572616c6c732f6769746875622f746865636f6472722f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://www.npmjs.com/package/fdir" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/5d376c7c85e0555f2f2a9ea11097e90db20306fd0d2ae0dbb73cacccbed2d68f/68747470733a2f2f696d672e736869656c64732e696f2f62756e646c6570686f6269612f6d696e7a69702f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://www.producthunt.com/posts/fdir-every-millisecond-matters" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/f974db4cef4d4dcf3baf85d1d90569b157bf81b3a0bb43e5a0092ea6fc1632eb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f50726f6475637448756e742d5570766f74652d7265643f7374796c653d666f722d7468652d6261646765266c6f676f3d70726f647563742d68756e74"&gt;&lt;/a&gt;
  &lt;a href="https://dev.to/thecodrr/how-i-wrote-the-fastest-directory-crawler-ever-3p9c" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/bd59e87b2a135efa145088f336c1424dc5fbf8f98a13fe5d5fbdf38d5a3ed704/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6465762e746f2d52656164253230426c6f672d626c61636b3f7374796c653d666f722d7468652d6261646765266c6f676f3d6465762e746f"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/thecodrr/fdir./LICENSE"&gt;&lt;img src="https://camo.githubusercontent.com/55d32752e28c702b0c93ff3c0202d39aca8c46a93bbbf5c7d34a72a2effcf4d2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f746865636f6472722f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;⚡ &lt;strong&gt;The Fastest:&lt;/strong&gt; Nothing similar (in the NodeJS world) beats &lt;code&gt;fdir&lt;/code&gt; in speed. It can easily crawl a directory containing &lt;strong&gt;1 million files in &amp;lt; 1 second.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;💡 &lt;strong&gt;Stupidly Easy:&lt;/strong&gt; &lt;code&gt;fdir&lt;/code&gt; uses expressive Builder pattern to build the crawler increasing code readability.&lt;/p&gt;
&lt;p&gt;🤖 &lt;strong&gt;Zero Dependencies*:&lt;/strong&gt; &lt;code&gt;fdir&lt;/code&gt; only uses NodeJS &lt;code&gt;fs&lt;/code&gt; &amp;amp; &lt;code&gt;path&lt;/code&gt; modules.&lt;/p&gt;
&lt;p&gt;🕺 &lt;strong&gt;Astonishingly Small:&lt;/strong&gt; &amp;lt; 2KB in size gzipped &amp;amp; minified.&lt;/p&gt;
&lt;p&gt;🔥 &lt;strong&gt;All Node Versions Supported:&lt;/strong&gt; Unlike other similar libraries that have dropped support for Node versions &amp;lt; 10, &lt;code&gt;fdir&lt;/code&gt; supports all versions &amp;gt;= 6.&lt;/p&gt;
&lt;p&gt;🖮 &lt;strong&gt;Hackable:&lt;/strong&gt; Extending &lt;code&gt;fdir&lt;/code&gt; is extremely simple now that the new Builder API is here. Feel free to experiment around.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;* &lt;code&gt;picomatch&lt;/code&gt; must be installed manually by the user to support globbing.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
Support&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Do you like this project? &lt;strong&gt;&lt;a href="https://ko-fi.com/thecodrr" rel="nofollow"&gt;Support me by donating&lt;/a&gt;&lt;/strong&gt;, creating an issue, becoming a stargazer, or opening a pull request. Thanks.&lt;/p&gt;
&lt;/blockquote&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/thecodrr/fdir"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



</description>
      <category>javascript</category>
      <category>node</category>
      <category>typescript</category>
    </item>
    <item>
      <title>How I Wrote the Fastest Directory Crawler Ever</title>
      <dc:creator>Abdullah Atta</dc:creator>
      <pubDate>Mon, 16 Mar 2020 10:36:45 +0000</pubDate>
      <link>https://dev.to/thecodrr/how-i-wrote-the-fastest-directory-crawler-ever-3p9c</link>
      <guid>https://dev.to/thecodrr/how-i-wrote-the-fastest-directory-crawler-ever-3p9c</guid>
      <description>&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/thecodrr"&gt;
        thecodrr
      &lt;/a&gt; / &lt;a href="https://github.com/thecodrr/fdir"&gt;
        fdir
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      ⚡ The fastest directory crawler &amp;amp; globbing library for NodeJS. Crawls 1m files in &amp;lt; 1s
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/thecodrr/fdir/raw/master/assets/fdir.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_ENzsgHc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/thecodrr/fdir/raw/master/assets/fdir.gif" width="75%"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;h1&gt;
The Fastest Directory Crawler &amp;amp; Globber for NodeJS&lt;/h1&gt;

&lt;p&gt;
  &lt;a href="https://www.npmjs.com/package/fdir" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/d5d650d2c29186d3e71f0dd7a39b9a23dd6ff7652fac00a16fe8c3935b9af2e1/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://www.npmjs.com/package/fdir" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/c6171a944893b44b385a98811d98e0da9a6e4ea11e2512707c6683d215c4b6b6/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64742f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://codeclimate.com/github/thecodrr/fdir/maintainability" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/2430092f400cbe8d54418e8df60e02d125700a13014c07323a0953113134d2b9/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636c696d6174652f6d61696e7461696e6162696c6974792d70657263656e746167652f746865636f6472722f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://coveralls.io/github/thecodrr/fdir?branch=master" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/08d6a6f56bc0bbd13d8bd4b5ce080466685406f24d4badd81d75d7355ee3038f/68747470733a2f2f696d672e736869656c64732e696f2f636f766572616c6c732f6769746875622f746865636f6472722f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://www.npmjs.com/package/fdir" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/5d376c7c85e0555f2f2a9ea11097e90db20306fd0d2ae0dbb73cacccbed2d68f/68747470733a2f2f696d672e736869656c64732e696f2f62756e646c6570686f6269612f6d696e7a69702f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://www.producthunt.com/posts/fdir-every-millisecond-matters" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/f974db4cef4d4dcf3baf85d1d90569b157bf81b3a0bb43e5a0092ea6fc1632eb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f50726f6475637448756e742d5570766f74652d7265643f7374796c653d666f722d7468652d6261646765266c6f676f3d70726f647563742d68756e74"&gt;&lt;/a&gt;
  &lt;a href="https://dev.to/thecodrr/how-i-wrote-the-fastest-directory-crawler-ever-3p9c" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/bd59e87b2a135efa145088f336c1424dc5fbf8f98a13fe5d5fbdf38d5a3ed704/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6465762e746f2d52656164253230426c6f672d626c61636b3f7374796c653d666f722d7468652d6261646765266c6f676f3d6465762e746f"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/thecodrr/fdir./LICENSE"&gt;&lt;img src="https://camo.githubusercontent.com/55d32752e28c702b0c93ff3c0202d39aca8c46a93bbbf5c7d34a72a2effcf4d2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f746865636f6472722f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;⚡ &lt;strong&gt;The Fastest:&lt;/strong&gt; Nothing similar (in the NodeJS world) beats &lt;code&gt;fdir&lt;/code&gt; in speed. It can easily crawl a directory containing &lt;strong&gt;1 million files in &amp;lt; 1 second.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;💡 &lt;strong&gt;Stupidly Easy:&lt;/strong&gt; &lt;code&gt;fdir&lt;/code&gt; uses expressive Builder pattern to build the crawler increasing code readability.&lt;/p&gt;

&lt;p&gt;🤖 &lt;strong&gt;Zero Dependencies*:&lt;/strong&gt; &lt;code&gt;fdir&lt;/code&gt; only uses NodeJS &lt;code&gt;fs&lt;/code&gt; &amp;amp; &lt;code&gt;path&lt;/code&gt; modules.&lt;/p&gt;

&lt;p&gt;🕺 &lt;strong&gt;Astonishingly Small:&lt;/strong&gt; &amp;lt; 2KB in size gzipped &amp;amp; minified.&lt;/p&gt;

&lt;p&gt;🔥 &lt;strong&gt;All Node Versions Supported:&lt;/strong&gt; Unlike other similar libraries that have dropped support for Node versions &amp;lt; 10, &lt;code&gt;fdir&lt;/code&gt; supports all versions &amp;gt;= 6.&lt;/p&gt;

&lt;p&gt;🖮 &lt;strong&gt;Hackable:&lt;/strong&gt; Extending &lt;code&gt;fdir&lt;/code&gt; is extremely simple now that the new Builder API is here. Feel free to experiment around.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;* &lt;code&gt;picomatch&lt;/code&gt; must be installed manually by the user to support globbing.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
Support&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Do you like this project? &lt;strong&gt;&lt;a href="https://ko-fi.com/thecodrr" rel="nofollow"&gt;Support me by donating&lt;/a&gt;&lt;/strong&gt;, creating an issue, becoming a stargazer, or opening a pull request. Thanks.&lt;/p&gt;
&lt;/blockquote&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/thecodrr/fdir"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;If it's not fast, the work is not yet complete.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Said no one ever.&lt;/p&gt;

&lt;p&gt;Writing code fast and writing fast code are two very different things. One could even say they are opposites. If you are in the habit of writing code very fast there's a great chance that it will be slow. Writing fast code is not just about choosing the fastest language, the fastest platform, the fastest libraries etc. Anyone could do that. What makes code truly fast is the little things; the loops, the conditionals, the assignments, function calls etc.&lt;/p&gt;
&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I woke up Thursday morning, groggy, upset and very, very sleepy. My head was hurting. I had been coding all night and I had finally finished the first version of &lt;code&gt;fdir&lt;/code&gt;; the fastest directory crawler for NodeJS. I opened my laptop after a good breakfast, splendid tea and a nice walk; ran the benchmark again: &lt;code&gt;fdir&lt;/code&gt; was up against 13 other contenders. Always &lt;code&gt;fdir&lt;/code&gt; would come out on top in both synchronous and asynchronous crawling. But it was not ready yet...&lt;/p&gt;

&lt;h2&gt;
  
  
  The First Try
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;Writing fast code starts from the very first line.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The purpose of &lt;code&gt;fdir&lt;/code&gt; is simple; &lt;strong&gt;crawl as many directories as possible in as short a time as possible.&lt;/strong&gt; The first version of &lt;code&gt;fdir&lt;/code&gt; used recursion; it went something like this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This is an overly simplified version.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dirents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;withFileTypes&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="nx"&gt;dirents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dirent&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sep&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;dirent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dirent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isDirectory&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;bind&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;This could already beat almost everything out there. There's nothing special in it. Just some loops, recursion etc. etc. So what made it faster than everything?&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The first line.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;withFileTypes: true&lt;/code&gt; to be specific. This allowed me to skip the &lt;code&gt;fs.lstatSync&lt;/code&gt; syscall for &lt;strong&gt;each&lt;/strong&gt; item in a directory. Yup. You can imagine the speed boost.&lt;/p&gt;

&lt;p&gt;This line must be making you jump out of your underwear. Why didn't you use &lt;code&gt;path.join&lt;/code&gt;?!!&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;....&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sep&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;dirent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;....&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Because it's slow. It's much slower than just using &lt;code&gt;path.sep&lt;/code&gt;. I benchmarked it. It's about 50% slower.&lt;/p&gt;
&lt;h3&gt;
  
  
  v1 Benchmark:
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--h9dkcPmR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/thecodrr/fdir/1db624e8ec05512f2ed139c44d821d193e025edf/assets/power.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--h9dkcPmR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/thecodrr/fdir/1db624e8ec05512f2ed139c44d821d193e025edf/assets/power.png" alt="v1 Benchmark" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, only &lt;code&gt;rrdir.sync&lt;/code&gt; comes even close to &lt;code&gt;fdir&lt;/code&gt; and that's because it uses a similar approach.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Defenders Arrive
&lt;/h2&gt;

&lt;p&gt;Saturday evening, &lt;a href="https://github.com/thecodrr/fdir"&gt;I was posting about &lt;code&gt;fdir&lt;/code&gt; on Reddit&lt;/a&gt;. 2 hours later, the author of &lt;code&gt;rrdir&lt;/code&gt; opened a PR to update his library to improve async performance. I was heavily refactoring &lt;code&gt;fdir&lt;/code&gt; and adding support for Node version &amp;lt; 10 so his PR couldn't be merged. After an hour, though, I manually updated his library and ran the benchmarks again.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/thecodrr/fdir/pull/2"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        fix benchmark, bump rrdir, add rrdir.stream
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#2&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/silverwind"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--4r0sCd5a--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars1.githubusercontent.com/u/115237%3Fv%3D4" alt="silverwind avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/silverwind"&gt;silverwind&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/thecodrr/fdir/pull/2"&gt;&lt;time&gt;Mar 14, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;async rrdir shouldn't look so bad anymore with this&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/thecodrr/fdir/pull/2"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  Results:
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Async:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--t-WPlDPv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/thecodrr/fdir/bee095e0996bacf0fe97ffa7cd024b9fffa77ea8/assets/node13-async.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--t-WPlDPv--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/thecodrr/fdir/bee095e0996bacf0fe97ffa7cd024b9fffa77ea8/assets/node13-async.png" alt="Async benchmarks" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sync:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b1aLW4NI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/thecodrr/fdir/bee095e0996bacf0fe97ffa7cd024b9fffa77ea8/assets/node13-sync.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b1aLW4NI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/thecodrr/fdir/bee095e0996bacf0fe97ffa7cd024b9fffa77ea8/assets/node13-sync.png" alt="Async benchmarks" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Two hours after that, the author of &lt;code&gt;fs-recursive&lt;/code&gt; opened a PR to include his library in the benchmark. The title of the PR was: "I am fastest now". And it was. By quite the margin (50%). Of course I merged it.&lt;/p&gt;


&lt;div class="ltag_github-liquid-tag"&gt;
  &lt;h1&gt;
    &lt;a href="https://github.com/thecodrr/fdir/pull/3"&gt;
      &lt;img class="github-logo" alt="GitHub logo" src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg"&gt;
      &lt;span class="issue-title"&gt;
        Now I'm the fastest
      &lt;/span&gt;
      &lt;span class="issue-number"&gt;#3&lt;/span&gt;
    &lt;/a&gt;
  &lt;/h1&gt;
  &lt;div class="github-thread"&gt;
    &lt;div class="timeline-comment-header"&gt;
      &lt;a href="https://github.com/simov"&gt;
        &lt;img class="github-liquid-tag-img" src="https://res.cloudinary.com/practicaldev/image/fetch/s--d-NXuRrM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://avatars0.githubusercontent.com/u/1694112%3Fv%3D4" alt="simov avatar"&gt;
      &lt;/a&gt;
      &lt;div class="timeline-comment-header-text"&gt;
        &lt;strong&gt;
          &lt;a href="https://github.com/simov"&gt;simov&lt;/a&gt;
        &lt;/strong&gt; posted on &lt;a href="https://github.com/thecodrr/fdir/pull/3"&gt;&lt;time&gt;Mar 14, 2020&lt;/time&gt;&lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
    &lt;div class="ltag-github-body"&gt;
      &lt;p&gt;Thanks for the benchmark 👍&lt;/p&gt;

    &lt;/div&gt;
    &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/thecodrr/fdir/pull/3"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  The Rewrite
&lt;/h2&gt;

&lt;p&gt;And of course, I couldn't let &lt;code&gt;fs-recursive&lt;/code&gt; take the first place. I had spent "one whole night" writing the fastest crawler. I couldn't back down now. So I rewrote the whole algorithm. From top to bottom. It removed recursion (from &lt;code&gt;fdir.sync&lt;/code&gt;), stopped array recreation, only used a single Promise per &lt;code&gt;fdir.async&lt;/code&gt; call etc. etc. The code now looked like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dirs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dirents&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readdirSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;readdirOpts&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;dirents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dirent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;fullPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sep&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;dirent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dirent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isDirectory&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
        &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The code is pretty self-explanatory; we keep adding directories to the &lt;code&gt;dirs&lt;/code&gt; array so the loop never ends until there are no more directories. But &lt;code&gt;fdir.sync&lt;/code&gt; was already the first so I didn't really &lt;em&gt;need&lt;/em&gt; to optimize it further but I couldn't resist. Removing the multiple array initialisation, recursion gave a good speed boost and overall made the code quite clean (imo). &lt;/p&gt;

&lt;p&gt;The real challenge was optimizing the async version. As you all know, looping with asynchronous/callback functions is quite a PITA. So after everything this came into being:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;paths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dirs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;readCount&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;currentDepth&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;maxDepth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// cache the total directories before starting the walk&lt;/span&gt;
      &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(;&lt;/span&gt; &lt;span class="nx"&gt;cursor&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;dir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
        &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;readdirOpts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;dirents&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;dirents&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dirent&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;fullPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;dir&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;sep&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;dirent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dirent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isDirectory&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fullPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;});&lt;/span&gt;
          &lt;span class="c1"&gt;// check if we have walked all the directories we had&lt;/span&gt;
          &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;readCount&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;total&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// check if we got any new ones&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dirs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="nx"&gt;cursor&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
              &lt;span class="nx"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// walk again if we have new directories.&lt;/span&gt;
              &lt;span class="nx"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
          &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;walk&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The concept is quite similar to &lt;code&gt;fdir.sync&lt;/code&gt; but we retained recursion (although a new version of it). I couldn't find a way to reliably remove recursion. &lt;/p&gt;
&lt;h3&gt;
  
  
  The Results
&lt;/h3&gt;

&lt;p&gt;And, &lt;code&gt;fdir&lt;/code&gt; was back on top.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Async:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gI4O21Zj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/thecodrr/fdir/7b5cbcc97ee573bfc27ad01af5282c07cd4ce236/assets/node13-async.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gI4O21Zj--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/thecodrr/fdir/7b5cbcc97ee573bfc27ad01af5282c07cd4ce236/assets/node13-async.png" alt="Async Benchmark" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sync:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--506bT7GQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/thecodrr/fdir/7b5cbcc97ee573bfc27ad01af5282c07cd4ce236/assets/node13-sync.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--506bT7GQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://raw.githubusercontent.com/thecodrr/fdir/7b5cbcc97ee573bfc27ad01af5282c07cd4ce236/assets/node13-sync.png" alt="Sync Benchmark" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  The Takeaway
&lt;/h2&gt;

&lt;p&gt;The moment you have all been waiting for. The takeaways. What I learned. What I didn't. Etc. etc. However, I don't have "don't use X but Y" kind of lessons for you. I am sorry. The reason is, performance is dependent upon use-case. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Don't write code fast. You will have to rewrite it again and again. And if it's a large codebase, it will very soon become a PITA. So write it carefully, take all the precautions, do all the optimizations.&lt;/li&gt;
&lt;li&gt;A single millisecond matters. Oftentimes, we do not add an optimization just because it adds only a millisecond. But "drop by drop a river is born" right?&lt;/li&gt;
&lt;li&gt;NodeJS is very fast, you just have to write honest code. Don't make it complex just for the hell of it. Keep it simple, keep it fast.&lt;/li&gt;
&lt;li&gt;Benchmark. Benchmark. Benchmark. JavaScript has a lot of ways of doing one thing, multiple loops, iterators etc. You won't know what's fastest until you benchmark. I ran benchmarks for each line of my code that could have an alternative. Remember, every millisecond matters.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But I am gonna give a few "use X not Y" lessons anyway.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use as few conditionals as possible. Each branch adds an overhead and although the engine optimizes it, you have to be careful.&lt;/li&gt;
&lt;li&gt;Prepare for errors beforehand. Try-catch is expensive. Be careful.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;for&lt;/code&gt;, &lt;code&gt;forEach&lt;/code&gt; and &lt;code&gt;array.reduce&lt;/code&gt; are all very fast. Use whichever works for you. Actually, use them all and see which one makes your code faster.&lt;/li&gt;
&lt;li&gt;Research the API before using it. More often than note, there's something in the API that will reduce unnecessary calls, bootstrapping, error-checks etc. Like &lt;code&gt;withFileTypes: true&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;string&lt;/code&gt; methods as less as possible. Actually, use &lt;code&gt;strings&lt;/code&gt; as less as possible. Pushing a &lt;code&gt;string&lt;/code&gt; into an array is much slower than pushing an &lt;code&gt;int&lt;/code&gt;. (I didn't get to apply this).&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  So What Happens Now?
&lt;/h2&gt;

&lt;p&gt;Well, I will keep benchmarking and finding ways to make it faster. I will try using WebAssembly, Workers etc etc. Innovation, my friend, innovation. Currently, &lt;strong&gt;fdir can crawl about 1 million files in ~900ms&lt;/strong&gt; but I want to reduce it down to 500ms. The current code is as optimized as it can get. So let's see what I try.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/thecodrr"&gt;
        thecodrr
      &lt;/a&gt; / &lt;a href="https://github.com/thecodrr/fdir"&gt;
        fdir
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      ⚡ The fastest directory crawler &amp;amp; globbing library for NodeJS. Crawls 1m files in &amp;lt; 1s
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
&lt;a rel="noopener noreferrer" href="https://github.com/thecodrr/fdir/raw/master/assets/fdir.gif"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_ENzsgHc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://github.com/thecodrr/fdir/raw/master/assets/fdir.gif" width="75%"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;h1&gt;
The Fastest Directory Crawler &amp;amp; Globber for NodeJS&lt;/h1&gt;
&lt;p&gt;
  &lt;a href="https://www.npmjs.com/package/fdir" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/d5d650d2c29186d3e71f0dd7a39b9a23dd6ff7652fac00a16fe8c3935b9af2e1/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://www.npmjs.com/package/fdir" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/c6171a944893b44b385a98811d98e0da9a6e4ea11e2512707c6683d215c4b6b6/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f64742f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://codeclimate.com/github/thecodrr/fdir/maintainability" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/2430092f400cbe8d54418e8df60e02d125700a13014c07323a0953113134d2b9/68747470733a2f2f696d672e736869656c64732e696f2f636f6465636c696d6174652f6d61696e7461696e6162696c6974792d70657263656e746167652f746865636f6472722f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://coveralls.io/github/thecodrr/fdir?branch=master" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/08d6a6f56bc0bbd13d8bd4b5ce080466685406f24d4badd81d75d7355ee3038f/68747470733a2f2f696d672e736869656c64732e696f2f636f766572616c6c732f6769746875622f746865636f6472722f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://www.npmjs.com/package/fdir" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/5d376c7c85e0555f2f2a9ea11097e90db20306fd0d2ae0dbb73cacccbed2d68f/68747470733a2f2f696d672e736869656c64732e696f2f62756e646c6570686f6269612f6d696e7a69702f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
  &lt;a href="https://www.producthunt.com/posts/fdir-every-millisecond-matters" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/f974db4cef4d4dcf3baf85d1d90569b157bf81b3a0bb43e5a0092ea6fc1632eb/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f50726f6475637448756e742d5570766f74652d7265643f7374796c653d666f722d7468652d6261646765266c6f676f3d70726f647563742d68756e74"&gt;&lt;/a&gt;
  &lt;a href="https://dev.to/thecodrr/how-i-wrote-the-fastest-directory-crawler-ever-3p9c" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/bd59e87b2a135efa145088f336c1424dc5fbf8f98a13fe5d5fbdf38d5a3ed704/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6465762e746f2d52656164253230426c6f672d626c61636b3f7374796c653d666f722d7468652d6261646765266c6f676f3d6465762e746f"&gt;&lt;/a&gt;
  &lt;a href="https://github.com/thecodrr/fdir./LICENSE"&gt;&lt;img src="https://camo.githubusercontent.com/55d32752e28c702b0c93ff3c0202d39aca8c46a93bbbf5c7d34a72a2effcf4d2/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f746865636f6472722f666469723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;⚡ &lt;strong&gt;The Fastest:&lt;/strong&gt; Nothing similar (in the NodeJS world) beats &lt;code&gt;fdir&lt;/code&gt; in speed. It can easily crawl a directory containing &lt;strong&gt;1 million files in &amp;lt; 1 second.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;💡 &lt;strong&gt;Stupidly Easy:&lt;/strong&gt; &lt;code&gt;fdir&lt;/code&gt; uses expressive Builder pattern to build the crawler increasing code readability.&lt;/p&gt;
&lt;p&gt;🤖 &lt;strong&gt;Zero Dependencies*:&lt;/strong&gt; &lt;code&gt;fdir&lt;/code&gt; only uses NodeJS &lt;code&gt;fs&lt;/code&gt; &amp;amp; &lt;code&gt;path&lt;/code&gt; modules.&lt;/p&gt;
&lt;p&gt;🕺 &lt;strong&gt;Astonishingly Small:&lt;/strong&gt; &amp;lt; 2KB in size gzipped &amp;amp; minified.&lt;/p&gt;
&lt;p&gt;🔥 &lt;strong&gt;All Node Versions Supported:&lt;/strong&gt; Unlike other similar libraries that have dropped support for Node versions &amp;lt; 10, &lt;code&gt;fdir&lt;/code&gt; supports all versions &amp;gt;= 6.&lt;/p&gt;
&lt;p&gt;🖮 &lt;strong&gt;Hackable:&lt;/strong&gt; Extending &lt;code&gt;fdir&lt;/code&gt; is extremely simple now that the new Builder API is here. Feel free to experiment around.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;* &lt;code&gt;picomatch&lt;/code&gt; must be installed manually by the user to support globbing.&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
Support&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Do you like this project? &lt;strong&gt;&lt;a href="https://ko-fi.com/thecodrr" rel="nofollow"&gt;Support me by donating&lt;/a&gt;&lt;/strong&gt;, creating an issue, becoming a stargazer, or opening a pull request. Thanks.&lt;/p&gt;
&lt;/blockquote&gt;…&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/thecodrr/fdir"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;&lt;a href="https://www.producthunt.com/posts/fdir-every-millisecond-matters"&gt;&lt;strong&gt;Support fdir on ProductHunt&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Thanks for reading,&lt;br&gt;
thecodrr&lt;/p&gt;

</description>
      <category>showdev</category>
      <category>javascript</category>
      <category>node</category>
      <category>functional</category>
    </item>
    <item>
      <title>The (so) Many Ways of Concatenating an Array</title>
      <dc:creator>Abdullah Atta</dc:creator>
      <pubDate>Fri, 13 Mar 2020 07:53:48 +0000</pubDate>
      <link>https://dev.to/thecodrr/the-so-many-ways-of-concatenating-an-array-2a26</link>
      <guid>https://dev.to/thecodrr/the-so-many-ways-of-concatenating-an-array-2a26</guid>
      <description>&lt;p&gt;The truth behind performance is benchmarks. JavaScript is the type of language in which there are many ways of doing just one simple thing. When you have many ways of doing just 1 thing, it gets complicated; you have to make a choice. And how do you know which way is the fastest? That is what makes JavaScript confusing and complicated.&lt;/p&gt;

&lt;p&gt;Have a look at this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;second_array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;How would you concatenate these 2 arrays? In JavaScript there are about 10 ways of concatenating (joining) 2 arrays. Which one would you choose?&lt;/p&gt;

&lt;h3&gt;
  
  
  Array.prototype.concat:
&lt;/h3&gt;

&lt;p&gt;This is the simplest possible way.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;concat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;second_array&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Array.prototype.push:
&lt;/h3&gt;

&lt;p&gt;Again relatively simple, although, a little verbose.&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;h3&gt;
  
  
  Array.prototype.reduce:
&lt;/h3&gt;

&lt;p&gt;Just a teeny-tiny bit more complex.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;second_array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;reduce&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;current&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;all&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For-each:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;second_array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For-of:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;item&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;second_array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For-in:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;second_array&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;second_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  For:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nx"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;second_array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;second_array&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Spread-Operator:
&lt;/h3&gt;

&lt;p&gt;A little bit more verbose but still understandable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;array&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;array&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;second_array&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Which way is your go-to when it comes to concatenation? Leave a comment below.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;You'd think that JavaScript engines and compilers would be intelligent enough for you to choose any of these ways and be equally fast. You'd be wrong. 100% of time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's Benchmark:
&lt;/h3&gt;

&lt;p&gt;After benchmarking all these methods of array concatenation, here are the results for Google Chrome:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Array.prototype.concat x 6,006,271 ops/sec ±1.51% (61 runs sampled)

Array.prototype.push x 15,125,549 ops/sec ±0.59% (62 runs sampled)

Array.prototype.reduce x 26,952,859 ops/sec ±0.59% (64 runs sampled)

For-each x 26,682,412 ops/sec ±0.46% (64 runs sampled)

For-of x 23,628,346 ops/sec ±0.83% (64 runs sampled)

For-in x 2,951,756 ops/sec ±0.52% (64 runs sampled)

For x 25,458,988 ops/sec ±0.56% (64 runs sampled)

The Spread-Operator x 15,266,695 ops/sec ±0.57% (65 runs sampled)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can go run and &lt;a href="https://www.measurethat.net/Benchmarks/Show/7609/1/the-many-ways-of-concatenating"&gt;see the results yourself here.&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Which should I choose?
&lt;/h3&gt;

&lt;p&gt;You should of course always choose the fastest. But oftentimes, the fastest on one browser is actually slower on the other. In my opinion, your go to method should be the &lt;code&gt;for-loop&lt;/code&gt; one. It is the best optimised on almost all the browsers. But if you are targetting NodeJS's V8, go with &lt;code&gt;Array.prototype.reduce&lt;/code&gt; or the &lt;code&gt;ForEach&lt;/code&gt; method. If great readability is your concern, I'd go with &lt;code&gt;Array.prototype.push&lt;/code&gt; or the spread operator.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why is X method faster than Y?
&lt;/h3&gt;

&lt;p&gt;I don't know very deeply about what happens under-the-hood in each method. Maybe someone with more knowledge can specify? : )&lt;/p&gt;

&lt;p&gt;Thanks for reading, hope you learned something.&lt;br&gt;
Have a great day!&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>node</category>
    </item>
  </channel>
</rss>
