<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Jonathan Creamer</title>
    <description>The latest articles on Forem by Jonathan Creamer (@jcreamer898).</description>
    <link>https://forem.com/jcreamer898</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%2F140904%2F7c9e0e7e-f031-4810-8b5f-2e3885107fda.jpeg</url>
      <title>Forem: Jonathan Creamer</title>
      <link>https://forem.com/jcreamer898</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jcreamer898"/>
    <language>en</language>
    <item>
      <title>The JavaScript Developer's Guide to Ubuntu on Windows 11 with WSL</title>
      <dc:creator>Jonathan Creamer</dc:creator>
      <pubDate>Fri, 05 Jan 2024 16:34:09 +0000</pubDate>
      <link>https://forem.com/jcreamer898/the-javascript-developers-guide-to-ubuntu-on-windows-11-with-wsl-ll8</link>
      <guid>https://forem.com/jcreamer898/the-javascript-developers-guide-to-ubuntu-on-windows-11-with-wsl-ll8</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1v55L86v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2024/01/6C7A1911-EDIT.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1v55L86v--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2024/01/6C7A1911-EDIT.jpg" alt="The JavaScript Developer's Guide to Ubuntu on Windows 11 with WSL" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is a bit of a re-hash of an &lt;a href="https://www.jonathancreamer.com/setting-up-wsl2-and-the-vscode-containers-plugin/"&gt;earlier post&lt;/a&gt; on setting up WSL in Windows. It is just so easy now, that I wanted to make a whole new post.&lt;/p&gt;

&lt;p&gt;It's seriously as easy as &lt;code&gt;wsl --install&lt;/code&gt; now!&lt;/p&gt;

&lt;p&gt;Seriously just check this out... 👇👇&lt;/p&gt;

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

</description>
      <category>wsl</category>
      <category>containers</category>
      <category>ide</category>
      <category>setup</category>
    </item>
    <item>
      <title>Learning how to Learn</title>
      <dc:creator>Jonathan Creamer</dc:creator>
      <pubDate>Fri, 19 May 2023 14:43:54 +0000</pubDate>
      <link>https://forem.com/jcreamer898/learning-how-to-learn-54j8</link>
      <guid>https://forem.com/jcreamer898/learning-how-to-learn-54j8</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--68dLm6Ua--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2023/05/6C7A2713.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--68dLm6Ua--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2023/05/6C7A2713.jpg" alt="Learning how to Learn" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As silly as it sounds, the ability to learn is not necessarily easy.&lt;/p&gt;

&lt;p&gt;We all as engineers put ourselves in a state where we put guilt on ourselves when we stop what we're doing, and learn something because it feels like that's not "work".&lt;/p&gt;

&lt;p&gt;💡&lt;/p&gt;

&lt;p&gt;"Be passionate and bold. Always keep learning. You stop doing useful things if you don’t learn" Satya Nadella Microsoft CEO&lt;/p&gt;

&lt;p&gt;The reality is, learning is everything, we should be perpetual learners in every aspect of work, and life. I'd even go so far as to say we're doing our company's a disservice by NOT taking time to learn!&lt;/p&gt;

&lt;p&gt;The big question then is, "how do I learn how to learn?!"&lt;/p&gt;

&lt;h2&gt;
  
  
  Create systems not goals
&lt;/h2&gt;

&lt;p&gt;I heard Cory House reference a book a few years ago in his keynote at Connect.tech called "How to Fail at Everything and Still Win Big" and one idea in that book says that instead of trying to create new goals such as "read x number of books" or "exercise more", we should create systems that enable us to make those goals a reality.&lt;/p&gt;

&lt;p&gt;We should approach learning that way! Rather than saying things like, "I want to learn a new language like Rust", or "I want to read 3 new books this year", we should create a system for ourselves that allows us to complete those goals.&lt;/p&gt;

&lt;p&gt;For example, use an app such as To Do, Todoist, Apple Reminders, and create yourself a morning checklist that covers a daily few things you want to do.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--duR2FwVa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2023/05/image.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--duR2FwVa--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2023/05/image.png" alt="Learning how to Learn" width="800" height="242"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to learn a new technology, block off time on your calendar daily or weekly in order to spend a bit of time reading a book about it. Take an hour every Friday to stop what you're doing, read a book, watch some content, etc.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learning Resources
&lt;/h2&gt;

&lt;p&gt;There are so many resources out there for developers to learn from, but here are a few of my favorite&lt;/p&gt;

&lt;h3&gt;
  
  
  Start a blog
&lt;/h3&gt;

&lt;p&gt;Wait wait? A blog? YES! One of the absolute BEST ways to learn is simply to write down things down. I love the quote, "&lt;em&gt;Writing is thinking".&lt;/em&gt; It's so true, often times taking the time to write down something that you've been learning and thinking about will offer clarity and understanding that you didn't expect. It doesn't have to be a complicated blog setup, it's 2023, use Wordpress, Github Pages, Azure Static Webapps, Notepad, just something to get your mind working.&lt;/p&gt;

&lt;h3&gt;
  
  
  Social Media
&lt;/h3&gt;

&lt;p&gt;This one sometimes makes people giggle, but the reality of it is, Twitter is still a massive source of great free content. Social media, in spite of its obvious pitfalls, is still a great place to go to consume new ideas, and occasionally when the mood strikes, put your own new learnings and ideas out there.&lt;/p&gt;

&lt;p&gt;Use Tweetdeck to create a List of top news sites that cover your interests, and add a column for it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6t2CKqmV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2023/05/image-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6t2CKqmV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2023/05/image-1.png" alt="Learning how to Learn" width="605" height="651"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--14i5yB9U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2023/05/image-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--14i5yB9U--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2023/05/image-2.png" alt="Learning how to Learn" width="416" height="698"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can even follow certain hashtags if you want, and join them with an &lt;code&gt;OR&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tJSYGxOg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2023/05/image-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tJSYGxOg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2023/05/image-3.png" alt="Learning how to Learn" width="436" height="545"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Online courses
&lt;/h3&gt;

&lt;p&gt;Occasionally a company you work for will offer a free education site like &lt;a href="//pluralsight.com"&gt;Pluralsight&lt;/a&gt;, &lt;a href="https://frontendmasters.com/?ref=jonathancreamer.com"&gt;Frontend Masters&lt;/a&gt;, &lt;a href="https://egghead.io/?ref=jonathancreamer.com"&gt;Egghead.io&lt;/a&gt;, &lt;a href="https://www.udemy.com/?ref=jonathancreamer.com"&gt;Udemy&lt;/a&gt;, &lt;a href="https://www.linkedin.com/learning/?ref=jonathancreamer.com"&gt;LinkedIn Learning&lt;/a&gt; and more, but even if they don't offer it to you as a free resource, consider joining one of them anyways! Most of them only cost roughly $30/month, and  are full of great content. Here is where you could leverage that hour block of time you schedule on Friday's to go watch some courses on that new language, or learn more about advanced React Hooks usage. Whatever that thing is, take the time to go watch some content on it.&lt;/p&gt;

&lt;h3&gt;
  
  
  News Sites and Newsletters
&lt;/h3&gt;

&lt;p&gt;&lt;a href="http://dev.to/?ref=jonathancreamer.com"&gt;Dev.to&lt;/a&gt; is one of the best ways to get a stream of content, and also turn around, and write about your own thoughts and ideas.&lt;/p&gt;

&lt;p&gt;There are lots of great online news sites like Reddit's &lt;a href="https://reddit.com/r/javascript?ref=jonathancreamer.com"&gt;r/javascript&lt;/a&gt;, or &lt;a href="https://www.reddit.com/r/rust/?ref=jonathancreamer.com"&gt;r/rust&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If that's all too overwhelming, just go subscribe to one of the dozens of great newsletters out there that aggregate all that data into a weekly digest.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://javascriptweekly.com/?ref=jonathancreamer.com"&gt;JavaScript Weekly: The JavaScript Email Newsletter&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://react.statuscode.com/?ref=jonathancreamer.com"&gt;React Status&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://nodeweekly.com/?ref=jonathancreamer.com"&gt;Node Weekly&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://esnextnews.com/?ref=jonathancreamer.com"&gt;ES.next News: the latest in JavaScript and cross-platform tools&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Go forth and learn
&lt;/h2&gt;

&lt;p&gt;Learning is key to growth. Make sure to create the systems you need to foster learning as a part of your day to day life. You will better yourself, better your company, and better those around you.&lt;/p&gt;

</description>
      <category>learning</category>
      <category>javascript</category>
      <category>technology</category>
      <category>developer</category>
    </item>
    <item>
      <title>Tip for writing nodejs scripts using only built-in modules and async</title>
      <dc:creator>Jonathan Creamer</dc:creator>
      <pubDate>Tue, 03 Jan 2023 21:42:35 +0000</pubDate>
      <link>https://forem.com/jcreamer898/tip-for-writing-nodejs-scripts-using-only-built-in-modules-and-async-4ln0</link>
      <guid>https://forem.com/jcreamer898/tip-for-writing-nodejs-scripts-using-only-built-in-modules-and-async-4ln0</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhelq05dl3ycsj34f6b4.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkhelq05dl3ycsj34f6b4.JPG" alt="Tip for writing nodejs scripts using only built-in modules and async" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the last few years, I've spent a huge majority of my time writing scripts in nodejs as my default scripting language. I've dabbled with bash a bit too, but it's still so weird, and hard to test, and I'm such a Typescript fan that I generally prefer to go the typescript route as often as possible.&lt;/p&gt;

&lt;p&gt;Below is a list of tips to make writing nodejs scripts fun, fast, and easy.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use ES Modules
&lt;/h2&gt;

&lt;p&gt;Yes! You can do it now! However, &lt;a href="https://nodejs.org/docs/latest-v16.x/api/packages.html#determining-module-system" rel="noopener noreferrer"&gt;thar be dragons&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In general tho, if you want to use ES modules in node, you can...&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Name your file with &lt;code&gt;.mjs&lt;/code&gt; on the end of it&lt;/li&gt;
&lt;li&gt;Use a &lt;code&gt;.js&lt;/code&gt; file in a place where the closest &lt;code&gt;package.json&lt;/code&gt; has &lt;code&gt;"type": "module"&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;node --eval&lt;/code&gt; and pass &lt;code&gt;--input-type=module&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Similar rules apply to keeping a file use &lt;code&gt;commonjs&lt;/code&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Name your file with &lt;code&gt;.cjs&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use a &lt;code&gt;.js&lt;/code&gt; file in a place where the closest &lt;code&gt;package.json&lt;/code&gt; has &lt;code&gt;"type": "commonjs"&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;node --eval&lt;/code&gt; and pass &lt;code&gt;--input-type=commonjs&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;There are a couple of provisos&lt;/strong&gt; , a, &lt;strong&gt;a couple&lt;/strong&gt; of &lt;strong&gt;quid&lt;/strong&gt; pro quos&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh5u60v56mc7zb7hj2v19.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh5u60v56mc7zb7hj2v19.gif" alt="Tip for writing nodejs scripts using only built-in modules and async" width="498" height="263"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you switch to using ES Modules in node, you have to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always include the extension in your imports...
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./bar.js&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;ul&gt;
&lt;li&gt;You have to use &lt;code&gt;import()&lt;/code&gt; instead of &lt;code&gt;require&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;This doesn't work... &lt;code&gt;__dirname&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But, this does...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:path&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fileURLToPath&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:url&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;__filename&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;fileURLToPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;__dirname&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__filename&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;p&gt;You might also run into issues with &lt;em&gt;some&lt;/em&gt; of the &lt;code&gt;node_modules&lt;/code&gt; that you import, so, just be careful. But, if you're generally sticking to native node modules and utilities anyways, then you should be pretty good to go.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use top level await
&lt;/h2&gt;

