<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Joakim</title>
    <description>The latest articles on DEV Community by Joakim (@joakimdevelops).</description>
    <link>https://dev.to/joakimdevelops</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%2F388641%2F3dc48304-9270-482c-8f6c-e76a430419fc.png</url>
      <title>DEV Community: Joakim</title>
      <link>https://dev.to/joakimdevelops</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joakimdevelops"/>
    <language>en</language>
    <item>
      <title>10 Things 2020 has taught me</title>
      <dc:creator>Joakim</dc:creator>
      <pubDate>Tue, 16 Mar 2021 12:48:51 +0000</pubDate>
      <link>https://dev.to/joakimdevelops/10-things-2020-has-taught-me-nfj</link>
      <guid>https://dev.to/joakimdevelops/10-things-2020-has-taught-me-nfj</guid>
      <description>&lt;p&gt;&lt;strong&gt;2020 started out rough for a lot of us.&lt;/strong&gt; Most of us moved out of the office, and into our couches, kitchens, closets, or otherwise improvised office areas. Whereas you might have lost some precious moments in your car or the gratuitous sneeze-in-your-face on the commute, most of us gained something far more important; &lt;em&gt;Time&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;I have tried my best to put this time to use as best I can. Whether practicing inversions on the piano, getting that extra hour of exercise, or scrolling through whatever blogs and articles I could find that seemed like my cup of tea.&lt;/p&gt;

&lt;p&gt;I also dedicated some of this time to document things I have learned during the day. Whenever I found something, learned something new or otherwise gained insight or knowledge into an area I deemed relevant to my professional field, I would make a note of it, and when given the opportunity, test it out for myself and detail my findings and sharing them.&lt;/p&gt;

&lt;p&gt;This could be anything from finding a new useful code snippet to gaining insight into a whole new concept or paradigm. Today I want to share with you some of my favorites from this list, and I hope you will enjoy and be inspired to take this path for yourself.&lt;/p&gt;

&lt;p&gt;I am focusing exclusively on &lt;strong&gt;JavaScript&lt;/strong&gt; for this article. I have learned other things as well, but I think the core audience would not deem my aspirations for lego, piano nor amateur furniture builds relevant. That being said, this is starting to feel like one of those recipe introductions that describes the soups' relationship to Napoleon's great-grandfather. Just give me soup?&lt;/p&gt;

&lt;p&gt;Soups, ahoy. Without further ado, here are some excerpts, and my favorite things, that I learned during 2020, in the order that I learned them.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Array.sort() behaves differently across browsers
&lt;/h3&gt;

&lt;p&gt;This is more of a mistake that I scratched my head over for a long time earlier this past spring. Consider the following:&lt;/p&gt;

&lt;p&gt;When sorting an array, me, and probably a lot of other people, fell into the trap of using this simple callback: &lt;code&gt;sort((x,y) =&amp;gt; x &amp;lt; y))&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;However, when running this on a simple example. We get the following in Chrome and Firefox respectively:&lt;/p&gt;

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

&lt;p&gt;The comparison callback that &lt;code&gt;sort()&lt;/code&gt; accepts must return either &lt;code&gt;1&lt;/code&gt;, &lt;code&gt;0&lt;/code&gt; or &lt;code&gt;-1&lt;/code&gt;. Since our callback returns neither, but rather booleans. The different implementations of javascript across these browsers seem to have their own quirks in how they interpret these booleans.&lt;/p&gt;

&lt;p&gt;So while Firefox for example seem to accept, or rather interpret, booleans as &lt;code&gt;1&lt;/code&gt; and &lt;code&gt;-1&lt;/code&gt; respectively, there is no guarantee that other browsers do the same thing, or even that Firefox itself will continue to do so in the future.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Joakim does not accurately read Array documentation. Do not be like Joakim. Read the documentation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Chrome also used to implement different sorting algorithms &lt;a href="https://bugs.chromium.org/p/v8/issues/detail?id=90#c24" rel="noopener noreferrer"&gt;depending on the size of the array&lt;/a&gt; although this has since been changed to always use a &lt;strong&gt;stable&lt;/strong&gt; sorting algorithm.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort" rel="noopener noreferrer"&gt;Read more about .sort()&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  2. JSON.stringifys optional replacer argument.
&lt;/h3&gt;

&lt;p&gt;Everyone and their mother who has ever dabbled in web development have, or will, at some point used &lt;code&gt;JSON.stringify&lt;/code&gt;. But this year it dawned on me the second argument to this function: &lt;code&gt;replacer&lt;/code&gt;. Which can be used as a sort of whitelist for key value pairs when parsing JSON.&lt;/p&gt;

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

&lt;p&gt;BUT replacer can also be a function, which might be used to validate, replace or parse (or anything else under the sun. Creativity hat on, gals and guys) the JSON key value pairs.&lt;/p&gt;

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

&lt;p&gt;This comes with a slight hit to performance, as you can see for yourself in &lt;a href="https://perf.link/#eyJpZCI6ImNveW1mczIzYjduIiwidGl0bGUiOiJKU09OLnN0cmluZ2lmeSgpIHJlcGxhY2VyIGFyZ3VtZW50IGJlbmNobWFyayIsImJlZm9yZSI6ImNvbnN0IGRhdGEgPSB7b25lOiBcIm9uZVwiLCB0d286IDIsIHRocmVlOiBcInRocmVlXCIsIGZvdXI6IFwiZm91clwiLCBmaXZlOiA1fSIsInRlc3RzIjpbeyJuYW1lIjoiU3RyaW5naWZ5IHdpdGhvdXQgcmVwbGFjZXIiLCJjb2RlIjoiSlNPTi5zdHJpbmdpZnkoZGF0YSkiLCJydW5zIjpbNjY4MDAwLDY4MzAwMCw4ODUwMDAsMjUxMDAwLDkwMDAsMjAwMDAwLDI3MTAwMCw3MzQwMDAsMTY3MDAwLDI4ODAwMCwyODMwMDAsMjEwMDAsNTg0MDAwLDQ1MDAwLDEwMDAwLDQzODAwMCw5MDAwLDk1MDAwLDE0NTAwMCwxMTYwMDAsOTgwMDAsMTAwMDAsOTAwMCwzMzIwMDAsMjU3MDAwLDkwMDAsOTAwMCw0NTUwMDAsMjM0MDAwLDczMTAwMCw5MDAwLDI2NDAwMCw5MDAwLDUyMDAwMCwxMDAwMCw5MDAwLDcxMDAwLDgzNDAwMCw5MDAwLDc3MDAwLDkwMDAsNTc2MDAwLDE2MjAwMCw5MDAwLDkwMDAsODY1MDAwLDEwMDAwLDEwMDAwLDM0MDAwLDQ1MDAwLDY4MDAwLDIxNjAwMCw5MzkwMDAsOTAwMCwzNzYwMDAsMTk0MDAwLDIyNzAwMCw3MDAwLDI2MDAwMCwxMDAwMCw2MjUwMDAsOTAwMCw5ODAwMCwyNTkwMDAsMTU3MDAwLDEwMDAsOTAwMCwzNTEwMDAsMzAyMDAwLDEwMDAwLDE0MTAwMCwxNDc4MDAwLDE5MzAwMCw0OTYwMDAsMzg1MDAwLDU0NDAwMCwxNzEwMDAsOTAwMCw5MjAwMCw2NTQwMDAsMTI5MDAwLDkwMDAsMzc0MDAwLDEwMDAwLDk4MjAwMCwxNDcwMDAsMjIwMDAsMzA0MDAwLDU3NjAwMCwyMDAwLDExNTAwMCw1MTEwMDAsOTAwMCw1MzAwMCwxMDAwMCw5MDAwLDI2MDAwLDQwNzAwMCw2ODAwMCw3MjAwMF0sIm9wcyI6MjM3MTIwfSx7Im5hbWUiOiJTdHJpbmdpZnkgd2l0aCByZXBsYWNlciBhcyB3aGl0ZWxpc3QiLCJjb2RlIjoiSlNPTi5zdHJpbmdpZnkoZGF0YSwgW1wib25lXCIsIFwidGhyZWVcIiwgXCJmaXZlXCJdKSIsInJ1bnMiOls1MjIwMDAsNjgzMDAwLDcyNjAwMCwyMzYwMDAsOTAwMCwxNDIwMDAsMjMzMDAwLDAsMTI0MDAwLDI3MjAwMCwxMTEwMDAsMjkwMDAsNTQ1MDAwLDM3MDAwLDEwMDAsMzUxMDAwLDkwMDAsNDcwMDAsOTgwMDAsOTgwMDAsNjIwMDAsMTAwMDAsOTAwMCwyOTcwMDAsMTQ5MDAwLDYyOTAwMCw5MDAwLDE1OTAwMCwxODQwMDAsNTQ2MDAwLDkwMDAsMTg5MDAwLDkwMDAsNDUwMDAwLDEwMDAwLDkwMDAsMzYwMDAsMCwzNDQwMDAsNTYwMDAsOTAwMCwzODMwMDAsOTQwMDAsOTUyMDAwLDk5MDAwLDY5NzAwMCwxMDAwMCwxMDAwMCw0MDAwMCw0MTAwMCw0NzAwMCwyMDAwMDAsNzczMDAwLDkwMDAsMzE3MDAwLDE2MjAwMCwxNjAwMDAsODU5MDAwLDE5MDAwMCw5MDAwLDUxODAwMCwxMDAwMCw5ODAwMCwxMDAwMCw5ODAwMCwxMTEwMDAsOTAwMCwzNzAwMDAsMTkwMDAwLDkwMDAsOTkwMDAsOTAwMCwxNTYwMDAsNDU5MDAwLDMzNjAwMCw1MjUwMDAsMTE3MDAwLDEwMDAwLDYzMDAwLDYwNjAwMCwxMTAwMDAsOTAwMCwzMzEwMDAsOTAwMCw5MDAwLDEyMDAwMCwzNDAwMCwzMDQwMDAsNDc1MDAwLDEwMDAsOTAwMDAsNDE0MDAwLDgzMDAwLDkwMDAsMzUwMDAwLDMwMjAwMCwxODAwMCwzNjkwMDAsODI4MDAwLDEwMDAwXSwib3BzIjoyMDE3ODB9LHsibmFtZSI6IlN0cmluZ2lmeSB3aXRoIHJlcGxhY2VyIGNhbGxiYWNrIiwiY29kZSI6IkpTT04uc3RyaW5naWZ5KGRhdGEsICh2YWwpID0%2BIE51bWJlci5pc0ludGVnZXIodmFsKSA%2FIHZhbC50b1N0cmluZygpIDogdmFsKSIsInJ1bnMiOlsxMDQ1MDAwLDY2MjAwMCw1MzMwMDAsMTAwMCw5MDAwLDEwMDAwMCwxOTgwMDAsNDEwMDAsMTAwMDAwLDE3MDAwLDIyMDAwMCwxMTAwMCwxMTAwMCwwLDcwMDAsMzE1MDAwLDg1NDAwMCw1MDAwMCw5MDAwLDUzMDAwLDEzMDAwLDkwMDAsMTAwMDAsMjAzMDAwLDE1OTAwMCw5MDAwLDkwMDAsNzMwMDAsMTc0MDAwLDUwNzAwMCw5MDAwLDE4NjAwMCw1OTUwMDAsNDEyMDAwLDkwMDAsOTAwMCwxMDAwMCw2MTcwMDAsMTk2MDAwLDM3MDAwLDkwMDAsMzg2MDAwLDc5MDAwLDAsMTEwMDAsMCwxMDAwMCwxMzAwMCwzNDIwMDAsMTAwMCwyODAwMCw3NjAwMDAsNzI5MDAwLDkwMDAsMTU2MDAwLDM4MDAwLDEzMzAwMCwwLDk4MDAwLDkwMDAsNDg5MDAwLDEwMDAwLDYyMzAwMCwxMTAwMCwxMDAwMDAsMjcwMDAsMTAwMCwyODAwMDAsMTAwMDAsMTAwMDAsNTEwMDAsMTAwODAwMCw0OTAwMCw0NDMwMDAsMjk5MDAwLDI1OTAwMCwxMTQwMDAsMTcwMDAsMTkyMDAwLDU0NjAwMCwxMjIwMDAsMTAwMCwzMDMwMDAsOTAwMCw5MDAwLDEwMDAwMCwxMTAwMCwyMTQwMDAsNDM0MDAwLDEwMDAsNzYwMDAsMjk3MDAwLDUwMDAwLDMxNTAwMCwxMDAwLDkwMDAsOTAwMCwyMzEwMDAsMzIwMDAsNTgwMDAwXSwib3BzIjoxNzYzNjB9XSwidXBkYXRlZCI6IjIwMjEtMDMtMTBUMDg6Mzc6MjYuMDEzWiJ9" rel="noopener noreferrer"&gt;these benchmarks&lt;/a&gt;, but for the average usecase it should not be a significant difference.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify" rel="noopener noreferrer"&gt;Read more about JSON.stringify()&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  3. Array.filter() does not work with Promises
&lt;/h3&gt;