&lt;p&gt;This became available in 14.8. For the longest time, I'd always write a wrapper every time I got ready to write a node.js script like...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// await some stuff in here&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&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="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I did that so often that I wrote VSCode snippets for it. Heh.&lt;/p&gt;

&lt;p&gt;But, cool thing is, you can just &lt;code&gt;await&lt;/code&gt; anywhere in a JS file now.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;NOTE: you can only do this in a "module" context, i.e. see "Use ES Modules" above&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:fs/promises&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;pkg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./package.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;pkg&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use the new-ish promise based APIs along with the node prefix
&lt;/h2&gt;

&lt;p&gt;As of node v14.18 and v16, you can now require &lt;em&gt;native&lt;/em&gt; node modules, i.e. those things like &lt;code&gt;path&lt;/code&gt;, &lt;code&gt;fs&lt;/code&gt;, etc which are built into node, by using the &lt;code&gt;node:&lt;/code&gt; protocol in the import or require statement. This will prevent script writers from accidentally importing 3rd party versions of utilities.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:fs/promises&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;stream&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:stream/promises&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;dns&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:dns/promises&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;timers&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:timers/promises&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;Also, for everything else that takes a standard node &lt;code&gt;(err, results) =&amp;gt; {}&lt;/code&gt; callback, you can always fall back on the &lt;code&gt;promisify&lt;/code&gt; method.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:fs/promises&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;exec&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;_exec&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:child_process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;promisify&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:util&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_exec&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;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;git status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

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

&lt;/div&gt;



&lt;h2&gt;
  
  
  Use child_process effectively
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;child_process&lt;/code&gt; module is one of the most useful modules in a script writer's backpack. You can run any arbitrary thing on the machine using its &lt;code&gt;spawn&lt;/code&gt; or &lt;code&gt;exec&lt;/code&gt; methods. However, knowing when, and how to use either of them, is essential.&lt;/p&gt;

&lt;p&gt;The most fundamental difference between &lt;code&gt;spawn&lt;/code&gt; and &lt;code&gt;exec&lt;/code&gt; is...&lt;/p&gt;

&lt;p&gt;&lt;code&gt;spawn&lt;/code&gt; creates and returns a child process that you can interact with easily via streams&lt;/p&gt;

&lt;p&gt;&lt;code&gt;exec&lt;/code&gt; creates a runs a subprocess returning the output and error streams with a max of 200kb&lt;/p&gt;