&lt;p&gt;I tend to work a lot with array methods. A really common pattern would be: Perform a number of asynchronous operations, iterate over said operations to manipulate the data &amp;amp; filter out unwanted things.&lt;/p&gt;

&lt;p&gt;I first ran in to this during the summer, when in my project, we used a function to check the users access levels, when performing certain operations. Let's call it &lt;code&gt;userCan&lt;/code&gt;. By having this function return true or false, it could seamlessly be used as a &lt;code&gt;filter&lt;/code&gt; callback to determine whether the user had relevant permissions for any given set of actions.&lt;/p&gt;

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

&lt;p&gt;Consider &lt;code&gt;actions&lt;/code&gt; a batch of requests the user has made. We need to make sure only the actions the user has permission to do gets executed. Simplified code, but you get the gist:&lt;/p&gt;

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

&lt;p&gt;Short and sweet. But what happens when we introduce asynchronous operations in &lt;code&gt;userCan&lt;/code&gt;?&lt;/p&gt;

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

&lt;p&gt;Suddenly every user action is allowed! The user should not have permission to &lt;code&gt;DROP_DATABASE&lt;/code&gt;. Why is this happening?&lt;/p&gt;

&lt;p&gt;Well, Unfortunately &lt;code&gt;Array.filter()&lt;/code&gt; is a synchronous function, and therefore does not support Promises. Due to this, &lt;code&gt;filter()&lt;/code&gt; will not await &lt;code&gt;userCan&lt;/code&gt; to resolve a value, but just accept the Promise as a truthy value.&lt;/p&gt;

&lt;p&gt;To get around this, we need to get a bit creative. There are a few ways to work around this, the most common, and the way I would recommend, would be to use &lt;code&gt;.map()&lt;/code&gt; in conjunction with &lt;code&gt;.filter()&lt;/code&gt;.&lt;/p&gt;

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

&lt;p&gt;What we are doing here is using the asynchronous supported &lt;code&gt;.map()&lt;/code&gt; to check the given predicate, and when all Promises has resolved, filter out the falsy values from the resulting array.&lt;/p&gt;

&lt;p&gt;You could also do this with &lt;code&gt;.reduce()&lt;/code&gt;, but I find it a bit more convoluted.&lt;/p&gt;

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

&lt;p&gt;Neat, ain't it?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter" rel="noopener noreferrer"&gt;Read more about .filter()&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Nullish coalescing vs the logical OR operator
&lt;/h3&gt;

&lt;p&gt;A lot of people, myself included, probably feel very familiar writing something like the following, to have a fallback in case &lt;code&gt;baz&lt;/code&gt; is &lt;code&gt;undefined&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;const foo = baz || "fallback"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;code&gt;||&lt;/code&gt; checks for falsy values such as &lt;code&gt;false&lt;/code&gt;, &lt;code&gt;null&lt;/code&gt; and &lt;code&gt;0&lt;/code&gt;. But there might be cases where you need to treat &lt;code&gt;0&lt;/code&gt; as an actual value, or otherwise more explicitly handle nullish values.&lt;/p&gt;

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

&lt;p&gt;Nullish coalescing differs from &lt;code&gt;||&lt;/code&gt; in that it only returns it's right-hand side operand when its left-hand side value is &lt;code&gt;null&lt;/code&gt; or &lt;code&gt;undefined&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Nullish coalescing was introduced in TypeScript as of &lt;strong&gt;version 3.7&lt;/strong&gt; and is currently supported in the latest version of all major browsers and &lt;strong&gt;Node.js 14&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing_operator" rel="noopener noreferrer"&gt;More about Nullish Coalescing here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  5. Console.table()
&lt;/h3&gt;