&lt;p&gt;Therefore, most of the time &lt;code&gt;exec&lt;/code&gt; will do what you need, but if you need some sort of interactivity or have a bunch of output, then you can use &lt;code&gt;spawn&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One of the previous examples above used &lt;code&gt;exec&lt;/code&gt; to call &lt;code&gt;git status&lt;/code&gt;. Another example could be an abstraction over some sort of &lt;code&gt;unix&lt;/code&gt; method like &lt;code&gt;find&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="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:fs/promises&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;exec&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nx"&gt;_exec&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:child_process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;promisify&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:util&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;exec&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;promisify&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;_exec&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[,,&lt;/span&gt; &lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argv&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;out&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`find &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;directory&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; -type f -name &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;filename&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; `&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;out&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// run with...&lt;/span&gt;
&lt;span class="c1"&gt;// node ./script.mjs filename ./directory&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's an example of using &lt;code&gt;spawn&lt;/code&gt; to do something.&lt;/p&gt;

&lt;p&gt;In this case, we're going to spawn an &lt;code&gt;npm install&lt;/code&gt; in a different package in our repo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;spawn&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:child_process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;install&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Promise&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;reject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;proc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;spawn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;npm&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;install&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;stdio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inherit&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pipe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;pipe&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
      &lt;span class="na"&gt;env&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;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&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;proc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stdout&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;npm WARN&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Do something&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="nx"&gt;proc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;stderr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;data&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`stderr: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&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;proc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;on&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;close&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&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="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;reject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;install&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Something went wrong with the install.&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exit&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First thing to note here is that we're going create a function and use the &lt;code&gt;Promise&lt;/code&gt; constructor in the &lt;code&gt;return&lt;/code&gt;. That way we can &lt;code&gt;await&lt;/code&gt; it at the top level.&lt;/p&gt;

&lt;p&gt;Let's take a look at the options we're passing to &lt;code&gt;spawn&lt;/code&gt;. (You can see the entire API of spawn &lt;a href="https://nodejs.org/api/child_process.html#:~:text=The%20child_process.spawn%20%28%29%20method%20spawns%20the%20child%20process,the%20spawned%20process%20either%20exits%20or%20is%20terminated." rel="noopener noreferrer"&gt;here&lt;/a&gt;) The first is the top level command, in this case &lt;code&gt;npm&lt;/code&gt;. The second option is an array of the arguments we want to pass to &lt;code&gt;npm&lt;/code&gt; in this case just &lt;code&gt;install&lt;/code&gt;. But, if we wanted pass multiple things to &lt;code&gt;npm&lt;/code&gt;, we'd need to add them each as elements to that array such as &lt;code&gt;['install', '--save-dev', '--legacy-peer-deps']&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The third argument is the &lt;code&gt;options&lt;/code&gt; object. By default, when you spawn a process, the &lt;code&gt;stdio&lt;/code&gt; option is set to &lt;code&gt;pipe&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;pipe&lt;/code&gt; option means that the &lt;code&gt;proc&lt;/code&gt; which is returned from &lt;code&gt;spawn&lt;/code&gt; will have &lt;code&gt;proc.stdout&lt;/code&gt;, &lt;code&gt;proc.stdin&lt;/code&gt;, and &lt;code&gt;proc.stderr&lt;/code&gt; on it. These are &lt;code&gt;streams&lt;/code&gt; so that you can use methods like &lt;code&gt;on&lt;/code&gt; and &lt;code&gt;one&lt;/code&gt; to respond to events such as &lt;code&gt;data&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;stdin&lt;/code&gt; argument can either take &lt;code&gt;pipe&lt;/code&gt;, &lt;code&gt;inherit&lt;/code&gt;, or an array corresponding to which parts of the process you want to control...&lt;/p&gt;

&lt;p&gt;If you don't &lt;em&gt;need&lt;/em&gt; to use &lt;code&gt;stdin&lt;/code&gt; or &lt;code&gt;stderr&lt;/code&gt; for example, you can switch from &lt;code&gt;pipe&lt;/code&gt; to &lt;code&gt;inherit&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;stdin: [
  'inherit' /* stdin */,
  'pipe' /* stdout */,
  'inherit' /* stderr */ 
],
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Passing &lt;code&gt;stdin&lt;/code&gt; like that 👆 would provide &lt;code&gt;proc.stdout&lt;/code&gt;  but not &lt;code&gt;proc.stdin&lt;/code&gt; or &lt;code&gt;proc.stderr&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Lastly, you can watch for the process you're spawning to close by using &lt;code&gt;proc.on('close', () =&amp;gt; {});&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;One more nice option is that you can control which working directory the process is spawned in via the &lt;code&gt;cwd&lt;/code&gt; option. This allows you to use either &lt;code&gt;process.cwd()&lt;/code&gt;, or set some other path where you actually want to spawn the process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Typescript for an even cooler script writing experience
&lt;/h2&gt;

&lt;p&gt;Generally I prefer to use Typescript when writing just about anything these days, including scripts. There's a couple of different ways when writing scripts like this which you can use to leverage Typescript for the extra security blanket of checks in your code.&lt;/p&gt;

&lt;p&gt;First of all, if you're going to be using Typescript and Node, make sure that you have the &lt;code&gt;@types/node&lt;/code&gt; package installed as a &lt;code&gt;"devDependency"&lt;/code&gt;. That will ensure that all the native modules have correct type information.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5he976l39m733inqeqw2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5he976l39m733inqeqw2.png" alt="Tip for writing nodejs scripts using only built-in modules and async" width="667" height="144"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Intellisense for parameters&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmy4u20kkrwp8pglsjdf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftmy4u20kkrwp8pglsjdf.png" alt="Tip for writing nodejs scripts using only built-in modules and async" width="476" height="329"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Intellisense for options&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;That in and of itself is super useful.&lt;/p&gt;

&lt;p&gt;What's really worth noting though is that, you don't HAVE to have your file end in a &lt;code&gt;.ts&lt;/code&gt; extension. You can add a couple of options to a &lt;code&gt;tsconfig.json&lt;/code&gt;. They are &lt;code&gt;"allowJs"&lt;/code&gt; and &lt;code&gt;"checkJs"&lt;/code&gt;. Set them both to true, and you're good to go.&lt;/p&gt;

&lt;p&gt;Typescript as of the &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-4-7" rel="noopener noreferrer"&gt;4.7 release&lt;/a&gt; now supports ES Modules too by reading the &lt;code&gt;"type": "module"&lt;/code&gt; that can be added to &lt;code&gt;package.json&lt;/code&gt; files. And you can also manually tell Typescript to use modules by setting the &lt;code&gt;"module"&lt;/code&gt; option to &lt;code&gt;node16&lt;/code&gt; or &lt;code&gt;nodenext&lt;/code&gt;. All that is documented &lt;a href="https://www.typescriptlang.org/docs/handbook/2/modules.html#es-module-syntax" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you want to use &lt;code&gt;.ts&lt;/code&gt; instead of using allowJs and checkJs, you'll probably also want to install something like &lt;code&gt;@babel/register&lt;/code&gt;, or &lt;code&gt;ts-node&lt;/code&gt;, maybe even &lt;a href="https://github.com/folke/esbuild-runner" rel="noopener noreferrer"&gt;esbuild-runner&lt;/a&gt;. I still personaly prefer the &lt;a href="https://www.jonathancreamer.com/running-programs-with-babel-node/" rel="noopener noreferrer"&gt;Babel route&lt;/a&gt;.&lt;/p&gt;

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

&lt;p&gt;In the world of Frontend and DevOps aka &lt;a href="https://www.jonathancreamer.com/announcing-div-ops/" rel="noopener noreferrer"&gt;DivOps&lt;/a&gt;, writing scripts is inevitable. Writing scripts in Javascript / Typescript allows you to use the JS skills you have as a Frontend dev to interact with the machine to do all kinds of automations, pipelines, etc. And bonus points because you can also write unit tests too. Go forth and write all your scripts in JavaScript!&lt;/p&gt;

</description>
      <category>node</category>
      <category>promises</category>
      <category>javascript</category>
      <category>esmodules</category>
    </item>
    <item>
      <title>Calling an API with authorization using native nodejs with zero external dependencies</title>
      <dc:creator>Jonathan Creamer</dc:creator>
      <pubDate>Fri, 19 Aug 2022 19:17:48 +0000</pubDate>
      <link>https://forem.com/jcreamer898/calling-an-api-with-authorization-using-native-nodejs-with-zero-external-dependencies-25p6</link>
      <guid>https://forem.com/jcreamer898/calling-an-api-with-authorization-using-native-nodejs-with-zero-external-dependencies-25p6</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hiGVRWvI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2022/08/IMG_4649.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hiGVRWvI--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://www.jonathancreamer.com/content/images/2022/08/IMG_4649.jpg" alt="Calling an API with authorization using native nodejs with zero external dependencies" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Fetching from an API is one of the most repeated tasks for anyone writing JavaScript backends with node.js. There are dozens of libraries for doing this including &lt;code&gt;node-fetch&lt;/code&gt;, &lt;code&gt;isomorphic-fetch&lt;/code&gt;, &lt;code&gt;axios&lt;/code&gt;, etc etc, however, there's actually a couple of native ways that are fairly simple to use and require no external dependencies at all.&lt;/p&gt;

&lt;p&gt;Let's talk about a few of them!&lt;/p&gt;

&lt;h2&gt;
  
  
  The 'https' way
&lt;/h2&gt;

&lt;p&gt;In a world prior to node 18, many people may or may not realize that it's actually not &lt;em&gt;that&lt;/em&gt; hard to simply use the built in node.js &lt;code&gt;https&lt;/code&gt; module to do a simple API request with ZERO external dependencies.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const https = require("node:https");

const request = (options) =&amp;gt; {
  return new Promise((resolve, reject) =&amp;gt; {
    const req = https.request(options, (res) =&amp;gt; {
      let data = "";

      res.on("data", (d) =&amp;gt; {
        data += d;
      });

      res.on("end", () =&amp;gt; {
        data = JSON.parse(data.toString().trim());

        if (res.statusCode === 200) {
          resolve(data);
        } else {
          reject(new Error(`Error code: ${res.statusCode}.`));
        }
      });

      res.on("error", (error) =&amp;gt; {
        reject(new Error(error));
      });
    });

    req.end();
  });
};

const auth = `Basic ${Buffer.from(`${user}:${password}`).toString("base64")}`;

request({
 hostname: "foobar.com",
  port: 443,
  path: "/api/users/1",
  method: "GET",
  headers: {
    Accept: "application/json",
    Authorization: auth,
  },
})
.then((data) =&amp;gt; {
  console.log(data);
})
.catch((error) =&amp;gt; {
  // Do something with the error
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here you can see we used the native via &lt;code&gt;require("node:http")&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You can optionally start by creating your own function that returns a promise, here above there's a &lt;code&gt;request&lt;/code&gt; function of our own.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;https.request&lt;/code&gt; function returns an instance of the &lt;code&gt;ClientRequest&lt;/code&gt; class. And takes options, and a callback function. The callback function contains a parameter for an instance the &lt;code&gt;IncomingMessage&lt;/code&gt; class, or basically, the response.  &lt;/p&gt;

&lt;p&gt;You can use the &lt;code&gt;res.on("data", callback)&lt;/code&gt; like you would when you're reading a stream. There's a few event handers you can listen to, build the full response data by just building up a big response string.&lt;/p&gt;

&lt;p&gt;Then in &lt;code&gt;res.on("end", callback)&lt;/code&gt; you can check the status code, and send back data as JSON or however you want to send back data to the calling function by calling &lt;code&gt;resolve&lt;/code&gt; and resolving the promise. If anything goes wrong such as the status not being 200, you can &lt;code&gt;reject&lt;/code&gt; with an error, or a string, just something to let the caller know what's going on.&lt;/p&gt;

&lt;p&gt;There's also an &lt;code&gt;res.on("error", callback)&lt;/code&gt; handler in case something else goes wrong in the response.&lt;/p&gt;

&lt;p&gt;Finally, you just call &lt;code&gt;req.end()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Now you have your own custom &lt;code&gt;request&lt;/code&gt; function to make API requests with!&lt;/p&gt;

&lt;p&gt;The last piece is just building up the correct &lt;code&gt;Authorization&lt;/code&gt; headers to send along with the &lt;code&gt;headers&lt;/code&gt; option. That's often just a base64 encoded string in the format of &lt;code&gt;username:password&lt;/code&gt; along with &lt;code&gt;Basic ${auth}&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;As seen above...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const auth = Basic ${Buffer.from(${user}:${password}).toString("base64")};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The 'fetch' way
&lt;/h2&gt;

&lt;p&gt;For a while now, the &lt;code&gt;fetch&lt;/code&gt; API has been available in most &lt;a href="https://caniuse.com/fetch"&gt;browsers&lt;/a&gt;. However, it wasn't until recently that you have access to the &lt;code&gt;fetch&lt;/code&gt; API in node. As of &lt;a href="https://github.com/nodejs/node/blob/main/doc/changelogs/CHANGELOG_V18.md#fetch-experimental"&gt;18.0.0&lt;/a&gt;, you are now able to simply use &lt;code&gt;fetch&lt;/code&gt; in basically the same way you would in the browser. In 17.5.0 you could use the &lt;code&gt;--experimental-fetch&lt;/code&gt; flag, but that will no longer be needed in 18+.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;fetch("https://foobar.com/api/users/1", {
  headers: new Headers({
     'Authorization': `Basic ${Buffer.from(`${user}:${password}`).toString("base64")}`, 
     'Content-Type': 'application/json'
   }), 
})
.then((resp) =&amp;gt; {
  if (response.status &amp;gt;= 200 &amp;amp;&amp;amp; response.status &amp;lt;= 299) {
      return response.json();
    } else {
      throw Error(response.statusText);
    }
})
.catch(() =&amp;gt; {
  return resp.text();
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, that was a lot simpler. That's thanks to the work of the folks who put together the new &lt;code&gt;undici&lt;/code&gt; &lt;a href="https://undici.nodejs.org/#/"&gt;library&lt;/a&gt; that powers fetch in node!&lt;/p&gt;

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

&lt;p&gt;tldr; if you're in node 18, use fetch, otherwise, use https.&lt;/p&gt;

&lt;p&gt;The key takeaway here is that you &lt;em&gt;probably&lt;/em&gt; don't need to add some big fetching library just to make a simple HTTP request in node. It's simple enough to make your own thing.&lt;/p&gt;

</description>
      <category>node</category>
      <category>fetch</category>
      <category>api</category>
      <category>native</category>
    </item>
    <item>
      <title>Running Typescript scripts in node using esbuild</title>
      <dc:creator>Jonathan Creamer</dc:creator>
      <pubDate>Mon, 11 Jul 2022 18:22:00 +0000</pubDate>
      <link>https://forem.com/jcreamer898/running-typescript-scripts-in-node-using-esbuild-368g</link>
      <guid>https://forem.com/jcreamer898/running-typescript-scripts-in-node-using-esbuild-368g</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2VRs9e8j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2022/07/IMG_7069.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2VRs9e8j--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2022/07/IMG_7069.jpg" alt="Running Typescript scripts in node using esbuild" width="880" height="1173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Typescript is hands down my favorite way to write Javascript these days, but sometimes when I just want to run a quick JS script to do something, I'll still reach for &lt;code&gt;node ./foo/script.js&lt;/code&gt;. I'll sometimes reach for &lt;code&gt;babel-node&lt;/code&gt;&lt;code&gt;, or&lt;/code&gt;&lt;a class="mentioned-user" href="https://dev.to/babel"&gt;@babel&lt;/a&gt;/register`, but that can be pretty difficult to configure sometimes, and has some perf issues.&lt;/p&gt;

&lt;p&gt;It does work though, and I have a post on it...&lt;/p&gt;

&lt;p&gt;[&lt;/p&gt;

&lt;p&gt;Running Typescript programs with babel-node aka how does babel register work&lt;/p&gt;

&lt;p&gt;Running Typescript programs on demand with babel-node basically uses babel register, but how does babel register work? This post will detail it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--D5ZO5Zo9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/size/w256h256/2021/03/jclogo-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--D5ZO5Zo9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/size/w256h256/2021/03/jclogo-1.png" alt="Running Typescript scripts in node using esbuild" width="256" height="256"&gt;&lt;/a&gt;Jonathan CreamerJonathan Creamer&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MSRZrwIu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/IMG_7214.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MSRZrwIu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/IMG_7214.JPG" alt="Running Typescript scripts in node using esbuild" width="880" height="1173"&gt;&lt;/a&gt;&lt;br&gt;
](&lt;a href="https://www.jonathancreamer.com/running-programs-with-babel-node/"&gt;https://www.jonathancreamer.com/running-programs-with-babel-node/&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;However, I recently discovered that ESBuild has a similar mechanism to babel-node called &lt;code&gt;esbuild-runner&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;[&lt;/p&gt;

&lt;p&gt;esbuild-runner&lt;/p&gt;

&lt;p&gt;Super-fast on-the-fly transpilation of modern JS, TypeScript and JSX using esbuild. Latest version: 2.2.1, last published: 10 months ago. Start using esbuild-runner in your project by running &lt;code&gt;npm i esbuild-runner&lt;/code&gt;. There are 13 other projects in the npm registry using esbuild-runner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TDN5Jvbc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://static.npmjs.com/1996fcfdf7ca81ea795f67f093d7f449.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TDN5Jvbc--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://static.npmjs.com/1996fcfdf7ca81ea795f67f093d7f449.png" alt="Running Typescript scripts in node using esbuild" width="230" height="230"&gt;&lt;/a&gt;npm&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--r7XxGAJ5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://static.npmjs.com/338e4905a2684ca96e08c7780fc68412.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--r7XxGAJ5--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://static.npmjs.com/338e4905a2684ca96e08c7780fc68412.png" alt="Running Typescript scripts in node using esbuild" width="880" height="462"&gt;&lt;/a&gt;&lt;br&gt;
](&lt;a href="https://www.npmjs.com/package/esbuild-runner"&gt;https://www.npmjs.com/package/esbuild-runner&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;It's SUPER easy to use as well.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;`&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;npm i esbuild esbuild-runner&lt;br&gt;
`&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Then, anytime you run a &lt;code&gt;.ts&lt;/code&gt; file, you do...&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;&lt;br&gt;
node -r esbuild-runner/register ./path/to/script.ts&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And it's stupid fast...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6l86u2Il--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2022/07/image-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6l86u2Il--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2022/07/image-1.png" alt="Running Typescript scripts in node using esbuild" width="835" height="414"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hope to employ &lt;code&gt;esbuild-runner&lt;/code&gt; in some more local developer tooling so developers don't have to pre-compile or build their tools.&lt;/p&gt;

</description>
      <category>esbuild</category>
      <category>tools</category>
      <category>typescript</category>
      <category>node</category>
    </item>
    <item>
      <title>Inside the pain of monorepos and hoisting</title>
      <dc:creator>Jonathan Creamer</dc:creator>
      <pubDate>Fri, 10 Dec 2021 23:01:51 +0000</pubDate>
      <link>https://forem.com/jcreamer898/inside-the-pain-of-monorepos-and-hoisting-4dj3</link>
      <guid>https://forem.com/jcreamer898/inside-the-pain-of-monorepos-and-hoisting-4dj3</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--gESD14sb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/12/cave.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--gESD14sb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/12/cave.JPG" alt="Inside the pain of monorepos and hoisting" width="880" height="660"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Working in a monorepo comes with a long list of pros, and a few cons. One of the most painful cons, when it comes to working in a specifically JavaScript based monorepo, is the pain that comes from hoisting.&lt;/p&gt;

&lt;h2&gt;
  
  
  What's this hoisting thing?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--eGbPbvBK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/12/image-5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--eGbPbvBK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/12/image-5.png" alt="Inside the pain of monorepos and hoisting" width="880" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we all know, node_modules is a deep dark place with lots and lots of stuff. That problem is even more massive in a large monorepo.&lt;/p&gt;

&lt;p&gt;Let's take a step back for a sec and take a look at what happens when you &lt;code&gt;require&lt;/code&gt; something.&lt;/p&gt;

&lt;h3&gt;
  
  
  node module resolution
&lt;/h3&gt;

&lt;p&gt;If you take a read through &lt;a href="https://nodejs.org/api/modules.html#all-together"&gt;the docs&lt;/a&gt;, you'll find this...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require(X) from module at path Y
1. If X is a core module,
   a. return the core module
   b. STOP
2. If X begins with '/'
   a. set Y to be the filesystem root
3. If X begins with './' or '/' or '../'
   a. LOAD_AS_FILE(Y + X)
   b. LOAD_AS_DIRECTORY(Y + X)
   c. THROW "not found"
4. If X begins with '#'
   a. LOAD_PACKAGE_IMPORTS(X, dirname(Y))
5. LOAD_PACKAGE_SELF(X, dirname(Y))
6. LOAD_NODE_MODULES(X, dirname(Y))
7. THROW "not found"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What this is basically saying is...&lt;/p&gt;

&lt;p&gt;If you require &lt;code&gt;X&lt;/code&gt;, see if it exists in node, things like &lt;code&gt;fs&lt;/code&gt;, &lt;code&gt;child_process&lt;/code&gt;, etc.&lt;/p&gt;

&lt;p&gt;If you start &lt;code&gt;require('/X');&lt;/code&gt; you're at the file system root.&lt;/p&gt;

&lt;p&gt;If you &lt;code&gt;require('./X');&lt;/code&gt; then see if &lt;code&gt;.X&lt;/code&gt; is file, then a directory.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;...and this is the interesting one...&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you do &lt;code&gt;require('X');&lt;/code&gt; and it's not a node thing, then keep traversing the file system looking in every &lt;code&gt;node_modules&lt;/code&gt; along the way.&lt;/p&gt;

&lt;h3&gt;
  
  
  Hoisting
&lt;/h3&gt;

&lt;p&gt;Package managers such as &lt;code&gt;yarn&lt;/code&gt; and &lt;code&gt;npm&lt;/code&gt; implemented a hoisting algorithm as a part of their different &lt;code&gt;workspaces&lt;/code&gt; implementations.&lt;/p&gt;

&lt;p&gt;What this hoisting does is, it scans your &lt;code&gt;package.json&lt;/code&gt; files across your workspaces and figures out what the most common versions of dependencies are.&lt;/p&gt;

&lt;p&gt;If you have 50 packages, and 47 of them are using react 16.9.0, but 3 are using 16.13.0, it'll "hoist" the common version of react, 16.19.0 to the top level &lt;code&gt;./node_modules&lt;/code&gt; directory. That way you don't have to have 50 different versions of react in your project, the &lt;code&gt;import React&lt;/code&gt; or &lt;code&gt;require('react')&lt;/code&gt; calls will simply pull from the root &lt;code&gt;node_modules/react&lt;/code&gt; one in the case of 16.9.0, or &lt;code&gt;./packages/*/node_modules/react&lt;/code&gt; for the 3 cases of 16.13.0.&lt;/p&gt;

&lt;p&gt;Voila, space saved.&lt;/p&gt;

&lt;p&gt;However, the plot thickens...&lt;/p&gt;

&lt;h3&gt;
  
  
  Monorepo structure
&lt;/h3&gt;

&lt;p&gt;So, &lt;em&gt;most&lt;/em&gt; monorepo structures have a root &lt;code&gt;package.json&lt;/code&gt;, and a &lt;code&gt;packages&lt;/code&gt; folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./packages/foo/
./packages/foo/node_modules
./packages/bar/
./packages/bar/node_modules
./package.json
./node_modules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's say we're working with the &lt;code&gt;./packages/foo/&lt;/code&gt; and it does an &lt;code&gt;import React from 'react';&lt;/code&gt;.  &lt;/p&gt;

&lt;p&gt;Following the node module resolution from above, it'll eventually look in the &lt;code&gt;./packages/foo/node_modules&lt;/code&gt; directory. If it's &lt;em&gt;not&lt;/em&gt; there, it'll look at &lt;code&gt;../packages/node_modules/&lt;/code&gt;, which definitely should not be there, and then it'll look at the &lt;code&gt;./node_modules&lt;/code&gt; directory and see if it's there.&lt;/p&gt;

&lt;p&gt;Ok, so that seems fine, where can we go wrong here?&lt;/p&gt;

&lt;p&gt;Well, a couple of different bad things can happen here.&lt;/p&gt;

&lt;p&gt;Let's say the &lt;code&gt;foo/package.json&lt;/code&gt; has &lt;code&gt;"react": "^16.9.0"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Then, let's say over in &lt;code&gt;bar&lt;/code&gt;, they forgot to add react in the package.json, but in &lt;code&gt;bar/src/index.ts&lt;/code&gt; someone does an &lt;code&gt;import React...&lt;/code&gt;, and it also happens that &lt;code&gt;bar&lt;/code&gt; used a feature that only exists in the &lt;code&gt;16.13.0&lt;/code&gt; version of React.&lt;/p&gt;

&lt;p&gt;What's gonna happen? Welp, because of the fact that &lt;code&gt;bar&lt;/code&gt; doesn't have a &lt;code&gt;react&lt;/code&gt; in its &lt;code&gt;package.json&lt;/code&gt;, the node module resolution algorithm will kick in and look up to the &lt;code&gt;../../node_modules/&lt;/code&gt; directory and grab react from there.&lt;/p&gt;

&lt;p&gt;But OH NOES, that code won't work at runtime because the code written in &lt;code&gt;bar&lt;/code&gt; needs that fancy new feature in React 16.13! This is a problem that is also nicely summed up in the Rush docs as a "&lt;a href="https://rushjs.io/pages/advanced/phantom_deps/"&gt;Phantom Dependency&lt;/a&gt;" and a "&lt;a href="https://rushjs.io/pages/advanced/npm_doppelgangers/"&gt;Doppleganger&lt;/a&gt;".&lt;/p&gt;

&lt;h3&gt;
  
  
  Real world ouchies
&lt;/h3&gt;

&lt;p&gt;Here's a real world example of how this came into play in a recent release pipeline failure.&lt;/p&gt;

&lt;p&gt;In the monorepo supported by my team, the most common version of &lt;code&gt;jest-environment-jsdom&lt;/code&gt; that was hoisted to the root &lt;code&gt;node_modules&lt;/code&gt; folder in the repo was &lt;code&gt;24.9.0&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;A pull request when in which added &lt;code&gt;jest-environment-jsdom&lt;/code&gt; 26.10.0 to one of the packages in the &lt;code&gt;./packages&lt;/code&gt; folder. Well, what happened was, there were a couple of other places using that same version across the repo so, &lt;code&gt;yarn&lt;/code&gt; in its attempt to de-duplicate by hoisting decided to switch the hoisted version to &lt;code&gt;26.10.0&lt;/code&gt;!&lt;/p&gt;

&lt;p&gt;Here's where things got bad.&lt;/p&gt;

&lt;p&gt;Let's say the package which added &lt;code&gt;jest-environment-jsdom&lt;/code&gt; was called, &lt;code&gt;cool-button&lt;/code&gt;. The pull request for adding the new dependency will get pushed to CI, and the CI server does a check for all the places where &lt;code&gt;cool-button&lt;/code&gt; is used, and start running tests, builds, etc on the dependencies in the repo to make sure that the changes &lt;code&gt;cool-button&lt;/code&gt; doesn't break any of it's downstream dependencies.&lt;/p&gt;

&lt;p&gt;Ok, PR is green, all looks great!&lt;/p&gt;

&lt;p&gt;Well, let's say there's another package called &lt;code&gt;cool-color-picker&lt;/code&gt;. And &lt;code&gt;cool-color-picker&lt;/code&gt; had some tests which was more or less like...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;it('should pull from memory storage when localStorage isnt there', () =&amp;gt; {
  expect(storageUtilThing.get('item')).toBeTruthy();
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Well, in this crazy insane case... &lt;code&gt;cool-color-picker&lt;/code&gt; &lt;em&gt;was&lt;/em&gt; relying on the hoisted &lt;code&gt;jest-environment-jsdom&lt;/code&gt; version, 24.9.0. Well, that particular version used jsdom &lt;code&gt;11.11.0&lt;/code&gt;. In that particular version of &lt;code&gt;jsdom&lt;/code&gt; there was NO local storage support in the &lt;code&gt;jsdom&lt;/code&gt; environment, so the test would pass.&lt;/p&gt;

&lt;p&gt;However! In the new version of 26.10.0 of &lt;code&gt;jest-environment-jsdom&lt;/code&gt;, the version of &lt;code&gt;jsdom&lt;/code&gt; gets bumped to &lt;code&gt;16.x.x&lt;/code&gt; and it just so happens every so ironically that version &lt;code&gt;11.12.0&lt;/code&gt; of &lt;code&gt;jsdom&lt;/code&gt; implemented localStorage. See &lt;a href="https://github.com/jsdom/jsdom/blob/master/Changelog.md"&gt;Changelog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BTNNxLbK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/12/image-6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BTNNxLbK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/12/image-6.png" alt="Inside the pain of monorepos and hoisting" width="880" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;All the sudden, the test is now failing because the test had previously assumed that there was no localStorage support in jsdom without some kind of 3rd party mocking like &lt;code&gt;jest-localstorage-mock&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;What's worse here is, because &lt;code&gt;cool-color-picker&lt;/code&gt; isn't in the dependency graph of &lt;code&gt;cool-button&lt;/code&gt;, it never got tested as a part of the pull request.&lt;/p&gt;

&lt;p&gt;Therefore, the change landed and attempted to go through the release pipeline.&lt;/p&gt;

&lt;p&gt;THANKFULLY, although also painfully, the release pipeline currently does a "build the world" strategy regardless of what changed.&lt;/p&gt;

&lt;p&gt;It's here where the release pipeline which always builds all the packages that the failure happened and broke releases for a few hours until we figured out what happened which involved LOTS of code spelunking.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--BdduUBb---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.jonathancreamer.com/content/images/2021/12/cave-dive.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BdduUBb---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://www.jonathancreamer.com/content/images/2021/12/cave-dive.gif" alt="Inside the pain of monorepos and hoisting" width="640" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  So what next?
&lt;/h2&gt;

&lt;p&gt;Well, in an ideal world we'll soon be switching to a "strict" package manager like the one we're currently building called &lt;a href="https://www.npmjs.com/package/midgard-yarn-strict"&gt;midgard-yarn-strict&lt;/a&gt;, which will eventually migrate much of it's feature set into the implementation of &lt;a href="https://github.com/npm/rfcs/pull/436"&gt;Isolated Mode&lt;/a&gt; in NPM. Yarn v2 or later can also solve this problem with plug and play, or &lt;code&gt;pnpm&lt;/code&gt; as well, but we're currently focusing on the former of the solutions with NPM and midgard yarn strict.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;strict&lt;/code&gt; package manager such as these options will do a couple of things.&lt;/p&gt;

&lt;p&gt;First of all, the packages are forced to correctly declare their dependencies in the &lt;code&gt;package.json&lt;/code&gt; so as to eliminate the phantom dependency / doppleganger problem.&lt;/p&gt;

&lt;p&gt;Secondly, the root &lt;code&gt;node_modules&lt;/code&gt; folder can be moved to a different location on disk, and pointed to with symlinks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;./packages/foo/
./packages/foo/node_modules/react -&amp;gt; node_modules/.store/react-16.9.0
./packages/bar/
./packages/bar/node_modules/react -&amp;gt; node_modules/.store/react-16.13.0
./package.json

# This breaks the node module resoution
./node_modules/.store
./node_modules/.store/react-16.13.0
./node_modules/.store/react-16.9.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By moving the &lt;code&gt;node_modules&lt;/code&gt; folder somewhere else, and simply symlinking all of the package's dependencies to the new location, the hoisting algorithm breaks.&lt;/p&gt;

&lt;p&gt;So, in the previous case where the &lt;code&gt;bar&lt;/code&gt; package had forgotten to declare react in its package, &lt;code&gt;bar&lt;/code&gt; can no longer rely on hoisting!&lt;/p&gt;

&lt;p&gt;Other things you can do to help are implementing a couple of solutions like &lt;a href="https://www.npmjs.com/package/depcheck"&gt;DepCheck&lt;/a&gt; to make based on scanning your code that your dependencies are all correctly declared. There's also a tool called &lt;a href="https://github.com/jeffijoe/typesync"&gt;TypeSync&lt;/a&gt; which does something similar for the &lt;code&gt;@types&lt;/code&gt; packages to make sure they're present. The hoisting problem with&lt;code&gt;@types&lt;/code&gt; packages presents a whole different set of complexities because their usage isn't in code necessarily, but only in the TypeScript setup.&lt;/p&gt;

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

&lt;p&gt;Hoisting helped a lot in solving &lt;em&gt;some&lt;/em&gt; problems for &lt;em&gt;many&lt;/em&gt; repos out there. However, the moment your monorepo starts to scale a bit, you'll inevitably run into these problems.&lt;/p&gt;

</description>
      <category>node</category>
      <category>monorepo</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Setting up WSL2 and the VSCode Remote Containers WSL Plugin</title>
      <dc:creator>Jonathan Creamer</dc:creator>
      <pubDate>Mon, 13 Sep 2021 17:11:52 +0000</pubDate>
      <link>https://forem.com/jcreamer898/setting-up-wsl2-and-the-vscode-remote-containers-wsl-plugin-36ob</link>
      <guid>https://forem.com/jcreamer898/setting-up-wsl2-and-the-vscode-remote-containers-wsl-plugin-36ob</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2FIMG_3519.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%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2FIMG_3519.JPG" alt="Setting up WSL2 and the VSCode Remote Containers WSL Plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For years, macOS has been the gold standard for tooling when it comes to Web Development. The unix basis of macOS, iTerm, bash, VIM, etc are all things that folks building for the web platform rely on day to day.&lt;/p&gt;

&lt;p&gt;That all changes with WSL2.&lt;/p&gt;

&lt;p&gt;WSL2 allows web dev folks working in Windows to get the same goodness of macOS's unix based tooling running "more natively" on Windows.&lt;/p&gt;

&lt;p&gt;Read more about how all this works:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.docker.com/blog/docker-hearts-wsl-2/" rel="noopener noreferrer"&gt;Docker ❤️ WSL 2 - The Future of Docker Desktop for Windows - Docker Blog&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.docker.com/blog/new-docker-desktop-wsl2-backend/" rel="noopener noreferrer"&gt;Introducing the Docker Desktop WSL 2 Backend - Docker Blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Steps to install WSL2
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step  1
&lt;/h3&gt;

&lt;p&gt;Turn on WSL in a command prompt or Powershell.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;Enable the Virtual Machine Platform&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Probably should restart after this.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;Install this &lt;a href="https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi" rel="noopener noreferrer"&gt;X64 Patch&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;Make sure WSL2.0 is default.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wsl --set-default-version 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4
&lt;/h3&gt;

&lt;p&gt;Install Linux!&lt;/p&gt;

&lt;p&gt;Go to the &lt;a href="https://aka.ms/wslstore" rel="noopener noreferrer"&gt;Windows Store&lt;/a&gt;, and find your favorite Linux.&lt;/p&gt;

&lt;p&gt;e.g. &lt;a href="https://www.microsoft.com/store/apps/9n6svws3rx71" rel="noopener noreferrer"&gt;Ubuntu 20&lt;/a&gt;, &lt;a href="https://www.microsoft.com/store/apps/9p804crf0395" rel="noopener noreferrer"&gt;Alpine Linux&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Optional other good stuff
&lt;/h3&gt;

&lt;p&gt;That's it for WSL2 install, but there's more goodness you can get with...&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Windows Terminal
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701" rel="noopener noreferrer"&gt;Windows Terminal&lt;/a&gt; is a brilliant app that manages all kinds of command prompts, terminals, etc. Read more about how to make &lt;a href="https://www.jonathancreamer.com/making-powershell-pretty/" rel="noopener noreferrer"&gt;Powershell Pretty&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-1.png" alt="Setting up WSL2 and the VSCode Remote Containers WSL Plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By default it will work with Command Prompt and Powershell, but once you have WSL, and Linux installed, it'll also allow you to open Terminals straight into your Linux!&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Docker Desktop
&lt;/h3&gt;

&lt;p&gt;Installing &lt;a href="https://www.docker.com/products/docker-desktop" rel="noopener noreferrer"&gt;Docker Desktop&lt;/a&gt; allows you to install a new WSL2 based backend that speeds up working with Docker on Windows, adds a nice GUI on top of Docker that allows you to see your running containers visually, installs all the command line tools for docker like docker-compose, and allows you to install a small kubernetes cluster as well.&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%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-2.png" alt="Setting up WSL2 and the VSCode Remote Containers WSL Plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Read more &lt;a href="https://docs.docker.com/desktop/windows/wsl/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  VSCode Remote Containers
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1
&lt;/h3&gt;

&lt;p&gt;Install the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-wsl" rel="noopener noreferrer"&gt;Remote Containers - WSL&lt;/a&gt; plugin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2
&lt;/h3&gt;

&lt;p&gt;Clone a Repo, or something in your Linux Distro.&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%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-3.png" alt="Setting up WSL2 and the VSCode Remote Containers WSL Plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3
&lt;/h3&gt;

&lt;p&gt;Use the Command Palette (Control + Shift + P) and search for Remote-WSL to Open a Folder.&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%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-4.png" alt="Setting up WSL2 and the VSCode Remote Containers WSL Plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose the folder you want, and VSCode will now open the project connected directly to your Linux Distro.&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%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-5.png" alt="Setting up WSL2 and the VSCode Remote Containers WSL Plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Alternatively you can navigate to the repo in Terminal, and use &lt;code&gt;code .&lt;/code&gt; which will also open VSCode connected directly to the Linux Distro.&lt;/p&gt;

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

&lt;p&gt;This post tried to be as clear and concise along the way to get up and running with WSL2 and VSCode as quick as possible. It's a huge productivity win for Web Dev folks working on Windows to be able to develop against Linux, so hopefully this will help accelerate those gains.&lt;/p&gt;

&lt;h2&gt;
  
  
  BONUS PROTIP
&lt;/h2&gt;

&lt;p&gt;You can also install the &lt;a href="https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers" rel="noopener noreferrer"&gt;Remote - Containers&lt;/a&gt;plugin and test out different programming languages with the power of Docker.&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%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-7.png" alt="Setting up WSL2 and the VSCode Remote Containers WSL Plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.jonathancreamer.com%2Fcontent%2Fimages%2F2021%2F09%2Fimage-6.png" alt="Setting up WSL2 and the VSCode Remote Containers WSL Plugin"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>docker</category>
      <category>vscode</category>
      <category>wsl</category>
    </item>
    <item>
      <title>Making powershell pretty</title>
      <dc:creator>Jonathan Creamer</dc:creator>
      <pubDate>Wed, 21 Jul 2021 19:17:34 +0000</pubDate>
      <link>https://forem.com/jcreamer898/making-powershell-pretty-28d</link>
      <guid>https://forem.com/jcreamer898/making-powershell-pretty-28d</guid>
      <description>&lt;p&gt;For the first time in a long time, Windows has re-entered my life now that I work at Microsoft.&lt;/p&gt;

&lt;p&gt;In macOS land, I use iTerm and oh-my-zsh to make a pretty shell environment with all the colors and such, so when I got to Windows again and lanched into the blue Powershell Window, I figured there had to be something better...&lt;/p&gt;

&lt;p&gt;This is what Powershell looks like now!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--qIQvnLu---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/07/image.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--qIQvnLu---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/07/image.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Windows Terminal
&lt;/h3&gt;

&lt;p&gt;The first thing to make sure you have installed is the &lt;a href="https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701?activetab=pivot:overviewtab"&gt;Windows Terminal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;That is a fantastic product, and even has built in support for WSL, CMD, Azure, and launching into Ubuntu or whatever your Linux Environment is...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dS5tno25--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/07/image-1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dS5tno25--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/07/image-1.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Another #protip is you can hold Ctrl + Shift when launching Windows Terminal and it'll open as an Administrator.&lt;/p&gt;

&lt;p&gt;Windows Terminal is super easy to configure as well, and there are themes for it as well at &lt;a href="https://terminalsplash.com/"&gt;&amp;gt;_TerminalSplash - Windows Terminal Themes&lt;/a&gt; or &lt;a href="https://windowsterminalthemes.dev/"&gt;Windows Terminal Themes&lt;/a&gt;. You simply copy the JSON from those sites, and open the Windows Terminal Settings and Click "Open JSON File"...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--M_mrM3MM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/07/image-2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M_mrM3MM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/07/image-2.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Oh My Posh
&lt;/h3&gt;

&lt;p&gt;The tool that adds the bar at the bottom of the Powershell window is called &lt;a href="https://ohmyposh.dev/"&gt;Oh My Posh&lt;/a&gt; of course inspired by &lt;a href="https://ohmyz.sh/"&gt;oh-my-zsh&lt;/a&gt; for mac / linux.&lt;/p&gt;

&lt;p&gt;To install, simply run...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install-Module oh-my-posh -Scope CurrentUser
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then you can list all the themes with...&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Once you find one you like, you can edit your &lt;code&gt;$PROFILE&lt;/code&gt; in your editor of choice, e.g. &lt;code&gt;notepad $PROFILE&lt;/code&gt;, &lt;code&gt;code -a $PROFILE&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;And you can set your theme up with...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Set-PoshPrompt -Theme jandedobbeleer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The last thing you'll more than likely also have to do is download the right fonts that supports "Powerline" fonts, the Oh My Posh &lt;a href="https://ohmyposh.dev/docs/fonts"&gt;docs&lt;/a&gt;talk about that. More than likely, you'll choose a font from &lt;a href="https://www.nerdfonts.com/"&gt;Nerd Fonts&lt;/a&gt;, and update your Windows Terminal settings to point to the new font.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"profiles": 
    {
        "defaults": 
        {
            "fontFace": "MesloLGL Nerd Font"
        }
     }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It'll even show you what version of node you're in as well as many other what they call "Segments"...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2bU3fElq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/07/image-3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2bU3fElq--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2021/07/image-3.png" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There ya go! You'll be the envy of all your Windows code demos in meetings going forward.&lt;/p&gt;

</description>
      <category>powershell</category>
      <category>windows</category>
      <category>tools</category>
    </item>
    <item>
      <title>Getting started with Frontend Architecture and DivOps</title>
      <dc:creator>Jonathan Creamer</dc:creator>
      <pubDate>Wed, 31 Mar 2021 17:24:59 +0000</pubDate>
      <link>https://forem.com/jcreamer898/getting-started-with-frontend-architecture-and-divops-33gn</link>
      <guid>https://forem.com/jcreamer898/getting-started-with-frontend-architecture-and-divops-33gn</guid>
      <description>&lt;p&gt;Trying to understand the world of Frontend Software Development is like trying to solve a Rubix cube that automatically scrambles itself when you get close to solving it. You'll never fully understand it, and that's ok! What you can do though is maybe stop worrying about the entire cube, and focus on one side or even one row, and just be happy you solved that part of it.&lt;/p&gt;

&lt;p&gt;My friend Cory House tweeted this a while ago, and I heard him give a talk on it as well...&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Why specialize? Because the industry is changing faster than ever.  &lt;/p&gt;

&lt;p&gt;Today, the half-life of an engineering degree is between 2.5 and 5 years. You must study 10 - 20 hours a week just to keep up with the weekly changes.  &lt;/p&gt;

&lt;p&gt;Critical read for every dev: &lt;a href="https://t.co/lDaDAYA1RH"&gt;https://t.co/lDaDAYA1RH&lt;/a&gt; &lt;a href="https://t.co/869LlGzlJd"&gt;pic.twitter.com/869LlGzlJd&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;— Cory House (@housecor) &lt;a href="https://twitter.com/housecor/status/975730389925982208?ref_src=twsrc%5Etfw"&gt;March 19, 2018&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Specializing in something can be just as if not more rewarding for your long term career growth. Sometimes it's ok to stop learning a little about a lot and learn a lot about a little.&lt;/p&gt;

&lt;p&gt;The important point to make here is, you don't have to know everything there is to know about Frontend Development to be successful. In fact, you might be more successful if you simply pick the area of frontend you want to specialize in, and stick with that! Inside of the frontend world, as &lt;a href="https://twitter.com/brad_frost?"&gt;Brad Frost&lt;/a&gt; put it so well recently, there's the &lt;a href="https://bradfrost.com/blog/post/front-of-the-front-end-and-back-of-the-front-end-web-development/"&gt;Front of the frontend, and the Back of the frontend&lt;/a&gt;. If you're reading this and you find yourself leaning more and more into the "Back of the frontend", aka things like bundlers, testing, CI, Docker, deployments, APIs, etc, then maybe you should consider specializing in Frontend Architecture aka DivOps.&lt;/p&gt;

&lt;p&gt;&amp;lt;!--kg-card-begin: html--&amp;gt;&amp;lt;!--kg-card-end: html--&amp;gt;&lt;/p&gt;

&lt;p&gt;A lot of folks who start to specialize in DivOps at one point were on the Front side of frontend, using jQuery, then into Backbone, require.js, maybe Angular, then React or Vue, etc etc. Along that journey a few folks might have decided that actually enjoyed spending time configuring all those different tools to work. As time has passed, it's become increasingly more and more difficult and tedious to manage all that configuration and infrastructure.&lt;/p&gt;

&lt;p&gt;If the journey you're on feels like you've started venturing into the Divops world, then here are some great resources to get you started!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Weekly newsletters such as &lt;a href="https://nodeweekly.com/"&gt;node&lt;/a&gt;, &lt;a href="http://esnextnews.com/"&gt;esnext&lt;/a&gt;, and &lt;a href="https://javascriptweekly.com/"&gt;JS Weekly&lt;/a&gt; are expertly curated with swaths of knowledge delivered to your inbox weekly&lt;/li&gt;
&lt;li&gt;Ya know that &lt;code&gt;node_modules&lt;/code&gt; folder? Actually try looking into it some times. You can spend a few minutes reading over some babel plugins and learn a ton about important topics like ASTs&lt;/li&gt;
&lt;li&gt;Speaking of which, learn some ASTs! Start with the &lt;a href="https://github.com/jamiebuilds/babel-handbook"&gt;Babel Handbook&lt;/a&gt;, ASTs are how most modern tools work under the hood and can be extremely powerful in manipulating thousands of lines of code in seconds through things like babel plugins and "codemods" with &lt;a href="https://github.com/facebook/jscodeshift"&gt;jscodeshift&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;While yes, there are a TON of tools out there, you don't have to learn ALL of them at once, pick a few at a time, find out which one you like, try to learn the ins and outs of webpack vs rollup vs snowpack. In the end of the day, there are reasons why you might choose one over the other, but there's no technically wrong choice. Pick what works for your problem at that moment.&lt;/li&gt;
&lt;li&gt;Learn about monorepo tools like yarn workspaces, lerna, bolt, rush, etc. Monorepos can be extremely useful in a large scale frontend architecture&lt;/li&gt;
&lt;li&gt;Read code, like lots of it, particularly in code bases like &lt;a href="https://github.com/babel/babel"&gt;Babel&lt;/a&gt;, &lt;a href="https://github.com/typescript-eslint/typescript-eslint"&gt;Typescript ESLint&lt;/a&gt;, or just go through trending Github languages like... &lt;a href="http://github.com/trending/javascript"&gt;http://github.com/trending/javascript&lt;/a&gt;, &lt;a href="http://github.com/trending/javascript"&gt;http://github.com/trending/javascript&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Learn &lt;a href="https://docs.docker.com/get-started/overview/"&gt;Docker&lt;/a&gt;. Docker is huge in the DivOps, and DevOps worlds alike.&lt;/li&gt;
&lt;li&gt;Learn a CI tool, or a few... CircleCI, Travis CI, Github Actions, and Azure Pipelines are all good ones to get started with and basically all do the same thing, just slightly differently&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://2020.stateofjs.com/en-US/technologies/javascript-flavors/"&gt;Typescript&lt;/a&gt; is probably a good idea now. :)&lt;/li&gt;
&lt;li&gt;Talk to people, engage, join a &lt;a href="https://www.jonathancreamer.com/announcing-div-ops/"&gt;community&lt;/a&gt;, join Twitter to meet folks doing this same type of stuff, go to conferences, even virtual ones can offer you a chance to meet others&lt;/li&gt;
&lt;li&gt;Write. Things. Down. This cannot be stressed this enough. Journal, blog, create a Notion blog, Evernote, etc. Write down everything, ideas, day to day work logs, tips and tricks, proposals that you can share with other engineers or leadership folks, etc. Our brains can hold a finite amount of information in them at once.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Stay connected, specialize, and have fun!&lt;/p&gt;

&lt;p&gt;DivOps is a great path to tread, and is an ever evolving discipline.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Running Typescript programs with babel-node aka how does babel register work</title>
      <dc:creator>Jonathan Creamer</dc:creator>
      <pubDate>Wed, 09 Dec 2020 18:32:31 +0000</pubDate>
      <link>https://forem.com/jcreamer898/running-typescript-programs-with-babel-node-aka-how-does-babel-register-work-35jj</link>
      <guid>https://forem.com/jcreamer898/running-typescript-programs-with-babel-node-aka-how-does-babel-register-work-35jj</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--MSRZrwIu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/IMG_7214.JPG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--MSRZrwIu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/IMG_7214.JPG" alt="Running Typescript programs with babel-node aka how does babel register work" width="880" height="1173"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As a member of a frontend infrastructure team, (aka &lt;a href="https://www.jonathancreamer.com/announcing-div-ops/"&gt;DivOps&lt;/a&gt;), I write a lot of Javascript tooling. I also really really like Typescript. In fact most of the tooling I write these days is written in Typescript.&lt;/p&gt;

&lt;p&gt;The problem is, when the tools we work on are handed off to our end users, they have to either be compiled with tsc, or babel first. Generally we typecheck with &lt;code&gt;tsc&lt;/code&gt; and transpile with the &lt;code&gt;@babel/preset-typescript&lt;/code&gt; preset.&lt;/p&gt;

&lt;p&gt;Sometimes though, that compilation step causes a delay, and we'd rather just run the code as is, Typescript, ES modules and all. That's where tools like &lt;code&gt;@babel/node&lt;/code&gt; come in.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@babel/node&lt;/code&gt; allows you to "transpile" code from Typescript, or "ES Next" JavaScript with modules, or whatever to Javascript that can run in nodejs, and it does this at runtime as opposed to pre-transpiling.&lt;/p&gt;

&lt;p&gt;Aka you can do stuff like this, and run Typescript files without "pre" compiling them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;babel-node -x .ts -- ./path/to/script.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, how does &lt;code&gt;@babel/node&lt;/code&gt; actually work?&lt;/p&gt;

&lt;h2&gt;
  
  
  npm i -D &lt;a class="mentioned-user" href="https://dev.to/babel"&gt;@babel&lt;/a&gt;/node
&lt;/h2&gt;

&lt;p&gt;When you install this pacakage, it will add a &lt;code&gt;babel-node&lt;/code&gt; command to your &lt;code&gt;./node_modules/.bin&lt;/code&gt; folder. This &lt;code&gt;.bin&lt;/code&gt; folder is used for all CLI tools you install, things like &lt;code&gt;webpack&lt;/code&gt;, &lt;code&gt;babel-node&lt;/code&gt;, etc. The &lt;code&gt;.bin&lt;/code&gt; then just symlinks the &lt;code&gt;babel-node&lt;/code&gt; command to &lt;code&gt;./node_modules/@babel/node/bin/babel-node&lt;/code&gt;. This works because of the &lt;code&gt;"bin"&lt;/code&gt; being set to &lt;code&gt;"babel-node": "./bin/babel-node.js"&lt;/code&gt; right &lt;a href="https://github.com/babel/babel/blob/a17e4715c986eed1768461173b123650e5371307/packages/babel-node/package.json#L46"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Then, &lt;code&gt;babel-node&lt;/code&gt; is simply a program with a shebang that tells the system to what interpreter to use for the program, in this case the &lt;code&gt;/usr/bin/env&lt;/code&gt; &lt;a href="https://en.wikipedia.org/wiki/Env"&gt;command&lt;/a&gt; is what actually runs first, and makes sure that it can find &lt;code&gt;node&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#!/usr/bin/env node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;babel-node&lt;/code&gt; program itself then just imports &lt;code&gt;require("../lib/babel-node");&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;This is where we start getting into the actual runtime of &lt;code&gt;@babel/node&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;lib/babel-node.js&lt;/code&gt; script is responsible for reading in any runtime arguments for &lt;a href="https://www.npmjs.com/package/v8-flags"&gt;v8&lt;/a&gt; runtime stuff like &lt;code&gt;--harmon&lt;/code&gt; or &lt;a href="https://www.npmjs.com/package/node-environment-flags"&gt;node&lt;/a&gt; env variables like &lt;code&gt;--require&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Ultimately the &lt;code&gt;lib/babel-node.js&lt;/code&gt; uses a program called &lt;code&gt;kexec&lt;/code&gt;, a &lt;a href="https://github.com/jprichardson/node-kexec/blob/b9a462ee508b1b799e68db91ee0fc1938b9be3f7/src/kexec.cc"&gt;C++ program&lt;/a&gt;which swaps out a process at runtime, to actually run &lt;code&gt;./lib/_babel-node.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;./lib/_babel-node.js&lt;/code&gt; is where things really start to happen as this is &lt;em&gt;really&lt;/em&gt; the meat of what &lt;code&gt;@babel/node&lt;/code&gt; is actually doing. It uses a CLI helper utility called commander and sets it up with the following possible args.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LvYRRsiy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/Screenshot-on-2020-12-09-at-09-41-47.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LvYRRsiy--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/Screenshot-on-2020-12-09-at-09-41-47.png" alt="Running Typescript programs with babel-node aka how does babel register work" width="880" height="272"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll notice a few of those are similar to ones you'd use when working directly with &lt;code&gt;node&lt;/code&gt; itself. Things like &lt;code&gt;-e&lt;/code&gt;, &lt;code&gt;-p&lt;/code&gt;, and &lt;code&gt;-r&lt;/code&gt; are all flags that &lt;code&gt;node&lt;/code&gt; itself also accepts, other flags like &lt;code&gt;--inspect&lt;/code&gt; fall through to the node process that will ultimately get spun up.&lt;/p&gt;

&lt;p&gt;Eventually after some args parsing, an internal &lt;code&gt;Module.runMain&lt;/code&gt; &lt;a href="https://github.com/nodejs/node/blob/b589128f6f4c3c6f636bfb0146957847ef0a8d53/lib/internal/bootstrap/pre_execution.js#L417"&gt;function&lt;/a&gt;) happens and runs your script by overwriting the arguments passed with &lt;code&gt;process.argv&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;process.argv = [
 '/path/to/node/v12.17.0/bin/node',
 '/path/to/node_modules/@babel/node/lib/_babel-node',
 ...args,
];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then what happens in &lt;a href="%5Bhttps://github.com/babel/babel/blob/5067edfdd95fc4c38cb5e60192eac5f7649fa229/packages/babel-node/src/_babel-node.js#L198%5D(https://github.com/babel/babel/blob/5067edfdd95fc4c38cb5e60192eac5f7649fa229/packages/babel-node/src/_babel-node.js#L198)"&gt;this line&lt;/a&gt; is, &lt;code&gt;node&lt;/code&gt; will now run &lt;code&gt;/path/to/_babel-node&lt;/code&gt;, and send it your actual runtime arguments.&lt;/p&gt;

&lt;p&gt;So, that's how &lt;code&gt;_babel-node&lt;/code&gt; is actually invoked, but how does it transpile Typescript to Javascript on the fly?&lt;/p&gt;

&lt;p&gt;The answer there is &lt;code&gt;@babel/register&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a class="mentioned-user" href="https://dev.to/babel"&gt;@babel&lt;/a&gt;/register
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;@babel/register&lt;/code&gt; is the special sauce of how &lt;code&gt;@babel/node&lt;/code&gt; is able to actually read in Typescript, or ES Next Javascript, transpile it to commonjs, and run it on the fly.&lt;/p&gt;

&lt;p&gt;Using &lt;code&gt;@babel/register&lt;/code&gt; is one way the &lt;a href="https://babeljs.io/setup#installation"&gt;docs&lt;/a&gt; say to setup your code.&lt;/p&gt;

&lt;p&gt;Basically instead of &lt;code&gt;babel-node -- path/to/your/script.ts&lt;/code&gt; you can manually call the &lt;code&gt;@babel/register&lt;/code&gt; module itself by importing it in your code and call it with &lt;code&gt;node /path/to/your/script.ts&lt;/code&gt;, in the case of Typescript though&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;require("@babel/register")({
  extension: ['.ts', '.tsx', '.js', '.jsx']
});
const { main } = require("./src/cli");

main().catch((e) =&amp;gt; console.error(e));
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Keep in mind with register, you have to separate your entry point from your code because register has to run and add the &lt;code&gt;require&lt;/code&gt; hooks to the NEXT files you'll load, aka you can't have &lt;code&gt;import&lt;/code&gt; and &lt;code&gt;require("@babel/register");&lt;/code&gt; in the same file. Note to use Typescript and Typescript with React, you'll have to add the &lt;code&gt;"extensions"&lt;/code&gt;. The other arguments you can pass to register are the same as the regular babel &lt;a href="https://babeljs.io/docs/en/options"&gt;options&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In terms of &lt;code&gt;@babel/node&lt;/code&gt;, the &lt;code&gt;register&lt;/code&gt; function gets called &lt;a href="https://github.com/babel/babel/blob/5067edfdd95fc4c38cb5e60192eac5f7649fa229/packages/babel-node/src/_babel-node.js#L93"&gt;here&lt;/a&gt; and is passed the command line args, and some additional configuration for babel.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;@babel/register&lt;/code&gt; uses a library called &lt;a href="https://www.npmjs.com/package/pirates"&gt;pirates&lt;/a&gt; to add a compile hook using some internal &lt;code&gt;Module.__extensions&lt;/code&gt; &lt;a href="https://github.com/ariporad/pirates/blob/5223d20e54f724780eb73d4d4918f70004d9d8dc/src/index.js#L59"&gt;magic&lt;/a&gt; to change the underlying Javascript loader in node. It does that &lt;a href="https://github.com/babel/babel/blob/main/packages/babel-register/src/node.js#L99"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So basically every time a file gets &lt;code&gt;require&lt;/code&gt;'d going forward in your program, it'll first run through the &lt;code&gt;compile&lt;/code&gt; &lt;a href="https://github.com/babel/babel/blob/5067edfdd95fc4c38cb5e60192eac5f7649fa229/packages/babel-register/src/node.js#L39"&gt;function&lt;/a&gt;, get compiled, and finally executed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running and debugging babel-node
&lt;/h3&gt;

&lt;p&gt;There's a couple of different ways to run a script with &lt;code&gt;babel-node&lt;/code&gt;, just like with &lt;code&gt;node&lt;/code&gt; itself.&lt;/p&gt;

&lt;p&gt;Passing it the name of a script will invoke the script just like it would with &lt;code&gt;node&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;babel-node -x .ts -- ./path/to/script.ts&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;👆note the &lt;code&gt;-x .ts&lt;/code&gt; or &lt;code&gt;--extensions .ts&lt;/code&gt; there to make it recognize the Typescript &lt;code&gt;.ts&lt;/code&gt; extension as well as &lt;code&gt;.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;You can also add the &lt;code&gt;--inspect&lt;/code&gt; flag and in VS Code or using &lt;code&gt;chrome://inspect&lt;/code&gt;, you can &lt;strong&gt;debug&lt;/strong&gt; your command line script. In VS Code make sure you have on Auto Inspect, and you'll then be able to throw breakpoints into your code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rpsC10R2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/Screenshot-on-2020-12-09-at-10-45-36.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rpsC10R2--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/Screenshot-on-2020-12-09-at-10-45-36.png" alt="Running Typescript programs with babel-node aka how does babel register work" width="155" height="51"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--LMa-9NAE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/Screenshot-on-2020-12-09-at-10-44-14.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--LMa-9NAE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/Screenshot-on-2020-12-09-at-10-44-14.png" alt="Running Typescript programs with babel-node aka how does babel register work" width="569" height="74"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to use the Chrome developer tools to debug your script, make sure you throw a &lt;code&gt;debugger;&lt;/code&gt; statement somewhere in your code, then you can run...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;babel-node -x .ts --inspect-brk -- ./path/to/script.ts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;--inspect-brk&lt;/code&gt; will force the process to pause at the very first line of execution, which actually in this case will pause in the &lt;code&gt;_babel-node.js&lt;/code&gt; script since that's technically the first line of code that gets executed. Then you can visit &lt;code&gt;chrome://inspect&lt;/code&gt; and find your node script in the list, and click inspect.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--vuSxuPEM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/Screenshot-on-2020-12-09-at-11-16-04.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--vuSxuPEM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/Screenshot-on-2020-12-09-at-11-16-04.png" alt="Running Typescript programs with babel-node aka how does babel register work" width="604" height="90"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You'll then get dropped into a Chrome Debugger.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DhWm7IIX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/Screenshot-on-2020-12-09-at-10-50-23.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DhWm7IIX--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/12/Screenshot-on-2020-12-09-at-10-50-23.png" alt="Running Typescript programs with babel-node aka how does babel register work" width="584" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can run &lt;code&gt;babel-node&lt;/code&gt; with &lt;code&gt;-e&lt;/code&gt; and execute code on the fly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;babel-node -e "console.log('oh hai');"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can run a script in combo with &lt;code&gt;-p&lt;/code&gt; and print the results...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;babel-node -e "new Date().getTime()" -p
// 1607531838009
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lastly you can run &lt;code&gt;babel-node&lt;/code&gt; by itself, to spin up a &lt;code&gt;repl&lt;/code&gt; for playing around in &lt;code&gt;node&lt;/code&gt; with an environment that will transpile code on the fly for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Gotchas
&lt;/h2&gt;

&lt;p&gt;One thing in particular that has bit me many times, and partly is the reason why I am writing this post to begin with is,&lt;/p&gt;

&lt;h3&gt;
  
  
  When using babel register, call the register function before your code
&lt;/h3&gt;

&lt;p&gt;As mentioned previously, make sure when using &lt;code&gt;@babel/register&lt;/code&gt;, call the &lt;code&gt;require("@babel/register")&lt;/code&gt; first, then require your actual code. Otherwise it won't work at all.&lt;/p&gt;

&lt;h3&gt;
  
  
  babel-node's command line ignore overrides the ignores in your babel.config.js
&lt;/h3&gt;

&lt;p&gt;This one seems like a &lt;a href="%5Bhttps://github.com/babel/babel/issues/11892#issuecomment-687845634%5D(https://github.com/babel/babel/issues/11892#issuecomment-687845634)"&gt;bug&lt;/a&gt;, but basically, if your &lt;code&gt;babel.config.js&lt;/code&gt; has any kind of ignore in it...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module.exports = {
  /* ... blah blah babel stuff */
  ignore: [function(filepath) {
    return filepath.includes('some-string-you-wanna-ignore');
  }]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You have to pass an empty ignore in your &lt;code&gt;babel-node --ignore ' ' path/to/script.ts&lt;/code&gt;. It probably has to do with &lt;a href="https://github.com/babel/babel/blob/5067edfdd95fc4c38cb5e60192eac5f7649fa229/packages/babel-register/src/node.js#L140"&gt;this line&lt;/a&gt;. Register is expecting ignore not to be undefined, and it's not checking that against the ignore from the &lt;code&gt;babel.config.js&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  babel-node will add your process.cwd() location to the --only param by default.
&lt;/h3&gt;

&lt;p&gt;This might be fine in your codebase, but if you're expecting &lt;code&gt;babel-node&lt;/code&gt; to be able to transpile code from outside of your &lt;code&gt;cwd&lt;/code&gt;, it simply won't work because &lt;code&gt;@babel/register&lt;/code&gt; . This goes back to the same &lt;a href="https://github.com/babel/babel/blob/5067edfdd95fc4c38cb5e60192eac5f7649fa229/packages/babel-register/src/node.js#L140"&gt;line&lt;/a&gt; above. If no &lt;code&gt;--only&lt;/code&gt; flag is passed at run time, babel will by default ignore anything outside your current working directory AND anything in &lt;code&gt;$(cwd)/node_modules&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So, say you have a project structure like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;packages/tools/my-awesome-tool/
packages/utils/
package.json

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

&lt;/div&gt;



&lt;p&gt;If you have a script in &lt;code&gt;my-awesome-tool/scripts/cool-script.ts&lt;/code&gt; which imports from &lt;code&gt;packages/utils&lt;/code&gt; and you invoke it FROM the directory, i.e. if you did &lt;code&gt;cd packages/tools/my-awesome-tool&lt;/code&gt;, the scripts in&lt;code&gt;packages/utils&lt;/code&gt; will NOT get transpiled by default.&lt;/p&gt;

&lt;p&gt;There are 2 ways around this. First, just run all your scripts from the root of your project. Second, you can pass &lt;code&gt;--only /path/to/project&lt;/code&gt;. That way it won't ignore stuff.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make sure to add the &lt;code&gt;--&lt;/code&gt; thing when running a script
&lt;/h3&gt;

&lt;p&gt;If you forget to add &lt;code&gt;--&lt;/code&gt; in between your options i.e. &lt;code&gt;babel-node -x .ts path/to/scripts.ts&lt;/code&gt; instead of &lt;code&gt;babel-node -x .ts -- path/to/script.ts&lt;/code&gt;, then &lt;code&gt;babel-node&lt;/code&gt; is going to try to parse through the options you passed to your OWN script. This is especially important when the script your calling takes it args.&lt;/p&gt;

&lt;p&gt;For example...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;babel-node -x .ts -- ./node_modules/.bin/build-storybook \
  -c packages/tools/storybook/src/config \
  -o packages/tools/storybook/dist/storybook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, we're calling the &lt;code&gt;build-storybook&lt;/code&gt; command with &lt;code&gt;babel-node&lt;/code&gt;, and the &lt;code&gt;-o&lt;/code&gt; flag is setting the output dir for storybook. If you forget the &lt;code&gt;--&lt;/code&gt;, the &lt;code&gt;-o&lt;/code&gt; param will actually be parsed as the &lt;code&gt;--only&lt;/code&gt; flag for babel!&lt;/p&gt;

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

&lt;p&gt;&lt;code&gt;@babel/node&lt;/code&gt; is a nice convenient way to run scripts on the fly without pre-compiling them. Just be aware of some its nuances and you'll be able to build some amazing tools.&lt;/p&gt;

&lt;p&gt;This post was written primarily because many of the things mentioned are things I've dealt with in real life, and I kept running into them over and over again, and finally decided it was time to write them down for myself! Hopefully it can help you too.&lt;/p&gt;

</description>
      <category>babel</category>
      <category>typescript</category>
      <category>divops</category>
    </item>
    <item>
      <title>Dealing with async jest tests</title>
      <dc:creator>Jonathan Creamer</dc:creator>
      <pubDate>Fri, 25 Sep 2020 18:11:28 +0000</pubDate>
      <link>https://forem.com/jcreamer898/dealing-with-async-jest-tests-1bkm</link>
      <guid>https://forem.com/jcreamer898/dealing-with-async-jest-tests-1bkm</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UgZX-GLB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/09/delorean.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UgZX-GLB--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/09/delorean.jpg" alt="Dealing with async jest tests"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In &lt;a href="https://jestjs.io/"&gt;jest&lt;/a&gt;, there are a couple of different ways to handle tests which deal with async code.&lt;/p&gt;

&lt;p&gt;Let's say way have a test that calls &lt;code&gt;fetchSomeAsyncThing()&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should call my api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetchSomeAsyncThing&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will fail.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because of the way JavaScript handles async code.&lt;/p&gt;

&lt;p&gt;When you call a function known to be async, whether it's something that returns a &lt;code&gt;Promise&lt;/code&gt;, calls a &lt;code&gt;setTimeout&lt;/code&gt;, etc, that function get pushed onto a call stack, and called wayyy after your tests have actually ran.&lt;/p&gt;

&lt;p&gt;A stack is a data structure kinda like an array which basically means, the last thing that got put into it, is the first thing to come out. Read more about &lt;a href="https://github.com/trekhleb/javascript-algorithms/tree/master/src/data-structures/stack"&gt;stacks&lt;/a&gt; and &lt;a href="https://blog.bitsrc.io/understanding-asynchronous-javascript-the-event-loop-74cd408419ff"&gt;async Javacript.&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Use the done callback
&lt;/h2&gt;

&lt;p&gt;If your async function returns a callback, several of the jest functions provide a done callback which you can use 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;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should call my api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetchSomeAsyncThing&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, the callback to the &lt;code&gt;it&lt;/code&gt; method above returns a &lt;code&gt;done&lt;/code&gt; function.&lt;/p&gt;

&lt;p&gt;This &lt;code&gt;done&lt;/code&gt; function will tell jest that your async method is done and it will wait for that all to finish before wrapping up that test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use promises
&lt;/h2&gt;

&lt;p&gt;If your async function returns promises you can do one of 2 things.&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;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should call my api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;done&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;fetchSomeAsyncThing&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="nx"&gt;done&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;Similar to above, use the &lt;code&gt;done&lt;/code&gt; function inside the &lt;code&gt;.then&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Or, you can simply return the entire promise.&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;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should call my api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;fetchSomeAsyncThing&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case, jest will realize that the return value of the test was itself a promise, and will therefore wait until that promise fully resolves before wrapping up the test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use async / await
&lt;/h2&gt;

&lt;p&gt;Once again, if you know that your async function returns a promise, you can use the &lt;code&gt;async&lt;/code&gt; and &lt;code&gt;await&lt;/code&gt; features of &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function"&gt;modern Javascript&lt;/a&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="nx"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;should call my api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fetchSomeAsyncThing&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;hello world&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;async&lt;/code&gt; / &lt;code&gt;await&lt;/code&gt; method is a nice, clean way to read the code.&lt;/p&gt;

</description>
      <category>jest</category>
      <category>testing</category>
      <category>javascript</category>
      <category>async</category>
    </item>
    <item>
      <title>For of loops in Javascript one loop to rule them all</title>
      <dc:creator>Jonathan Creamer</dc:creator>
      <pubDate>Tue, 17 Mar 2020 19:04:37 +0000</pubDate>
      <link>https://forem.com/jcreamer898/for-of-loops-in-javascript-one-loop-to-rule-them-all-nk8</link>
      <guid>https://forem.com/jcreamer898/for-of-loops-in-javascript-one-loop-to-rule-them-all-nk8</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ZjfIyBee--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/03/IMG_0533-EFFECTS.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ZjfIyBee--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://www.jonathancreamer.com/content/images/2020/03/IMG_0533-EFFECTS.jpg" alt="For of loops in Javascript one loop to rule them all"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the longest time, &lt;code&gt;for in&lt;/code&gt; and &lt;code&gt;for&lt;/code&gt; were the main loops you could use to iterate over collections of things in JavaScript. Then we got some fancy array methods like &lt;code&gt;forEach&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;filter&lt;/code&gt;, etc. It starts to get a bit confusing of when to use each loop type. For example, you can't use &lt;code&gt;for in&lt;/code&gt; on array's, only on objects. Then, how do I loop over an object? Well, you can use &lt;code&gt;for in&lt;/code&gt;, but only if you check &lt;code&gt;hasOwnProperty&lt;/code&gt; or whatever, or use...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Object.keys(obj).map((key) =&amp;gt; {
  const value = map[key];
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which is all weird because you have to get the keys, then grab the value, etc.&lt;/p&gt;

&lt;p&gt;Now, we have a new thing as of ES6 called &lt;code&gt;for of&lt;/code&gt;. It's becoming more and more used as knowledge of how to use it has grown, but there's still occasional confusion around how/when to use it. Below is a quick cheatseat of some usages of &lt;code&gt;for of&lt;/code&gt;, one loop to rule them all.&lt;/p&gt;

&lt;h3&gt;
  
  
  Arrays
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const arrayOfStuff = ['thing one', 'thing two', 'thing three'];

for (const thing of arrayOfStuff) {
  console.log(thing);
}

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

&lt;/div&gt;



&lt;p&gt;For arrays, it's pretty simple. It looks like a &lt;code&gt;for in&lt;/code&gt;, but you can't &lt;code&gt;for in&lt;/code&gt; an array. The point here is, the &lt;code&gt;thing&lt;/code&gt; becomes each item in the array.&lt;/p&gt;

&lt;h3&gt;
  
  
  Arrays of Objects
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const arrayOfObjectsOfStuff = [{ name: 'thing one' }, {name: 'thing two' }, { name: 'thing three' }];

for (const { name } of arrayOfObjectsOfStuff) {
  console.log(name);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here you'll notice when iterating an array of objects, you can utilize destructuring to pull the value of the key &lt;code&gt;name&lt;/code&gt; off of every item in the array. Note, the descructuring here uses &lt;code&gt;{}&lt;/code&gt;'s because we're descructuring an object, vs &lt;code&gt;[]&lt;/code&gt; in the case of desctructuring an array.&lt;/p&gt;

&lt;h3&gt;
  
  
  Objects
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const userMap = {
  '123': 'user 1',
  '456': 'user 2',
  '789': 'user 3',
};

for (const [id, name] of Object.entries(userMap)) {
  console.log(id, name);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Things get even cooler here now, thanks to the magic of &lt;code&gt;Object.entries&lt;/code&gt;. Object.entries returns an array of key value pairs, so in this case basically...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[
  [123, 'user 1'],
  [456, 'user 2'],
  [789, 'user 3'],
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, you're in one line converting the object to an array of key value arrays, and then using destructuring to get the id, and name values!&lt;/p&gt;

&lt;h3&gt;
  
  
  Maps
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const actualMapOfUsers = new Map();

actualMapOfUsers.set('123', 'user 1');
actualMapOfUsers.set('456', 'user 2');
actualMapOfUsers.set('7899', 'user 3');

for (const [id, name] of Array.from(actualMapOfUsers)) {
  console.log(id, name);
}

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

&lt;/div&gt;



&lt;p&gt;With ES6 &lt;code&gt;Map&lt;/code&gt; objects, you can just use the &lt;code&gt;Array.from&lt;/code&gt; method to convert the &lt;code&gt;Map&lt;/code&gt; into, you guessed it, an array of key values pairs again.&lt;/p&gt;

&lt;h3&gt;
  
  
  Promises
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const getUser = async (name) =&amp;gt; {
  const response = await fetch(`https://api.github.com/users/${name}`);
  const json = await response.json();
  return json;
};

const arrayOfPromises = [];

const usernames = ['jcreamer898', 'kwelch', 'AlexSwensen'];
for (const user of usernames) {
  arrayOfPromises.push(getUser(user));
}

Promise.all(arrayOfPromises).then((users) =&amp;gt; {
  for (const user of users) {
    console.log(user.name);
  }
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The final crazy cool thing you can do is handle promises or async await inside of &lt;code&gt;for of&lt;/code&gt; loops. In the above example, we're actually creating an array of promises which we then resolve with &lt;code&gt;Promise.all&lt;/code&gt;, so this will add a bunch of stuff into the event loop and then once they're all resolved, call the &lt;code&gt;.then&lt;/code&gt; on the &lt;code&gt;Promise.all&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Note in this case, there's no use of async / await, so the code will transpile to much less than that of the code that would require babel polyfill, etc from using async await. That said, you probably already have a polyfill like babel installed, so alternatively you can still async/await the &lt;code&gt;Promise.all&lt;/code&gt; with...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const main = async () =&amp;gt; {
    const users = await Promise.all(arrayOfPromises);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other option is to use &lt;code&gt;await&lt;/code&gt; in an &lt;code&gt;async&lt;/code&gt; function and actually &lt;code&gt;await&lt;/code&gt; each response.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;const getUser = async (name) =&amp;gt; {
  const response = await fetch(`https://api.github.com/users/${name}`);
  const json = await response.json();
  return json;
};

const getUsers = async () =&amp;gt; {
    const users = [];
    const usernames = ['jcreamer898', 'kwelch', 'AlexSwensen'];

    for (const name of usernames) {
      const user = await getUser(name);
      users.push(user);
    }

    return users;
};

const main = async () =&amp;gt; {
  await getUsers();
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case the code will pause and wait for each &lt;code&gt;getUser&lt;/code&gt; response to come back before moving on to the next one.&lt;/p&gt;

&lt;p&gt;Here is a code sandbox where you can see all of this running!&lt;/p&gt;

&lt;p&gt;&amp;lt;!--kg-card-begin: html--&amp;gt;&amp;lt;!--kg-card-end: html--&amp;gt;&lt;/p&gt;

&lt;p&gt;Hopefully this article helps clear up any confusion in &lt;code&gt;for of&lt;/code&gt; loops going forward.&lt;/p&gt;

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