&lt;p&gt;This blew my feeble mind when I ran into it the first time this summer. We're all experienced developers, so we use &lt;code&gt;console.log&lt;/code&gt; as frequently as possible as it is possibly the strongest debugging tool there is! Well, here I am to tell you, that  &lt;code&gt;console.table()&lt;/code&gt; exists and how great it is:&lt;/p&gt;

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

&lt;p&gt;Whenever you're working with long arrays of  objects, this can be a lifesaver.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Console/table" rel="noopener noreferrer"&gt;More about console.table() here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  6. The Promise constructor anti-pattern
&lt;/h3&gt;

&lt;p&gt;The Promise constructor anti-pattern, or the deferred anti-pattern, refers to creating new objects, or in this case new Promises without reason. This is something I was very guilty of when I just started out as a junior developer and began delving into Promises.&lt;/p&gt;

&lt;p&gt;It complicates code and prevents rejections and errors from being properly propagated.&lt;/p&gt;

&lt;p&gt;I didn't know this was a recognized anti-pattern, and I myself just kind of naturally removed myself from the habit, until I learned more about it this year. It's easy to fall into this kind of way of working when you're new to Promises, and might not know that performing asynchronous operations already returns a Promise, which you in turn can chain.&lt;/p&gt;

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

&lt;p&gt;Rather than explicitly creating a new Promise, it is adviced to just use the original one returned from the async function we are calling in the first place:&lt;/p&gt;

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

&lt;p&gt;Doesn't that look a lot prettier?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/23803743/what-is-the-explicit-promise-construction-antipattern-and-how-do-i-avoid-it" rel="noopener noreferrer"&gt;Read more about the Promise constructor anti-pattern here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  7. Catch awaited errors
&lt;/h3&gt;

&lt;p&gt;Now to something a little more bite sized. We all know you handle resolved and rejected promises by using &lt;code&gt;then&lt;/code&gt; and &lt;code&gt;catch&lt;/code&gt;. But if you want to catch an error using &lt;strong&gt;async/await&lt;/strong&gt; you, to my knowledge, needed to wrap it in a &lt;em&gt;try/catch&lt;/em&gt; block, like so:&lt;/p&gt;

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

&lt;p&gt;But to my own amusement and amazement, I recently found that you can in fact use &lt;code&gt;.catch()&lt;/code&gt; on awaited Promises.&lt;/p&gt;

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

&lt;p&gt;Granted, this makes a lot of sense when you think about it, given that async/await is really just syntactic sugar on top of Promises.&lt;/p&gt;

&lt;p&gt;That being said, one might present the argument that one should stick to one convention or the other, and while I would usually agree with this sentiment, I just find it really handy in some cases. &lt;strong&gt;What do you think?&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  8. Using optional chaining for function calls.
&lt;/h3&gt;

&lt;p&gt;This might be common knowledge, and as someone who rigorously uses optional chaining, I wonder why it never occurred to me to try this; You can use optional chaining for function calls?&lt;/p&gt;

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

&lt;p&gt;It's beautiful.. And often comes in handy when working with React components for instance, which may or may not have event handlers such as &lt;code&gt;onClick&lt;/code&gt;. No more &lt;code&gt;onClick={onClick &amp;amp;&amp;amp; () =&amp;gt; onClick(param)}&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining" rel="noopener noreferrer"&gt;Learn more about optional chaining here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  9. Utilizing Web Workers
&lt;/h3&gt;

&lt;p&gt;JavaScript run-times are single-threaded environments, meaning code executions within a program can not be run in parallel, in contrast to for example Java and C#. This means that it's code execution by nature is &lt;em&gt;blocking&lt;/em&gt;. We have to wait for one piece of code to finish, before moving on to the next.&lt;/p&gt;

&lt;p&gt;Not to be confused with Promises, or &lt;a href="https://nodejs.org/api/child_process.html" rel="noopener noreferrer"&gt;Node.js Child Processes&lt;/a&gt;, &lt;strong&gt;Web Workers&lt;/strong&gt; are a means to bring this multi-threaded behaviour to JavaScript. They can be utilized for a multitude of things, but probably most commonly used to delegate CPU intensive tasks to other threads, preventing long interruptions and user interface blockers. &lt;/p&gt;

&lt;p&gt;Similar to event listeners and &lt;code&gt;Socket.io&lt;/code&gt;, workers communicate with each other using a messaging system and is very simple to get up and running.&lt;/p&gt;

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

&lt;p&gt;For the worker to listen and respond to the messages sent by the main thread, we just need to define the &lt;code&gt;onmessage&lt;/code&gt; handler and we're good to go.&lt;/p&gt;

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

&lt;p&gt;All we need to do now is make sure our main thread has some way to handle the messages sent back by our worker.&lt;/p&gt;

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

&lt;p&gt;While Web Workers can be very useful, they do come with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Functions_and_classes_available_to_workers#APIs_available_in_workers" rel="noopener noreferrer"&gt;some limitations&lt;/a&gt;, such as not having access to the DOM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers" rel="noopener noreferrer"&gt;Read more about Web Workers here&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  10. Not depending on dependencies
&lt;/h3&gt;

&lt;p&gt;Last, but not least, I want to give this honorary position in the list to one thing that probably taught me the most during this year.&lt;/p&gt;

&lt;p&gt;Earlier last spring, &lt;strong&gt;Deno&lt;/strong&gt; launched version 1.0 with an array of interesting features. Deno is a new, secure JavaScript and TypeScript runtime by Node.js creator &lt;a href="https://github.com/ry" rel="noopener noreferrer"&gt;Ryan Dahl (ry)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I'm not going to go deep into Deno here, but &lt;a href="https://deno.land" rel="noopener noreferrer"&gt;here&lt;/a&gt;'s a link if you want to learn more about it.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Me, being an avid Node.js engineer, jumped at the opportunity to discover what it can do. I dedicated a weekend to trying to write a file- &amp;amp; web server that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Has live reload&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports client routing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Requires zero configuration..&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;.. and at the same time being &lt;strong&gt;completely dependency free&lt;/strong&gt;. Meaning no third-party packages can be used. The resulting project is called &lt;a href="https://github.com/joakimunge/denoliver" rel="noopener noreferrer"&gt;Denoliver&lt;/a&gt;, and I went on to release version 2.0 later in 2020.&lt;/p&gt;

&lt;p&gt;I learned an absolute truckload &lt;em&gt;(no swearing here!)&lt;/em&gt; from this experiment. There's something highly intriguing having to solve problems most commonly solved with &lt;code&gt;npm install solution&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;I cannot recommend this approach enough. It really was an amazing journey. If you want to check out the project yourself for inspiration, or to contribute, you can find it &lt;a href="https://github.com/joakimunge/denoliver" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/joakimunge" rel="noopener noreferrer"&gt;
        joakimunge
      &lt;/a&gt; / &lt;a href="https://github.com/joakimunge/denoliver" rel="noopener noreferrer"&gt;
        denoliver
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      A simple, dependency free static file server for Deno with possibly the worst name ever.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;p&gt;
  &lt;a rel="noopener noreferrer" href="https://github.com/joakimunge/denolivermedia/denoliver_2.png"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fjoakimunge%2Fdenolivermedia%2Fdenoliver_2.png" title="Denoliver" alt="It's a liver" width="320"&gt;&lt;/a&gt;
&lt;/p&gt;
&lt;p&gt;
&lt;a href="https://github.com/joakimunge/denoliver/actions" rel="noopener noreferrer"&gt;
&lt;img src="https://camo.githubusercontent.com/9851ea73c8dafb302bbeea99e1d1990f42af950fc8da8354ddde5e3144ccd8e6/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f776f726b666c6f772f7374617475732f6a6f616b696d756e67652f64656e6f6c697665722f63693f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
&lt;a href="https://github.com/joakimunge/denoliver/releases" rel="noopener noreferrer"&gt;
&lt;img src="https://camo.githubusercontent.com/856765ab2ff0a768f62196f69251c06e246f553105a365de30aad30ba835c8cf/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f6a6f616b696d756e67652f64656e6f6c697665723f7374796c653d666f722d7468652d6261646765"&gt;&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Denoliver&lt;/strong&gt; is a small, zero config dev &amp;amp; static file server with live reloading written in TypeScript for Deno intended for prototyping and Single Page Applications.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Prerequisites&lt;/h2&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;To run this you need to have &lt;a href="https://deno.land/" rel="nofollow noopener noreferrer"&gt;Deno&lt;/a&gt; 1.0 or later installed.&lt;/h3&gt;
&lt;/div&gt;

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

&lt;ul&gt;
&lt;li&gt;Dependency free! No third party dependencies.&lt;/li&gt;
&lt;li&gt;Live reload&lt;/li&gt;
&lt;li&gt;Supports client side routing for Single Page Applications.&lt;/li&gt;
&lt;li&gt;Directory lists&lt;/li&gt;
&lt;li&gt;Supports HTTPS&lt;/li&gt;
&lt;li&gt;Allows for programmatic use as a module&lt;/li&gt;
&lt;li&gt;Boilerplating for rapid prototyping.&lt;/li&gt;
&lt;li&gt;Injectable HTTP request interceptors. (TS &amp;amp; JS)&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;

&lt;p&gt;Install as a Deno executable.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE: Deno is a secure runtime by default. You need to include the &lt;code&gt;--allow-net&lt;/code&gt;, &lt;code&gt;--allow-read&lt;/code&gt; and &lt;code&gt;--allow-write&lt;/code&gt; flags to make sure Denoliver can serve your directory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ deno install --allow-net --allow-read --allow-write --allow-run https://deno.land/x/denoliver/mod.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;or if you're not happy with the name:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;&lt;pre class="notranslate"&gt;&lt;code&gt;$ deno install -n whateverNameYouWant --allow-net --allow-read --allow-write --allow-run https://deno.land/x/denoliver/mod.ts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Why do I need the &lt;code&gt;--allow-run&lt;/code&gt; flag?&lt;/h2&gt;

&lt;/div&gt;

&lt;p&gt;&lt;em&gt;You don't need it!&lt;/em&gt;…&lt;/p&gt;
&lt;/div&gt;


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


&lt;h3&gt;
  
  
  Closing
&lt;/h3&gt;

&lt;p&gt;2020 has been an interesting time for everyone. I am very fortunate to be able to say that I have grown a lot during this time, and I have to give this small process a lot of credit as to why that is.&lt;/p&gt;

&lt;p&gt;It might seem like a peripheral thing, but I highly recommend taking a couple of minutes each day to reflect over what knowledge you have gained and jot it down in your medium of choice. Nothing is too big, or too small. By the end of the year, or possibly a lot sooner than that, you will be amazed with the knowledge you have gained.&lt;/p&gt;

&lt;p&gt;Hope you enjoyed the little tidbits of my journal today.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What have you learned this year?&lt;/strong&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>todayilearned</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Denoliver - I created a small, dependency free, live-reload file server for Deno</title>
      <dc:creator>Joakim</dc:creator>
      <pubDate>Mon, 18 May 2020 13:51:49 +0000</pubDate>
      <link>https://dev.to/joakimdevelops/denoliver-i-created-a-small-dependency-free-live-reload-file-server-for-deno-2e7b</link>
      <guid>https://dev.to/joakimdevelops/denoliver-i-created-a-small-dependency-free-live-reload-file-server-for-deno-2e7b</guid>
      <description>&lt;p&gt;I wanted to get into Deno and see what it had to offer during the weekend so I decided to write a &lt;a href="https://github.com/joakimunge/denoliver"&gt;small file server&lt;/a&gt; that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Is dependency free. (Meaning no third party dependencies/modules)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Has live reload&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports client routing&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Requires zero configuration&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Its purpose was mainly for me to learn how to work with the new runtime, but also to serve as a means of quickly get up and running with prototyping with new web prototypes.&lt;/p&gt;

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

&lt;p&gt;I'm currently working on improving it and adding a couple of other useful features like &lt;em&gt;HTTPS&lt;/em&gt;, &lt;em&gt;CORS&lt;/em&gt;, Optional entrypoints and a better file watcher.&lt;/p&gt;

&lt;p&gt;If you want to try it out for yourself, complain about the name or logo, or simply want to contribute you can find the project &lt;a href="https://github.com/joakimunge/denoliver"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/joakimunge/denoliver"&gt;Denoliver&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Big thanks to &lt;a href="https://twitter.com/lukejacksonn"&gt;Luke Jacksson&lt;/a&gt;. This project was heavily inspired by his &lt;a href="https://github.com/lukejacksonn/servor"&gt;Servor&lt;/a&gt;&lt;/p&gt;

</description>
      <category>deno</category>
      <category>opensource</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
