<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Posts on Abhijit Hota</title>
    <link>https://abhijithota.com/posts/</link>
    <description>Recent posts on Abhijit Hota</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Wed, 12 Jun 2024 14:41:53 +0000</lastBuildDate><atom:link href="https://abhijithota.com/posts/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Vanity import paths in Go using Caddy</title>
      <link>https://abhijithota.com/posts/golang-vanity-urls-using-caddy/</link>
      <pubDate>Wed, 12 Jun 2024 14:41:53 +0000</pubDate>
      
      <guid>https://abhijithota.com/posts/golang-vanity-urls-using-caddy/</guid>
      <description>&lt;p&gt;I recently published a &lt;a href=&#34;go.abhijithota.com/modfmt&#34;&gt;small Go tool&lt;/a&gt; and wanted to publish it on my own domain like &lt;code&gt;go.abhijithota.com/modfmt&lt;/code&gt; (instead of &lt;code&gt;github.com/abhijit-hota/modfmt&lt;/code&gt;) leveraging &lt;a href=&#34;https://sagikazarmark.hu/blog/vanity-import-paths-in-go/&#34;&gt;&amp;ldquo;vanity&amp;rdquo; import paths&lt;/a&gt;. Since I already had a small VPS running Caddy, I thought it would be neat to make it work for this.&lt;/p&gt;
&lt;h2 id=&#34;vanity-import-paths&#34;&gt;Vanity import paths&lt;/h2&gt;
&lt;p&gt;When you download a module via &lt;code&gt;go get&lt;/code&gt; or &lt;code&gt;go install&lt;/code&gt;, if the import URL is not a &lt;a href=&#34;https://pkg.go.dev/cmd/go#hdr-Remote_import_paths&#34;&gt;known VCS provider&lt;/a&gt;, it requests the URL over HTTPS/HTTP and expects an HTML response with a specific &lt;code&gt;meta&lt;/code&gt; tag in the &lt;code&gt;head&lt;/code&gt; which looks like:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff79c6&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;go-import&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&amp;lt;import-prefix&amp;gt; &amp;lt;vcs&amp;gt; &amp;lt;repo-root&amp;gt;&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So for a package called &lt;code&gt;go.abhijithota.com/modfmt&lt;/code&gt; whose source code is hosted at a GitHub repo (&lt;code&gt;https://github.com/abhijit-hota/modfmt&lt;/code&gt;), the &lt;code&gt;meta&lt;/code&gt; tag would be:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff79c6&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;go-import&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;go.abhijithota.com/modfmt git https://github.com/abhijit-hota/modfmt&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;using-caddy-to-make-the-vanity-url-work&#34;&gt;Using Caddy to make the vanity URL work&lt;/h2&gt;
&lt;p&gt;The bare minimum thing you need to do is handle a specific path on your domain or subdomain to respond with the relevant HTML with the &lt;code&gt;meta&lt;/code&gt; tag. Your Caddyfile would look something like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Caddy&#34; data-lang=&#34;Caddy&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;go.abhijithota.com&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;header&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;Content-Type&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;text/html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; /modfmt {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;respond&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;lt;&amp;lt;HTML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;!DOCTYPE&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;meta&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;name=&amp;#34;go-import&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;content=&amp;#34;go.abhijithota.com/modfmt&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;git&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;https://github.com/abhijit-hota/modfmt&amp;#34;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;HTML&lt;/span&gt; &lt;span style=&#34;color:#bd93f9&#34;&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;redir&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;https://abhijithota.com&lt;/span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt; # or wherever you want to
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;&lt;/span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This gives you a working vanity URL which you can use to install and get modules from.&lt;/p&gt;
&lt;h3 id=&#34;distinguishing-requests-from-go&#34;&gt;Distinguishing requests from Go&lt;/h3&gt;
&lt;p&gt;Go appends a &lt;code&gt;?go-get=1&lt;/code&gt; query parameter to the HTTPS request so that we can distinguish between normal queries and queries from the Go tools (&lt;code&gt;go get&lt;/code&gt;, etc.). We can use this to distinguish between what to do when someone visits the URL via a browser, etc. For instance, we can choose to redirect to our original GitHub page:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Caddy&#34; data-lang=&#34;Caddy&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;go.abhijithota.com&lt;/span&gt; {&lt;span style=&#34;color:#6272a4&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;    # For path /modfmt
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;&lt;/span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; /modfmt {&lt;span style=&#34;color:#6272a4&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;        # Check if the request has a ?go-get=1 appended by Go
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;@from_go&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;query&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;go-get=1&lt;/span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;        # If yes, then send back the required HTML
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;@from_go&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;header&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;Content-Type&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;text/html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;respond&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;lt;&amp;lt;HTML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;!DOCTYPE&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;meta&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;name=&amp;#34;go-import&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;content=&amp;#34;go.abhijithota.com/modfmt&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;git&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;https://github.com/abhijit-hota/modfmt&amp;#34;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;HTML&lt;/span&gt; &lt;span style=&#34;color:#bd93f9&#34;&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        }&lt;span style=&#34;color:#6272a4&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;        # If not, then redirect to our GitHub repo
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;&lt;/span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;redir&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;https://github.com/abhijit-hota/modfmt&lt;/span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt; # You can also redirect to the pkg.go.dev page for the module
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;&lt;/span&gt;        }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;redir&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;https://abhijithota.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The order of Caddy&amp;rsquo;s &lt;code&gt;handle&lt;/code&gt; directives act like a fallthrough. If the first one is not matched then the next one is checked and so on. In the above case, we check the request for a &lt;code&gt;?go-get=1&lt;/code&gt; query parameter using a named matcher. If the match is successful then we send the HTML required. If it isn&amp;rsquo;t, then the next in chain is used. Here, we have a &lt;code&gt;handle&lt;/code&gt; which basically matches everything. In our case, we redirect to GitHub&lt;/p&gt;
&lt;p&gt;We should also probably not leave the HTML page blank. The easiest thing to do here is use a &lt;code&gt;http-equiv=&amp;quot;refresh&amp;quot;&lt;/code&gt; to redirect to your GitHub repo:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-html&#34; data-lang=&#34;html&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;&lt;span style=&#34;color:#ff79c6&#34;&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;&lt;span style=&#34;color:#ff79c6&#34;&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff79c6&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;name&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;go-import&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;go.abhijithota.com/modfmt git https://github.com/abhijit-hota/modfmt&amp;#34;&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &amp;lt;&lt;span style=&#34;color:#ff79c6&#34;&gt;meta&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;http-equiv&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;refresh&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;content&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;0; url=https://github.com/abhijit-hota/modfmt&amp;#34;&lt;/span&gt; /&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &amp;lt;/&lt;span style=&#34;color:#ff79c6&#34;&gt;head&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&amp;lt;/&lt;span style=&#34;color:#ff79c6&#34;&gt;html&lt;/span&gt;&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Go to &lt;a href=&#34;https://go.abhijithota.com/modfmt?go-get=1&#34;&gt;https://go.abhijithota.com/modfmt?go-get=1&lt;/a&gt; to see the redirect in action.&lt;/p&gt;
&lt;p&gt;If you don&amp;rsquo;t want to redirect, you can write some basic HTML and CSS with the repo and docs URL and the installation instructions. At that point you might want to serve an HTML file directly.&lt;/p&gt;
&lt;h2 id=&#34;generalizing-our-setup&#34;&gt;Generalizing our setup&lt;/h2&gt;
&lt;p&gt;We don&amp;rsquo;t want to repeat the &lt;code&gt;handle /modfmt&lt;/code&gt; block every time we want to publish a package. We can leverage Caddy&amp;rsquo;s &lt;a href=&#34;https://caddyserver.com/docs/caddyfile/concepts#snippets&#34;&gt;snippets&lt;/a&gt; and &lt;a href=&#34;https://caddyserver.com/docs/caddyfile/directives/import&#34;&gt;&lt;code&gt;import&lt;/code&gt;&lt;/a&gt; directive to repeat the same pattern for a number of packages.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Caddy&#34; data-lang=&#34;Caddy&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;(gomodhandler) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; /{args[0]} {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;@from_go&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;query&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;go-get=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;@from_go&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;header&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;Content-Type&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;text/html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;respond&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;lt;&amp;lt;HTML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;!DOCTYPE&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;meta&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;name=&amp;#34;go-import&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;content=&amp;#34;go.abhijithota.com/&lt;/span&gt;{&lt;span style=&#34;color:#f1fa8c&#34;&gt;args[0&lt;/span&gt;]} &lt;span style=&#34;color:#f1fa8c&#34;&gt;git&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;https://github.com/abhijit-hota/&lt;/span&gt;{&lt;span style=&#34;color:#f1fa8c&#34;&gt;args[0&lt;/span&gt;]}&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;meta&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;http-equiv=&amp;#34;refresh&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;content=&amp;#34;0;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;url=https://github.com/abhijit-hota/&lt;/span&gt;{&lt;span style=&#34;color:#f1fa8c&#34;&gt;args[0&lt;/span&gt;]}&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;HTML&lt;/span&gt; &lt;span style=&#34;color:#bd93f9&#34;&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;redir&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;https://github.com/abhijit-hota/&lt;/span&gt;{&lt;span style=&#34;color:#f1fa8c&#34;&gt;args[0&lt;/span&gt;]}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;go.abhijithota.com&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; gomodhandler &lt;span style=&#34;color:#ff79c6&#34;&gt;modfmt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; gomodhandler &lt;span style=&#34;color:#ff79c6&#34;&gt;foo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ff79c6&#34;&gt;redir&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;https://abhijithota.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above Caddyfile introduces a snippet called &lt;code&gt;gomodhandler&lt;/code&gt; which is basically the same &lt;code&gt;/modfmt&lt;/code&gt; handler as we saw before but replaced with arguments. Think about it as a way to template the configuration from the configuration itself. When you &lt;code&gt;import&lt;/code&gt; a snippet, that snippet gets &lt;em&gt;inlined&lt;/em&gt; with the given arguments.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;For comparison, here is the same configuration without snippets:&lt;/p&gt;
&lt;details&gt;
&lt;summary&gt;&lt;strong&gt;Caddyfile&lt;/strong&gt;&lt;/summary&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-Caddy&#34; data-lang=&#34;Caddy&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;font-weight:bold&#34;&gt;go.abhijithota.com&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; /modfmt {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;@from_go&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;query&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;go-get=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;@from_go&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;header&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;Content-Type&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;text/html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;respond&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;lt;&amp;lt;HTML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;!DOCTYPE&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;meta&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;name=&amp;#34;go-import&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;content=&amp;#34;go.abhijithota.com/modfmt&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;git&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;https://github.com/abhijit-hota/modfmt&amp;#34;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;meta&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;http-equiv=&amp;#34;refresh&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;content=&amp;#34;0;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;url=https://github.com/abhijit-hota/modfmt&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;HTML&lt;/span&gt; &lt;span style=&#34;color:#bd93f9&#34;&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;redir&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;https://github.com/abhijit-hota/modfmt&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; /foo {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;@from_go&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;query&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;go-get=1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;@from_go&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;header&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;Content-Type&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;text/html&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;respond&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;lt;&amp;lt;HTML&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;!DOCTYPE&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;meta&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;name=&amp;#34;go-import&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;content=&amp;#34;go.abhijithota.com/foo&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;git&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;https://github.com/abhijit-hota/foo&amp;#34;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;meta&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;http-equiv=&amp;#34;refresh&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;content=&amp;#34;0;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;url=https://github.com/abhijit-hota/foo&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;/&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;HTML&lt;/span&gt; &lt;span style=&#34;color:#bd93f9&#34;&gt;200&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;redir&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;https://github.com/abhijit-hota/foo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;handle&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ff79c6&#34;&gt;redir&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;https://abhijithota.com&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/details&gt;
&lt;/blockquote&gt;
&lt;p&gt;This setup will have the following behavior for &lt;code&gt;modfmt&lt;/code&gt; and &lt;code&gt;foo&lt;/code&gt;:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Installing the module &lt;code&gt;go.abhijithota.com/&amp;lt;pkg&amp;gt;&lt;/code&gt; via &lt;code&gt;go get&lt;/code&gt; or &lt;code&gt;go install&lt;/code&gt; will install the module from the GitHub repo.&lt;/li&gt;
&lt;li&gt;Visiting &lt;code&gt;go.abhijithota.com/&amp;lt;pkg&amp;gt;&lt;/code&gt; will redirect to the respective GitHub repo.&lt;/li&gt;
&lt;li&gt;Visiting &lt;code&gt;go.abhijithota.com/&amp;lt;pkg&amp;gt;?go-get=1&lt;/code&gt; will return the HTML with the &lt;code&gt;meta&lt;/code&gt; tag and redirect to the respective GitHub repo due to the &lt;code&gt;http-equiv=&amp;quot;refresh&amp;quot;&lt;/code&gt; tag.&lt;/li&gt;
&lt;li&gt;Visiting any path on &lt;code&gt;go.abhijithota.com&lt;/code&gt; other than &lt;code&gt;modfmt&lt;/code&gt; or &lt;code&gt;foo&lt;/code&gt; will redirect to &lt;code&gt;abhijithota.com&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We are all set now to release our Go modules on our own domains or subdomains with vanity URLs.&lt;/p&gt;
&lt;h2 id=&#34;acknowledgement&#34;&gt;Acknowledgement&lt;/h2&gt;
&lt;p&gt;This post was inspired by &lt;a href=&#34;https://sagikazarmark.hu/blog/vanity-import-paths-in-go/&#34;&gt;Márk Sági-Kazár&amp;rsquo;s post&lt;/a&gt; on vanity import paths in Go which talks about their use-cases, using them effectively, best practices and much more in detail.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Method Middlewares with JavaScript Proxies</title>
      <link>https://abhijithota.com/posts/method-middlewares-with-javascript-proxies/</link>
      <pubDate>Fri, 17 May 2024 17:45:52 +0530</pubDate>
      
      <guid>https://abhijithota.com/posts/method-middlewares-with-javascript-proxies/</guid>
      <description>&lt;p&gt;You have an object that is a collection of methods:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; myFunctions &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    constant&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; (x) =&amp;gt; &lt;span style=&#34;color:#bd93f9&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    linear&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; (x) =&amp;gt; x,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    sine&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; (x) =&amp;gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Math&lt;/span&gt;.sin(&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Math&lt;/span&gt;.PI &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt; x),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cos&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; (x) =&amp;gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Math&lt;/span&gt;.cos(&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Math&lt;/span&gt;.PI &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt; x),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;};
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And you want to do the same operation based on the result of the methods:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; scaleToRange &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; (y, [yi, yf]) =&amp;gt; y &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt; (yf &lt;span style=&#34;color:#ff79c6&#34;&gt;-&lt;/span&gt; yi) &lt;span style=&#34;color:#ff79c6&#34;&gt;+&lt;/span&gt; yi;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; y &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; myFunctions.sine(x);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; yScaled &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; scaleToRange(y, [Y_MIN, Y_MAX]);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;No problem at all. 100/100 code. No notes. Commit. Push. Rejoice your life.&lt;/p&gt;
&lt;p&gt;But you slowly realize that you don&amp;rsquo;t want to see the unnecessary &lt;code&gt;yScaled&lt;/code&gt; declaration because it is not relevant to your function flow&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;. For whatever elitist reason that will make you feel like a better developer, you think that it&amp;rsquo;d better if you could just abstract this &lt;code&gt;scaleToRange&lt;/code&gt; function into the object itself.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;// Your dream code which is objectively worse
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; y &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; myFunctions.sine(x, [Y_MIN, Y_MAX]);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;You realize what you want is a &lt;strong&gt;middleware&lt;/strong&gt; to your method calls. So you resort to the obvious JavaScript abuse that you love doing so much:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; myFunctions &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Object&lt;/span&gt;.fromEntries(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Object&lt;/span&gt;.entries({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		constant&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; (x) =&amp;gt; &lt;span style=&#34;color:#bd93f9&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		linear&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; (x) =&amp;gt; x,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		sine&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; (x) =&amp;gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Math&lt;/span&gt;.sin(&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Math&lt;/span&gt;.PI &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt; x),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		cos&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; (x) =&amp;gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Math&lt;/span&gt;.cos(&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Math&lt;/span&gt;.PI &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt; x),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}).map(([key, fn]) =&amp;gt; [key, (x, [yi, yf]) =&amp;gt; (yf &lt;span style=&#34;color:#ff79c6&#34;&gt;-&lt;/span&gt; yi) &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt; fn(x) &lt;span style=&#34;color:#ff79c6&#34;&gt;+&lt;/span&gt; yi])
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Now there&amp;rsquo;s another problem. &amp;ldquo;3 iterations to declare the object?&amp;rdquo;, you scoff. Being a JavaScript developer, performance is of utmost priority to you. A dormant section in your brain lights up immediately. &amp;ldquo;Proxies!&amp;rdquo;, you exclaim, &amp;ldquo;aren&amp;rsquo;t they supposed to do something like this?&amp;rdquo;. A proxy technically is a middleware after all.&lt;/p&gt;
&lt;p&gt;You instinctively open your &lt;a href=&#34;https://developer.mozilla.org/en-US/&#34;&gt;Bible&lt;/a&gt; and lookup for the documentation on &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy&#34;&gt;JavaScript proxies&lt;/a&gt;, simultaneously fighting your sane sub-conscious thoughts, that are fragments of an article long forgotten about how you probably don&amp;rsquo;t need proxies.&lt;/p&gt;
&lt;p&gt;After a few minutes, you come up with this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; myFunctions &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Proxy&lt;/span&gt;(
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		constant&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; () =&amp;gt; &lt;span style=&#34;color:#bd93f9&#34;&gt;1&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		linear&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; (x) =&amp;gt; x,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		sine&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; (x) =&amp;gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Math&lt;/span&gt;.sin(&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Math&lt;/span&gt;.PI &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt; x),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		cos&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; (x) =&amp;gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Math&lt;/span&gt;.cos(&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Math&lt;/span&gt;.PI &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt; x),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		get&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; (target, key) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; fn &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; target[key];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; (x, [yi, yf]) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; y &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; fn(x);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;				&lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; (yf &lt;span style=&#34;color:#ff79c6&#34;&gt;-&lt;/span&gt; yi) &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt; y &lt;span style=&#34;color:#ff79c6&#34;&gt;+&lt;/span&gt; yi;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			};
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;blockquote&gt;
&lt;details open&gt;
&lt;summary&gt;&lt;strong&gt;Explanation&lt;/strong&gt;&lt;/summary&gt;
&lt;p&gt;A &lt;code&gt;Proxy&lt;/code&gt; in JavaScript is used to &lt;a href=&#34;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy#:~:text=intercept%20and%20redefine%20fundamental%20operations&#34;&gt;&lt;em&gt;intercept and redefine fundamental operations&lt;/em&gt;&lt;/a&gt; of an object that it wraps. It has two parameters. A &lt;code&gt;target&lt;/code&gt; - which is your original object you want to proxy stuff to and from. And a &lt;code&gt;handler&lt;/code&gt; - which is an object that contains how you proxy the target object. It returns the modified object.&lt;/p&gt;
&lt;p&gt;In the above code, we are creating a &lt;code&gt;Proxy&lt;/code&gt; object for the &lt;code&gt;myFunctions&lt;/code&gt; object. The &lt;code&gt;handler&lt;/code&gt; object has a &lt;code&gt;get&lt;/code&gt; method which is called whenever a property is accessed on the &lt;code&gt;myFunctions&lt;/code&gt; object. The &lt;code&gt;get&lt;/code&gt; method receives the &lt;code&gt;target&lt;/code&gt; object and the &lt;code&gt;key&lt;/code&gt; of the property that is being accessed. That enables us to &lt;em&gt;intercept&lt;/em&gt; the property access and manipulate it before returning it.&lt;/p&gt;
&lt;/details&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;p&gt;You hear Jerusalem bells ringing. The Roman cavalry choirs are singing. A portal opens up next to you. &lt;a href=&#34;https://youtu.be/sClk6aB_CPk&#34;&gt;Brendan Eich steps out and hands you a medal&lt;/a&gt;. You have done it. You commit your code and go to sleep. This high will help you fight your imposter syndrome for the next 3 days.&lt;/p&gt;
&lt;p&gt;This post has become annoyingly self-aware.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I realize that the given example flows pretty nicely. But in my actual use-case it felt out of place.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>my 2024 fumble list</title>
      <link>https://abhijithota.com/posts/my-2024-fumble-list/</link>
      <pubDate>Fri, 29 Dec 2023 14:48:55 +0530</pubDate>
      
      <guid>https://abhijithota.com/posts/my-2024-fumble-list/</guid>
      <description>&lt;h1 id=&#34;resolutions-2024&#34;&gt;resolutions 2024&lt;/h1&gt;
&lt;p&gt;i don&amp;rsquo;t write down resolutions every year. they are mostly just a background thought in my mind like &amp;ldquo;i should read more next year&amp;rdquo; or &amp;ldquo;i should release my projects next year&amp;rdquo;. this year i&amp;rsquo;m writing them down cause why not.&lt;/p&gt;
&lt;p&gt;most of these are increasing the things i enjoyed doing in 2023. some of these are stuff that can never happen (completing side projects) and some of these are totally new stuff that i want to try!&lt;/p&gt;
&lt;p&gt;here we go. no priority intended.&lt;/p&gt;
&lt;h2 id=&#34;consumption&#34;&gt;consumption&lt;/h2&gt;
&lt;h3 id=&#34;reading&#34;&gt;reading&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;read anything &lt;em&gt;properly&lt;/em&gt; everyday&lt;/p&gt;
&lt;p&gt;a good article, a short story, an essay, a poem, a chapter. anything. i&amp;rsquo;ve noticed i&amp;rsquo;m not good with books but i go through articles and short stories often. planning to add some more habit and structure to it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;books&lt;/p&gt;
&lt;p&gt;i miss how i used to read books. now i have a love hate relationship with them. i know i can&amp;rsquo;t hit these goals. but here we go.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;at least one book every 2 months ((re)starting slow!)&lt;/li&gt;
&lt;li&gt;try to complete books you thought to complete first&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;movies&#34;&gt;movies&lt;/h3&gt;
&lt;p&gt;i love movies. my movie watching habit came back in 2023. no goals other than just watch a lot of them. maybe a target of 150 is good. 100 is too easy (2 movies a week) and 200 is a little too hard (4 a week). so 3 movies a week it is.&lt;/p&gt;
&lt;p&gt;i wouldn&amp;rsquo;t mind if i don&amp;rsquo;t hit this target though as long as i&amp;rsquo;m content with the variety of movies i watch. happy ones, sad ones, funny ones, tragic ones, artsy ones, silly ones, old ones, new ones, good ones, bad ones, everything. except horror. it would be a cold day in hell when i start watching horror.&lt;/p&gt;
&lt;h3 id=&#34;games&#34;&gt;games&lt;/h3&gt;
&lt;p&gt;i played a couple of games this year that i really liked. hoping to continue the trend. mainly will focus on first person puzzles (portal&amp;rsquo;s my favourite game!), platformers, roguelikes and anything which i find fun.&lt;/p&gt;
&lt;p&gt;i also know what you&amp;rsquo;re thinking. &amp;ldquo;i&amp;rsquo;m sure you have games that you didn&amp;rsquo;t complete&amp;rdquo;. i do. i have enough things that make me worried about completing them. games are not those (yet).&lt;/p&gt;
&lt;h2 id=&#34;creation&#34;&gt;creation&lt;/h2&gt;
&lt;h3 id=&#34;writing&#34;&gt;writing&lt;/h3&gt;
&lt;p&gt;even if i read 0 words next year, i should have written to my heart&amp;rsquo;s content. movie and game reviews, posts like this, articles on what i am working on. just. type words on screen.&lt;/p&gt;
&lt;h3 id=&#34;softwarecoding&#34;&gt;software/coding&lt;/h3&gt;
&lt;p&gt;well. of course. it wouldn&amp;rsquo;t be a software developer&amp;rsquo;s resolution list unless it had this. want to complete a few projects next year. but more than that i want to pick up a few new things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;i learnt gamedev a few months ago (!) and after completing all the 2d chapters of &lt;a href=&#34;https://www.oreilly.com/library/view/godot-engine-game/9781788831505/&#34;&gt;Chris Bradfield&amp;rsquo;s godot book&lt;/a&gt;, i couldn&amp;rsquo;t get the time (skill issue) to get more into it. thinking to change that next year. if you want to see my newfound gamedev skills, check out &lt;a href=&#34;https://apps.abhijithota.com/space-rocks&#34;&gt;space rocks&lt;/a&gt;, one of the games from the book. i made a few changes and made it run on web (mostly). pretty fun.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;more creative coding! it&amp;rsquo;s a rite of passage to get into shaders after a few hours of game dev. &lt;a href=&#34;https://www.shadertoy.com/view/cldfW2&#34;&gt;that&amp;rsquo;s what i did&lt;/a&gt;. realised i&amp;rsquo;m not very good at it. but i still want to make some pretty stuff dance on screen. mathematical simulations are on top of that. maybe i&amp;rsquo;ll binge watch and code along the entire &lt;a href=&#34;https://www.youtube.com/playlist?list=PLRqwX-V7Uu6ZiZxtDDRCi6uhfTH4FilpH&#34;&gt;coding train catalogue&lt;/a&gt;. reminds me of &lt;a href=&#34;https://codepen.io/kretaceous&#34;&gt;my codepen days&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;photos&#34;&gt;photos&lt;/h3&gt;
&lt;p&gt;i love clicking photos. i should take more photos and more than that, properly share it even if i personally find most of them mid.&lt;/p&gt;
&lt;h2 id=&#34;misc&#34;&gt;misc&lt;/h2&gt;
&lt;h3 id=&#34;travel&#34;&gt;travel&lt;/h3&gt;
&lt;p&gt;travelled a good amount in 2023. want to do more of it in 2023 – both solo and with closed ones.&lt;/p&gt;
&lt;h3 id=&#34;share-more-stuff&#34;&gt;share more stuff&lt;/h3&gt;
&lt;p&gt;people who know me would be surprised by this. i do a lot of things but don&amp;rsquo;t really share them. but i should. i feel like sharing more is the more general term for shipping more. share the things you write, share the movies you like, share your thoughts, share the things you make, share the photos you take.&lt;/p&gt;
&lt;p&gt;i suck at all these. maybe this post could be a start to fixing it.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;thanks for reading and watch me fumble all of these in 2024.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>In my midwit phase</title>
      <link>https://abhijithota.com/posts/my-midwit-phase/</link>
      <pubDate>Wed, 27 Dec 2023 16:46:28 +0530</pubDate>
      
      <guid>https://abhijithota.com/posts/my-midwit-phase/</guid>
      <description>&lt;p&gt;Everyone has seen this or a variation of the &lt;a href=&#34;https://knowyourmeme.com/memes/iq-bell-curve-midwit&#34;&gt;midwit meme&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;midwit.webp&#34; alt=&#34;Midwit meme&#34;&gt;&lt;/p&gt;
&lt;p&gt;If you think the meme describes 3 different types of people, you&amp;rsquo;re both right and wrong because:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;every midwit meme describes a journey, not a classification.&lt;/p&gt;
&lt;p&gt;— &lt;a href=&#34;https://twitter.com/threepointone/status/1637124762479607810&#34;&gt;sunil pai, etc. (@threepointone)&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Lately at work I&amp;rsquo;ve been working on a pretty interesting thing which has me reaching for certain tools and techniques that I&amp;rsquo;ve thought to be overkill in the past. Being all day on Hacker News and reading a bunch of elitist comments parading about tech minimalism and ownership can only do so much.&lt;/p&gt;
&lt;p&gt;The thing is, I&amp;rsquo;m beginning to realise performance isn&amp;rsquo;t really difficult in modern applications if you choose the right tools – be it programming languages or libraries you use. If you&amp;rsquo;re thoughtful, even the bare minimum amount, you&amp;rsquo;ll get enough juice out of your system.&lt;/p&gt;
&lt;p&gt;What&amp;rsquo;s difficult is to &lt;strong&gt;scale&lt;/strong&gt; performance in presence of &lt;strong&gt;constraints&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;And coming to my previous point, I used to believe all these shiny technologies are overkill. Turns out I&amp;rsquo;ve never worked with actual &lt;strong&gt;constraints&lt;/strong&gt; for actual &lt;strong&gt;scale&lt;/strong&gt;. Hence, the midwit meme. I feel I&amp;rsquo;m entering that phase. Containers, microservices, Kubernetes and serverless all make sense to some extent now because I see some need for them. I&amp;rsquo;ve become mid. Enjoyer of technologies.&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;oppie.jpeg&#34; alt=&#34;A closeup still of Cillian Murphy from the movie - Oppenheimer&#34;&gt;&lt;/p&gt;
&lt;p&gt;Now I might be doing disservice to these technologies by putting them into a category in which only us midwits believe in. But I only do so because, as cool as it all is, it sure &lt;strong&gt;should&lt;/strong&gt; be simpler. It sure should be easier. And I believe realising how to do that would mean going further right in the chart.&lt;/p&gt;
&lt;p&gt;What comes then, I don&amp;rsquo;t know. &lt;a href=&#34;https://www.swyx.io/simplicity-rush&#34;&gt;I&amp;rsquo;m not in a rush to find out&lt;/a&gt;.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Containerisation for DevOps</title>
      <link>https://abhijithota.com/posts/devops-and-containerization/</link>
      <pubDate>Mon, 11 Sep 2023 18:00:00 +0530</pubDate>
      
      <guid>https://abhijithota.com/posts/devops-and-containerization/</guid>
      <description>&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;In October 2022, A certain company reached out to me to write an article about DevOps and containerization. I never got to complete it in time and when I did, they didn&amp;rsquo;t respond.&lt;/p&gt;
&lt;p&gt;I did a good amount of &lt;em&gt;research&lt;/em&gt; for this article, provided I did not know much about the space. Now that I work for a &lt;a href=&#34;https://argonaut.dev&#34;&gt;DevOps shop&lt;/a&gt;, I thought it was only fair to publish this article.&lt;/p&gt;
&lt;p&gt;I don&amp;rsquo;t think the writing is the best but it&amp;rsquo;s better to publish it than to let it rot in my drafts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;You can directly skip to the section about software development lifecycle if you&amp;rsquo;re already aware of DevOps. Despite, I think the immediate next sections act as a good primer.&lt;/p&gt;
&lt;h2 id=&#34;devops&#34;&gt;DevOps&lt;/h2&gt;
&lt;p&gt;Despite being the simple amalgamation of the words, &lt;em&gt;development&lt;/em&gt; and &lt;em&gt;operations&lt;/em&gt;, DevOps as a concept is inherently &lt;a href=&#34;https://blog.massdriver.cloud/devops-is-bullshit&#34;&gt;misunderstood&lt;/a&gt;. It isn&amp;rsquo;t a word well defined &lt;a href=&#34;https://en.wikipedia.org/wiki/DevOps#Definition&#34;&gt;in literature&lt;/a&gt;. Although the common consensus however is that it&amp;rsquo;s ideally &lt;a href=&#34;https://www.oreilly.com/content/building-a-devops-culture/&#34;&gt;about a culture&lt;/a&gt; in your team which maximises ease and quality of releases and development-to-deployment speeds leveraging collaboration, tooling and other methodologies.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://about.gitlab.com/topics/devops/&#34;&gt;According to GitLab&lt;/a&gt;, DevOps is&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;people working together to conceive, build and deliver secure software at top speed. [it] enables software developers (devs) and operations (ops) teams to accelerate delivery through automation, collaboration, fast feedback, and iterative improvement.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;DevOps itself is &lt;strong&gt;never concerned with the actual application business logic&lt;/strong&gt;. Like a management methodology, it is about making development and operations team more integrated, making the software supply more efficient in the process.&lt;/p&gt;
&lt;h3 id=&#34;characteristics-of-devops&#34;&gt;Characteristics of devops&lt;/h3&gt;
&lt;p&gt;The meanings and henceforth the rules of DevOps change org to org but there are certain properties that must be aligned in the DevOps movement:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Collaboration and Shared Responsibility&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;From Rouan Wilsenach&amp;rsquo;s article about &lt;a href=&#34;https://martinfowler.com/bliki/DevOpsCulture.html&#34;&gt;DevOps culture&lt;/a&gt;,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It’s easy for a development team to become disinterested in the operation and maintenance of a system if it is handed over to another team to look after.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Workflow Automation/Tooling&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;From &lt;a href=&#34;https://www.hashicorp.com/tao-of-hashicorp&#34;&gt;The Tao of Hashicorp&lt;/a&gt;,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;focus on the end goal and workflow, rather than the underlying technologies. [&amp;hellip;] As technologies evolve and better tooling emerges, the ideal workflow is just updated to leverage those technologies. Technologies change, end goals stay the same.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Feedback and Communication&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;From &lt;a href=&#34;https://www.oreilly.com/content/building-a-devops-culture/&#34;&gt;O&amp;rsquo;Reilly&amp;rsquo;s approach to building a DevOps culture&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A team taking a more DevOps approach talks about the product throughout its lifecycle, discussing requirements, features, schedules, resources, and whatever else might come up. The focus is on the product, not building fiefdoms and amassing political power. Production and build metrics are available to everyone and prominently displayed.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;what-is-containerization&#34;&gt;What is Containerization?&lt;/h2&gt;
&lt;p&gt;Containerization, in simplest of terms, means isolation. It is one way of doing &lt;a href=&#34;https://en.wikipedia.org/wiki/OS-level_virtualization&#34;&gt;OS-level virtualization&lt;/a&gt;, which basically means running a program, be it a simple application or a whole another OS, on top of your current OS.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A lot of containerization software exist in the industry today. However the one that completely turned the landscape by providing a easier UI is &lt;a href=&#34;https://www.docker.com/&#34;&gt;Docker&lt;/a&gt;. For the rest of the article, when we say containers, we mean Docker containers.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id=&#34;the-problems-faced-in-devops&#34;&gt;The problems faced in DevOps&lt;/h3&gt;
&lt;p&gt;Development of almost all software can be boiled down to the 7 steps: &lt;strong&gt;plan&lt;/strong&gt;, &lt;strong&gt;build&lt;/strong&gt;, &lt;strong&gt;test&lt;/strong&gt;, &lt;strong&gt;package&lt;/strong&gt;, &lt;strong&gt;secure&lt;/strong&gt;, &lt;strong&gt;release&lt;/strong&gt;, &lt;strong&gt;deploy&lt;/strong&gt; and &lt;strong&gt;monitor&lt;/strong&gt;. This is called the software development lifecycle. A DevOps driven team would need to care about the efficiency of all these steps and sure enough, teams face issues in all of the steps. We&amp;rsquo;re going to see what are some of the common problems faced in some of these steps.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Plan&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Planning involves gathering requirements, laying the roadmap, prioritising and making sure everyone is on board with what&amp;rsquo;s on the whiteboard. These are not exhaustive and still difficult.&lt;/p&gt;
&lt;p&gt;Sometimes, a designer might want to see how feasible is an element, or a PM wants to see what a certain feature will be used like.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Build&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Only writing code (not programming) is probably the easiest part of the cycle. The difficult thing is setting things up, choosing the tooling, checking for cross-platform issues, etc. The problem increases during onboarding of a new hire in your team and you have to help them setup their systems with all the tools and technologies that you use.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Test&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Building quality &lt;em&gt;into&lt;/em&gt; software is incredibly mandatory for anything remotely serious. Integration or even unit testing can help check for errors well before deployments, in the developers&amp;rsquo; local machines itself. How do you ensure your tests cover most of the cases, inputs or scenarios without a lot of friction in setting them up or risking your own system?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Package&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is the stage where you basically &amp;ldquo;build&amp;rdquo; your application, service or library for production usage by your end-users. You would &lt;code&gt;build&lt;/code&gt; a web application, &lt;code&gt;compile&lt;/code&gt; a service binary or something similar. This brings with it problems like; Where to build? What tools to build with? How to check if the builds are consistent?&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Secure&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;After we have built our website, executable or something else, how to verify if it is not tampered with? How to check if a build is actually what we want?&lt;/p&gt;
&lt;p&gt;We also want to check if the applications do not cause any harm to the underlying system running it.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Releases&lt;/strong&gt; &amp;amp; &lt;strong&gt;Rollbacks&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is where the consistency of the build comes into play, especially if you have a distributed system. Rollbacks are also crucial when things go wrong. But they can be hard to implement correctly and sometimes lead to &lt;a href=&#34;https://blog.cloudflare.com/partial-cloudflare-outage-on-october-25-2022/&#34;&gt;longer downtimes&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;why-containerization&#34;&gt;Why Containerization?&lt;/h2&gt;
&lt;p&gt;The problems described above demand a few things in common. Faster development, immutability of builds and security via isolation. With containerisation, all of these are addressed to in one way or the other.&lt;/p&gt;
&lt;h3 id=&#34;reproducible-environments&#34;&gt;Reproducible environments&lt;/h3&gt;
&lt;p&gt;Docker follows a declarative text-file based approach for creating images via its configuration file called the &lt;code&gt;Dockerfile&lt;/code&gt;. It is a one-stop shop for all your configurations and versions of tools. You can manage this&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;What is declarative? Instead of writing code that says &amp;ldquo;Start this app on port 8080&amp;rdquo;, you say &amp;ldquo;port = 8080&amp;rdquo; and start the container.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This feature of containers makes them absolutely easy for abstracting and composing different environments. Want a staging environment? No problem. Change some variables and spin up another container without worrying about what will happen to the production environment.&lt;/p&gt;
&lt;h3 id=&#34;versatile-builds&#34;&gt;Versatile builds&lt;/h3&gt;
&lt;p&gt;In the previous section, we saw the problems that come with packaging and security. Docker &lt;a href=&#34;https://docs.docker.com/get-started/overview/#docker-objects&#34;&gt;images&lt;/a&gt; are meant to be &lt;strong&gt;read-only&lt;/strong&gt; and &lt;strong&gt;immutable&lt;/strong&gt;. This works greatly for security as we don&amp;rsquo;t want our build to be tampered with. After an release image/container is built, it is pushed to a registry like &lt;a href=&#34;https://github.com/features/packages&#34;&gt;GitHub Container Registry&lt;/a&gt; or &lt;a href=&#34;https://hub.docker.com/&#34;&gt;Docker Hub&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Creating a Docker image or container also means that you don&amp;rsquo;t have to worry about configuration drift or dependency mismatch. Everything that is needed for a particular application will be bundled into the image, thereby giving consistent builds. Not to mention, since the &lt;code&gt;Dockerfile&lt;/code&gt; it&amp;rsquo;s basically just code, can be version controlled via an SCM like Git.&lt;/p&gt;
&lt;p&gt;The benefit of images not only comes when releasing but also when rolling back inevitable bugs that get into the application. If your image releases are versioned, which they are in most cases, all you have to do to is pull up a previous version from your registry, spin it up and take the current one down.&lt;/p&gt;
&lt;h3 id=&#34;consistent-development-tools&#34;&gt;Consistent development tools&lt;/h3&gt;
&lt;p&gt;You can ship not only your entire production application wherever and however you want to, but also speed up development with including tools &lt;em&gt;inside&lt;/em&gt; your containers. New developer joining your team? New container for them.&lt;/p&gt;
&lt;p&gt;Tools like &lt;a href=&#34;https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers&#34;&gt;VSCode Dev Containers&lt;/a&gt; make this process super easy. You can have project wise development containers and all a new developer has to do is pull and start the container.&lt;/p&gt;
&lt;h3 id=&#34;testing-via-isolation&#34;&gt;Testing via Isolation&lt;/h3&gt;
&lt;p&gt;We discussed the importance of testing and its problems. How do we properly ensure that tests are made against as rigorous scenarios as possible without harming our development or CI system? &lt;strong&gt;Run them inside containers!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Technologies like &lt;a href=&#34;https://github.com/ory/dockertest&#34;&gt;&lt;code&gt;ory/dockertest&lt;/code&gt;&lt;/a&gt; provide a first-class experience in spinning up &lt;strong&gt;entire databases&lt;/strong&gt; inside containers and testing your code in them!&lt;/p&gt;
&lt;h3 id=&#34;security-via-isolation&#34;&gt;Security via Isolation&lt;/h3&gt;
&lt;p&gt;As we discussed in the earlier paragraphs, when we use containers, we package and ship applications with their dependencies, rather than having to rely on the underlying operating system. This significantly reduces the risk of vulnerabilities in the application. This also protects against the dependencies installed in the OS being exploited.&lt;/p&gt;
&lt;p&gt;With proper auditing, at least a smoke-test verification of all the dependencies that goes to our containers, we can protect our apps against a lot of threats.&lt;/p&gt;
&lt;p&gt;Another thing to note is that each container runs in its own isolated environment. This isolation prevents containers from interacting with each other, which reduces the chances of security breaches or accidental leaks. You can start a billion containers and be sure that if one fails, others will remain intact, or at worst, fail because of different reasons.&lt;/p&gt;
&lt;h3 id=&#34;resource-conscious&#34;&gt;Resource conscious&lt;/h3&gt;
&lt;p&gt;Containers are much lighter than their heavy virtualization counter-parts - virtual machines.&lt;/p&gt;
&lt;p&gt;In traditional virtualization, something called &lt;a href=&#34;https://en.wikipedia.org/wiki/Hypervisor&#34;&gt;hypervisors&lt;/a&gt; &lt;strong&gt;emulate&lt;/strong&gt; hardware to run Virtual Machines. Containerization on the other hand is about &lt;a href=&#34;https://sysadmincasts.com/episodes/24-introduction-to-containers-on-linux-using-lxc&#34;&gt;just running another process&lt;/a&gt; on top of your base OS using various kernel mechanisms like &lt;code&gt;chroot&lt;/code&gt;, &lt;code&gt;namespaces&lt;/code&gt; and &lt;code&gt;cgroups&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The benefit that comes with ditching the hypervisor can be seen in real life examples. For example, Google starts around &lt;a href=&#34;https://speakerdeck.com/jbeda/containers-at-scale?slide=2&#34;&gt;2 billion containers per week&lt;/a&gt;! And that was in 2014. That gives us an idea about how lightweight they actually are.&lt;/p&gt;
&lt;p&gt;Containers also allow us to limit the resource usage like memory or CPU with easy configurations.&lt;/p&gt;
&lt;h3 id=&#34;enables-collaboration&#34;&gt;Enables Collaboration&lt;/h3&gt;
&lt;p&gt;A last point that might be a bit stretched but can definitely become a reality is containers can be run by anyone. The designer in your team doesn&amp;rsquo;t have to learn about &lt;code&gt;npm&lt;/code&gt; or &lt;code&gt;Webpack&lt;/code&gt; to look at the application. They just need to &lt;a href=&#34;https://docs.docker.com/get-docker/&#34;&gt;install Docker&lt;/a&gt; on their machine, download the code, and start the container.&lt;/p&gt;
&lt;p&gt;Albeit not a better solution over staging environments or tunnels, teams actually use this sometimes!&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Containerization is often cited as one of the key technologies that enables DevOps culture. They allow for much more rapid and consistent deployment of applications, and they make it much easier to manage dependencies and isolate applications from each other. This makes it possible to deploy applications much more frequently, and to do so with much less risk.&lt;/p&gt;
&lt;p&gt;When we go back to the &lt;a href=&#34;#characteristics-of-devops&#34;&gt;characteristics of DevOps&lt;/a&gt; and see how &lt;a href=&#34;#why-containerization&#34;&gt;containers solve&lt;/a&gt; the problems posed in the &lt;a href=&#34;#the-problems-faced-in-devops&#34;&gt;software development lifecycle&lt;/a&gt;, we can see it all coming together.&lt;/p&gt;
&lt;p&gt;Containerization make workflow automation better by making the CI more efficient with isolated testing. They make packaging and releasing a breeze with images and containers. They enable iterative development and quick feedback by making it easy for anyone to reproduce environments suited to the scenarios being tested.&lt;/p&gt;
&lt;p&gt;In the end, it&amp;rsquo;s safe to say that containerization is a capable catalyst for incorporating DevOps methodologies in the team. It is no silver bullet but they make complex application deployments quick and reliable.&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Poor man&#39;s CI/CD with GitHub Webhooks</title>
      <link>https://abhijithota.com/posts/poor-mans-cicd-with-github-actions/</link>
      <pubDate>Wed, 05 Oct 2022 10:32:17 +0530</pubDate>
      
      <guid>https://abhijithota.com/posts/poor-mans-cicd-with-github-actions/</guid>
      <description>&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;In my 5th semester of college (mid 2021), I was in-charge of the Web Operations team at &lt;a href=&#34;https://ecell.iitm.ac.in/home&#34;&gt;E-Cell IITM&lt;/a&gt;. Our responsibility was to make web applications for events, workshops and competitions. The tech stack was primarily Node.js with Express, React and MongoDB for the database. If you&amp;rsquo;re a &lt;em&gt;full-stack developer&lt;/em&gt;, you might know this as the MERN stack.&lt;/p&gt;
&lt;p&gt;The environment was fast-paced. We were building a lot of things and breaking more of them in the process. It was like a startup. The highest number of users for an application was only 6.5k. And that&amp;rsquo;s the reason we could experiment a lot of stuff. Following best practices was something we tried a lot to inculcate by adding tools like linters, formatters, pre-commit hooks, etc. but again, &lt;strong&gt;we were all freshers; making and breaking things&lt;/strong&gt; and somewhere down the line we would just push something with just a commit message of &lt;code&gt;fix stuff&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We have an in-premise server in the institute cluster for hosting the MERN applications. It is just an Ubuntu box with &lt;a href=&#34;https://pm2.io/&#34;&gt;&lt;code&gt;pm2&lt;/code&gt;&lt;/a&gt; installed for running Node.js apps. A lot of our time was spent in deploying very, &lt;em&gt;very&lt;/em&gt; minor changes. Fix-a-typo-in-a-static-page-level minor. The process was generally this:&lt;/p&gt;
&lt;ol start=&#34;0&#34;&gt;
&lt;li&gt;Connect to institute&amp;rsquo;s VPN if you&amp;rsquo;re not in Insti&amp;rsquo;s network&lt;/li&gt;
&lt;li&gt;SSH into the server&lt;/li&gt;
&lt;li&gt;&lt;code&gt;git pull&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;npm run build&lt;/code&gt; if it&amp;rsquo;s a React application&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pm2 restart frontend-server&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Easy and simple. Manual and boring. Perfect characteristics of something that needs to be automated. Automation is the mother of invention when it comes to software development and so I went looking for answers.&lt;/p&gt;
&lt;h2 id=&#34;self-hosted-github-actions&#34;&gt;Self-hosted GitHub Actions&lt;/h2&gt;
&lt;p&gt;The first and the most obvious solution was to use &lt;a href=&#34;https://github.com/features/actions&#34;&gt;GitHub Actions&lt;/a&gt;. I&amp;rsquo;ve never used them before and was pretty excited to learn and use it. My excitement was soon doubled when I got to know that you can &lt;a href=&#34;https://docs.github.com/en/actions/hosting-your-own-runners&#34;&gt;self-host them&lt;/a&gt;. I was able to learn it and setup it for our backend Node.js monolith in a day. But something felt off.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It required installing a lot of stuff to a rather humble machine. It also demanded a lot of memory relative to what our applications were using. To give you an idea, our main backend service uses &lt;strong&gt;105 MB&lt;/strong&gt; at maximum whereas the runner used around &lt;strong&gt;1 GB&lt;/strong&gt; in average.&lt;/li&gt;
&lt;li&gt;The action was such that it checked out the whole repository every time. The repository was, in a way, large.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/li&gt;
&lt;li&gt;All our applications stayed in the home directory (&lt;code&gt;$HOME&lt;/code&gt;). I could not figure out how to checkout the repository in the same place where it was and got around it by adding &lt;a href=&#34;https://docs.github.com/en/actions/hosting-your-own-runners/running-scripts-before-or-after-a-job&#34;&gt;post-job scripts&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;We weren&amp;rsquo;t looking at a lot of scale so this level of sophistication felt overkill.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All we wanted to do was to run a few scripts on a &lt;code&gt;git push&lt;/code&gt;. Surely, there was a minimal way of doing this?&lt;/p&gt;
&lt;h2 id=&#34;the-hack-which-seemed-like-the-solution&#34;&gt;The hack which seemed like the solution&lt;/h2&gt;
&lt;p&gt;Webhooks are an elegant way to communicate from server to client. They are one of the simpler ways to implement &lt;em&gt;event-driven architecture&lt;/em&gt;. Think of webhooks as a third-party server sending an HTTP POST request to your own server. This doesn&amp;rsquo;t require you to &lt;a href=&#34;https://en.wikipedia.org/wiki/Polling_(computer_science)&#34;&gt;keep asking that server for data&lt;/a&gt; or keep an open connection. GitHub offers &lt;a href=&#34;https://docs.github.com/en/developers/webhooks-and-events/webhooks/about-webhooks&#34;&gt;Webhooks&lt;/a&gt; for a lot of repository and organisation level events.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s how they work:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;You provide a URL and a secret to GitHub. GitHub stores the hash of that secret.&lt;/li&gt;
&lt;li&gt;You choose the events you want a webhook for.&lt;/li&gt;
&lt;li&gt;Whenever that event happens, GitHub sends a &lt;code&gt;JSON&lt;/code&gt; or &lt;code&gt;XML&lt;/code&gt; payload via a &lt;code&gt;HTTP POST&lt;/code&gt; request to the URL you provided in step 1. It also sends the signature which is derived from the secret you provided.&lt;/li&gt;
&lt;li&gt;In your server, you check the signature with your original signature. If it&amp;rsquo;s correct, you handle the payload however you want to.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The payload being talked about contains a &lt;a href=&#34;https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads&#34;&gt;lot of information related to the event&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And there was it. A simple &lt;code&gt;HTTP POST&lt;/code&gt; containing relevant data. The idea was to commit and push with a commit message starting with &lt;code&gt;deploy&lt;/code&gt;. The commit message, committer, files changed, etc. would be included in the &lt;a href=&#34;https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#push&#34;&gt;payload for the push event&lt;/a&gt;. And here&amp;rsquo;s how it panned out in our case:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Provide a URL like &lt;code&gt;https://ecell.iitm.ac.in/api/gh-webhook&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Choose to send the webhook only on &lt;code&gt;push&lt;/code&gt; events.&lt;/li&gt;
&lt;li&gt;When we receive a webhook, check if the commit message starts with &lt;code&gt;deploy&lt;/code&gt;, the committer is one of the admins and some code is changed.&lt;/li&gt;
&lt;li&gt;Run a simple script:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;git pull
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;npm run build
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pm2 restart
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;step-by-step-instructions&#34;&gt;Step by step instructions&lt;/h2&gt;
&lt;p&gt;Let&amp;rsquo;s try to replicate this with an example repository and &lt;code&gt;localhost&lt;/code&gt; as the server. Find the repository here: &lt;a href=&#34;https://github.com/abhijit-hota/webhook-example&#34;&gt;&lt;code&gt;webhook-example&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;adding-the-webhook-to-the-repository&#34;&gt;Adding the webhook to the repository&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;Choose a repository you want to work on. You can fork the example repository. Make sure to rename &lt;code&gt;.template.env&lt;/code&gt; to &lt;code&gt;.env&lt;/code&gt; and change the secret string if you want to.&lt;/li&gt;
&lt;li&gt;Go to &lt;code&gt;Settings&lt;/code&gt; &amp;gt; &lt;code&gt;Webhooks&lt;/code&gt; &amp;gt; &lt;code&gt;Add webhook&lt;/code&gt;. Or just visit &lt;code&gt;https://github.com/&amp;lt;username&amp;gt;/&amp;lt;repo-name&amp;gt;/settings/hooks/new&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We will start the server and expose it via a tunnel. I&amp;rsquo;m using &lt;a href=&#34;https://github.com/cloudflare/cloudflared&#34;&gt;&lt;code&gt;cloudflared&lt;/code&gt;&lt;/a&gt; but you can use anything else if you want to.&lt;/li&gt;
&lt;li&gt;As you can see, we have chosen &lt;code&gt;application/json&lt;/code&gt; as the content type cause we want the payload in JSON. For the secret, you can put any random string but make sure you remember/note what you put there. For the example repository you also have to update your &lt;code&gt;.env&lt;/code&gt; file. Details in the next section.
&lt;img src=&#34;2022-10-05-21-59-23.png&#34; alt=&#34;&#34;&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note about SSL&lt;/strong&gt;: We&amp;rsquo;ve only disabled it because it&amp;rsquo;s just a demo. Enable this without fail in your real applications.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;listening-to-the-webhook-in-your-server&#34;&gt;Listening to the webhook in your server&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;The &lt;a href=&#34;https://github.com/abhijit-hota/webhook-example/blob/master/index.js&#34;&gt;&lt;code&gt;index.js&lt;/code&gt;&lt;/a&gt; is the entry point for our server. It&amp;rsquo;s a simple static site server in Node.js which serves a React build. We mount the webhook &lt;em&gt;listener&lt;/em&gt; in the &lt;code&gt;/webhook&lt;/code&gt; route. Notice how we used this route in the URL we provided to GitHub in the previous step.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;// Mount the webhook listener
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;&lt;/span&gt;app.use(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;/webhook&amp;#39;&lt;/span&gt;, webhookRouter);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;In &lt;a href=&#34;https://github.com/abhijit-hota/webhook-example/blob/master/webhook.js&#34;&gt;&lt;code&gt;webhook.js&lt;/code&gt;&lt;/a&gt;, we first parse the &lt;code&gt;.env&lt;/code&gt; file which contains our secret.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dotenv.config();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; SECRET &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; process.env.GH_WEBHOOK_SECRET;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Next we add 2 middlewares. The first middleware stores the raw request buffer. We do this because parsing damages the integrity of the signature.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;bodyParser.json({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	verify&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; (req, res, buf) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	req.rawBody &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; buf;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  	},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;The second middleware verifies the signature sent with our secret that only we and GitHub knows. This way we know the request is actually a valid one from GitHub. This is why SSL is so important because without that you&amp;rsquo;re exposing this request to &lt;a href=&#34;https://en.wikipedia.org/wiki/Man-in-the-middle_attack&#34;&gt;MITM attacks&lt;/a&gt;.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; body &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; Buffer.from(req.rawBody, &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;utf8&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; ghSign &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; req.get(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;x-hub-signature-256&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; ourSign &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;sha256=&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;+&lt;/span&gt; crypto.createHmac(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;sha256&amp;#39;&lt;/span&gt;, SECRET).update(body).digest(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;hex&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; (ghSign &lt;span style=&#34;color:#ff79c6&#34;&gt;!==&lt;/span&gt; ourSign) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   &lt;span style=&#34;color:#ff79c6&#34;&gt;throw&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;new&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;Error&lt;/span&gt;();
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;And finally, we listen to it in the &lt;code&gt;POST&lt;/code&gt; handler.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;webhookRouter.post(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;/&amp;#39;&lt;/span&gt;, &lt;span style=&#34;color:#ff79c6&#34;&gt;async&lt;/span&gt; (req, res) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt; 	console.debug(req.body)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;At this point, if you push some changes, you can see the payload in your terminal where the server is running:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;ref&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;refs/heads/master&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;repository&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;webhook-example&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;full_name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;abhijit-hota/webhook-example&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;pusher&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;abhijit-hota&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;email&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;abhihota025@gmail.com&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;head_commit&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;id&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;6c386ca6d6f3df80ea7b0abd59c3b9a8c3983726&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;message&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;chore: add comments and increase legibility&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;timestamp&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;2022-10-05T22:19:21+05:30&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;author&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;abhijit-hota&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;email&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;abhihota025@gmail.com&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;username&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;abhijit-hota&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;added&amp;#34;&lt;/span&gt;: [],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;removed&amp;#34;&lt;/span&gt;: [],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;modified&amp;#34;&lt;/span&gt;: [
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;.template.env&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;index.js&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;            &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;webhook.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        ]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;I&amp;rsquo;ve removed &lt;em&gt;a lot&lt;/em&gt; of stuff from the payload and have just shown the relevant ones. Now all that left is to run commands based on the data we get. More on this in the next section.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&#34;building-and-executing-commands&#34;&gt;Building and executing commands&lt;/h3&gt;
&lt;blockquote&gt;
&lt;p&gt;We&amp;rsquo;re only going to see how to solve it for Linux but it shouldn&amp;rsquo;t be that hard to build queries for Windows systems in a similar way, if you&amp;rsquo;re using Windows at all for deployments.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol&gt;
&lt;li&gt;We check for the commit message and the pusher. You can of course, choose your own logic here:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; { head_commit&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; commit, pusher } &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; req.body;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; (&lt;span style=&#34;color:#ff79c6&#34;&gt;!&lt;/span&gt;commit.message.startsWith(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;deploy&amp;#39;&lt;/span&gt;) &lt;span style=&#34;color:#ff79c6&#34;&gt;||&lt;/span&gt; pusher.name &lt;span style=&#34;color:#ff79c6&#34;&gt;!==&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;abhijit-hota&amp;#39;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; res.send(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;Deployment skipped.&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;We create an array of commands to run. And we add to it as we go over the changes. The code is pretty self-explanatory and I&amp;rsquo;ve added comments too.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; commands &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; [&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;cd &amp;#34;&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; changes &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; [...commit.modified, ...commit.added, ...commit.removed];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; requiresReinstall &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; changes.any((change) =&amp;gt; change.startsWith(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;package&amp;#39;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; (requiresReinstall) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    commands.push(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;npm install&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; hasFrontendChanges &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; changes.any((change) =&amp;gt; change.startsWith(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;frontend&amp;#39;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; (hasFrontendChanges) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    commands.push(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;cd frontend&amp;#39;&lt;/span&gt;); 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; requiresReinstallInFrontend &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; changes.any((change) =&amp;gt; change.startsWith(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;frontend/package&amp;#39;&lt;/span&gt;));
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; (requiresReinstallInFrontend) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        commands.push(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;npm install&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    commands.push(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;npm run build&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;commands.push(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;npm start&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Join the whole command string with &lt;code&gt;&amp;amp;&amp;amp;&lt;/code&gt; and run it.
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; cmd &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; commands.join(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39; &amp;amp;&amp;amp; &amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;console.debug(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Command to run:&amp;#34;&lt;/span&gt;, cmd);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;exec(cmd); &lt;span style=&#34;color:#6272a4&#34;&gt;// exec from child_process
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;Let&amp;rsquo;s put it to test! We commit with the message &lt;code&gt;deploy: test&lt;/code&gt; and we see the message:
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;Command to run: &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;cd&lt;/span&gt; /home/kreta/work/misc/webhook-example &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; git pull --all &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; git checkout main &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;amp;&amp;amp;&lt;/span&gt; npm start
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;code&gt;npm start&lt;/code&gt; in the &lt;code&gt;package.json&lt;/code&gt; starts the server in &lt;code&gt;localhost:8080&lt;/code&gt;. And sure enough:
&lt;img src=&#34;2022-10-05-23-08-39.png&#34; alt=&#34;&#34;&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&#34;its-a-hack-at-the-end-of-the-day&#34;&gt;It&amp;rsquo;s a hack at the end of the day&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;The performance cost is way less than GH Action runners. We run a separate Node.js server for this which only takes up like &lt;code&gt;50 MB&lt;/code&gt; of RAM. I&amp;rsquo;m sure we can remove all the fluff from there and make it leaner but it works for now.&lt;/li&gt;
&lt;li&gt;For multi-repo systems, you can create organisation-level webhooks and change the command according to the &lt;code&gt;repository&lt;/code&gt; field in the payload.&lt;/li&gt;
&lt;li&gt;&amp;ldquo;But Abhijit, there&amp;rsquo;s no CI at all!&amp;rdquo;. Just add an &lt;code&gt;npm test&lt;/code&gt; somewhere and log the reports, email, etc. if you care about it.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Addressing the obvious thoughts in your head, yes, it can break and there&amp;rsquo;s no way of knowing if the command is faulty. But you can setup logging, alerts etc. It&amp;rsquo;s your system. It&amp;rsquo;s code. It cannot get more &lt;a href=&#34;https://en.wikipedia.org/wiki/Infrastructure_as_code&#34;&gt;IaC&lt;/a&gt; than this. I set this up on the actual server almost a year ago and it hasn&amp;rsquo;t been changed ever since. As you can see, this is a setup once and forget kinda system.&lt;/p&gt;
&lt;p&gt;But if your infra is changing a lot of times and requires really good monitoring, please don&amp;rsquo;t use this. This is a hack and I&amp;rsquo;m not very fond of hacks. Except for this one. This one, I&amp;rsquo;m proud of.&lt;/p&gt;
&lt;h2 id=&#34;first-principles-are-good&#34;&gt;First principles are good&lt;/h2&gt;
&lt;p&gt;The simplest &lt;em&gt;solutions&lt;/em&gt; are the best ones. If we go backwards from a solution to the problem, we can find  better ways of thinking. Some hacks and workarounds can sometimes go against the practice of using the right tools and can feel like reinventing the wheel. But if the trade-off is worth it, maybe it is the best solution for it after all. Remember to &lt;a href=&#34;https://zerodha.tech/blog/scaling-with-common-sense/&#34;&gt;scale with common sense&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;The repository was larger than needed because it had a whole Bootstrap theme template.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>My arsenal of CLI tools</title>
      <link>https://abhijithota.com/posts/cli-tools/</link>
      <pubDate>Sun, 17 Jul 2022 08:43:07 +0530</pubDate>
      
      <guid>https://abhijithota.com/posts/cli-tools/</guid>
      <description>&lt;h2 id=&#34;background&#34;&gt;Background&lt;/h2&gt;
&lt;p&gt;I&amp;rsquo;ve been seriously using Linux for (just) over 2 years.
The thing I take pride in is my pragmatic, albeit flashy at times, CLI setup.
This article could be a &lt;code&gt;dotfiles&lt;/code&gt; repository but I keep it private because I think it&amp;rsquo;s too risky.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s look into some tools I use daily.&lt;/p&gt;
&lt;blockquote&gt;
&lt;details&gt;
&lt;summary&gt;My terminal setup&lt;/summary&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://sw.kovidgoyal.net/kitty/&#34;&gt;kitty&lt;/a&gt;, the best terminal emulator&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;fast&lt;/li&gt;
&lt;li&gt;panes, tabs, windows&lt;/li&gt;
&lt;li&gt;a plethora of configurable keybindings&lt;/li&gt;
&lt;li&gt;really good plugin model and ecosystem&lt;/li&gt;
&lt;li&gt;remote control allows amazing interop between other software&lt;/li&gt;
&lt;li&gt;fantastic scroll-back buffer manipulation capabilities&lt;/li&gt;
&lt;li&gt;little features such as following links via keyboard, selecting text, etc.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;zsh&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/ohmyzsh/ohmyzsh/&#34;&gt;&lt;code&gt;ohmyzsh&lt;/code&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/romkatv/powerlevel10k&#34;&gt;powerlevel10k&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Bunch of plugins&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/details&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;tools-of-trade&#34;&gt;Tools of trade&lt;/h2&gt;
&lt;p&gt;There are a lot of &lt;a href=&#34;https://jvns.ca/blog/2022/04/12/a-list-of-new-ish--command-line-tools/&#34;&gt;awesome&lt;/a&gt; &lt;a href=&#34;https://earthly.dev/blog/command-line-tools/&#34;&gt;articles&lt;/a&gt; and &lt;a href=&#34;https://github.com/ibraheemdev/modern-unix&#34;&gt;resources&lt;/a&gt; that list out amazing CLI tools.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;m going to be talking about the tools which have stuck with me and I actually use, hence the use of word &amp;ldquo;My&amp;rdquo; in the title.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s go over the tools categorically as Julia Evans does in &lt;a href=&#34;https://jvns.ca/blog/2022/04/12/a-list-of-new-ish--command-line-tools/&#34;&gt;her CLI list&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&#34;replacement-for-standard-tools&#34;&gt;Replacement for standard tools&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/sharkdp/bat&#34;&gt;&lt;strong&gt;batcat&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;cat&lt;/code&gt; command with other niceties such as syntax highlighting, paging, line numbers, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/sharkdp/fd&#34;&gt;&lt;strong&gt;fd&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A faster, user-friendlier &lt;code&gt;find&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/BurntSushi/ripgrep/&#34;&gt;&lt;strong&gt;ripgrep&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A faster, user-friendlier &lt;code&gt;grep&lt;/code&gt;&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/Byron/dua-cli&#34;&gt;&lt;strong&gt;dua&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A tool to check how much space on disk, a particular directory/file is occupying and to delete it in a nicer way. Can be an alternative to &lt;code&gt;du&lt;/code&gt; and &lt;code&gt;rm&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/aristocratos/btop/&#34;&gt;&lt;strong&gt;btop&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Powerful and pretty resource monitoring tool, alternative to &lt;code&gt;top&lt;/code&gt;. One of my favorite tools here because of the convenient keyboard bindings.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/dalance/procs&#34;&gt;&lt;strong&gt;procs&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Prettier &lt;code&gt;ps&lt;/code&gt; with extra features. I mainly use it as it displays the PID of a server associated with its TCP port. Very handy to clear dangling processes. Only if this was possible in &lt;code&gt;btop&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://tldr.sh/&#34;&gt;&lt;strong&gt;tldr&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Provides short usage examples for common commands. I don&amp;rsquo;t dislike &lt;code&gt;man&lt;/code&gt; pages but they can be really hard to sift through when you are just looking for a basic example.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Just as a little game, guess what command I&amp;rsquo;ve &lt;code&gt;tldr&lt;/code&gt;ed the most.&lt;sup id=&#34;fnref:2&#34;&gt;&lt;a href=&#34;#fn:2&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/zyedidia/micro&#34;&gt;&lt;strong&gt;micro&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I need a quick, in-terminal editor a lot of times. Even though I use a lot of CLI tools, I&amp;rsquo;m not acquainted with &lt;code&gt;vi&lt;/code&gt;&lt;sup id=&#34;fnref:3&#34;&gt;&lt;a href=&#34;#fn:3&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;3&lt;/a&gt;&lt;/sup&gt; or &lt;code&gt;nano&lt;/code&gt;. I prefer the &amp;ldquo;vanilla&amp;rdquo; editor keys such as arrow keys for moving among words, &lt;code&gt;Ctrl+X&lt;/code&gt;/&lt;code&gt;Ctrl+V&lt;/code&gt;, &lt;code&gt;Shift+Arrow&lt;/code&gt; for selecting, etc. &lt;code&gt;micro&lt;/code&gt; is a perfect tool to me for this situation.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;newish-inventions&#34;&gt;New(ish) inventions&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/ajeetdsouza/zoxide&#34;&gt;&lt;strong&gt;zoxide&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A directory autojumper based on frecency. &lt;code&gt;zoxide&lt;/code&gt; isn&amp;rsquo;t a new invention in itself but autojumping tools are. If there&amp;rsquo;s a tool that I&amp;rsquo;d take with me to my grave, it would be this. I&amp;rsquo;ve used it more than I can admit.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/mwh/dragon/&#34;&gt;&lt;strong&gt;dragon&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Render a GUI list of files from the CLI to drag somewhere. I generally use this to drag files into my browser like upload boxes, email attachments, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/zyedidia/eget&#34;&gt;&lt;strong&gt;eget&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If it&amp;rsquo;s not obvious by now, I love tools. And all of these CLI tools are hosted on GitHub. &lt;code&gt;eget&lt;/code&gt; makes it way easier to download releases and extract them into the one of many &lt;code&gt;bin&lt;/code&gt; directories Linux has.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/eradman/entr&#34;&gt;&lt;strong&gt;entr&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;A small filesystem watcher. I don&amp;rsquo;t use this much as I rely on language specific tooling like &lt;code&gt;air&lt;/code&gt; for Golang.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/twpayne/chezmoi&#34;&gt;&lt;strong&gt;chezmoi&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Powerful and easy dotfile manager using Git. I have auto-commit/push turned on and regularly do a &lt;code&gt;chezmoi re-add&lt;/code&gt; so I&amp;rsquo;m not scared of losing my configuration at all.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/atanunq/viu&#34;&gt;&lt;strong&gt;viu&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;View images in the terminal. Good for previewing files. When I came across this for the first time, it was sorcery to me. &lt;a href=&#34;https://sw.kovidgoyal.net/kitty/graphics-protocol/&#34;&gt;Thanks again, Kitty&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/jarun/nnn&#34;&gt;&lt;strong&gt;nnn&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I haven&amp;rsquo;t tried a lot of CLI file managers because &lt;code&gt;nnn&lt;/code&gt; was the first I tried and my mind just said, yep, I&amp;rsquo;m not going to move off this.&lt;/p&gt;
&lt;p&gt;Along with the awesome keyboard navigation features, the real deal for me was the plugin system which leveraged my already existing tools. It has a preview plugin which ties with &lt;code&gt;viu&lt;/code&gt;, a &lt;code&gt;dragon&lt;/code&gt; plugin, a KDE Connect plugin to send files to otehr devices, and a &lt;code&gt;zoxide&lt;/code&gt; plugin for autojumping.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&#34;jsonyamlcsv-things&#34;&gt;JSON/YAML/CSV things&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/TomWright/dasel&#34;&gt;&lt;strong&gt;dasel&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Super convenient conversion among JSON &amp;lt;-&amp;gt; CSV &amp;lt;-&amp;gt; YAML &amp;lt;-&amp;gt; etc. It&amp;rsquo;s simple and just converts one format to the other. No fancy transformation stuff.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://stedolan.github.io/jq/&#34;&gt;&lt;strong&gt;jq&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Super powerful JSON toolkit. &lt;code&gt;jq&lt;/code&gt; has a relatively steeper learning curve but I&amp;rsquo;ve been successfully using it with the help of &lt;a href=&#34;https://gist.github.com/olih/f7437fb6962fb3ee9fe95bda8d2c8fa4&#34;&gt;this cheat sheet&lt;/a&gt; and occasional trips to the &lt;a href=&#34;https://stedolan.github.io/jq/manual/&#34;&gt;manual&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/alexhallam/tv&#34;&gt;&lt;strong&gt;tv&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a CLI CSV viewer. It&amp;rsquo;s just better than &lt;code&gt;cat&lt;/code&gt;ing CSVs.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;miscellaneous&#34;&gt;Miscellaneous&lt;/h2&gt;
&lt;p&gt;These don&amp;rsquo;t really fall under &lt;em&gt;CLI&lt;/em&gt; tools, but are CLI extensions or alternatives to other tools.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://userbase.kde.org/KDEConnect&#34;&gt;&lt;strong&gt;kdeconnect-cli&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;I do a lot of file sharing from and to my phone and KDE Connect works flawlessly.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&#34;https://github.com/Rigellute/spotify-tui&#34;&gt;&lt;strong&gt;spotify-tui&lt;/strong&gt;&lt;/a&gt; and &lt;a href=&#34;https://github.com/Spotifyd/spotifyd&#34;&gt;&lt;strong&gt;spotifyd&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Call me crazy but trying Spotify in the terminal was one of the reason I pay for Spotify Premium. Worth it.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;useful-aliases&#34;&gt;Useful aliases&lt;/h2&gt;
&lt;p&gt;These are some useful aliases built on top of above mentioned tools and standard tools that I frequently use:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;share&lt;/code&gt;:&lt;/p&gt;
&lt;p&gt;A Wrapper around KDE Connect that shares screenshots and files&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;share&lt;span style=&#34;color:#ff79c6&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6272a4&#34;&gt;# `share ss`: Shares latest screenshots/image in the clipboard&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;[[&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$1&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;ss&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;]]&lt;/span&gt;; &lt;span style=&#34;color:#ff79c6&#34;&gt;then&lt;/span&gt; 
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;img_path&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;/tmp/&lt;span style=&#34;color:#ff79c6&#34;&gt;$(&lt;/span&gt;date +&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;%d_%m_%y-%H_%M_%m&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;)&lt;/span&gt;.png
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      xclip -selection clipboard -t image/png -o &amp;gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$img_path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      kdeconnect-cli -n sam --share &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$img_path&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6272a4&#34;&gt;# `share /some/path/file.ext`: Shares files&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff79c6&#34;&gt;else&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      kdeconnect-cli -n sam --share &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff79c6&#34;&gt;fi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;j2c&lt;/code&gt; &amp;amp; &lt;code&gt;c2j&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Convert JSON &amp;lt;-&amp;gt; CSV&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;j2c&lt;span style=&#34;color:#ff79c6&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  dasel -r json -w csv
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;c2j&lt;span style=&#34;color:#ff79c6&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    dasel -r csv -w json
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;dmv&lt;/code&gt;/&lt;code&gt;dcp&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;I constantly face this situation where I have to &lt;code&gt;mv&lt;/code&gt; or &lt;code&gt;cp&lt;/code&gt; the latest downloaded file to the folder I&amp;rsquo;m currently at. This alias was my solution&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dmv&lt;span style=&#34;color:#ff79c6&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;__fname&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;$(&lt;/span&gt;ls -t ~/Downloads | head -n 1&lt;span style=&#34;color:#ff79c6&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;__fpath&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$HOME&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;/Downloads/&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$__fname&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  mv &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$__fpath&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;\.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;dcp&lt;span style=&#34;color:#ff79c6&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;__fname&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;$(&lt;/span&gt;ls -t ~/Downloads | head -n 1&lt;span style=&#34;color:#ff79c6&#34;&gt;)&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;__fpath&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$HOME&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;/Downloads/&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$__fname&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    cp -a &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$__fpath&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;\.&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;str&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Shortcut to generate random strings. Useful for placeholders, development secret keys, etc.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;str&lt;span style=&#34;color:#ff79c6&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#6272a4&#34;&gt;# Usage: `str 8`&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  node -p &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;crypto.randomBytes(&lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$1&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;/2).toString(&amp;#39;hex&amp;#39;);&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;pskill&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Usage: &lt;code&gt;pskill foo&lt;/code&gt;. Slightly dangerous alias that kills all processes matching &lt;code&gt;foo&lt;/code&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;pskill&lt;span style=&#34;color:#ff79c6&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  procs &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$1&lt;/span&gt; --no-header --only pid | xargs &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;kill&lt;/span&gt; -15
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;m&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Quick maths! Stole it from &lt;a href=&#34;https://news.ycombinator.com/item?id=31772976&#34;&gt;this HN comment&lt;/a&gt;.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-zsh&#34; data-lang=&#34;zsh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;m&lt;span style=&#34;color:#ff79c6&#34;&gt;()&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  python3 -c &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;from math import *; print(&lt;/span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;$*&lt;/span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;)&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;a-hyperbolic-rant&#34;&gt;A hyperbolic rant&lt;/h2&gt;
&lt;p&gt;I love the CLI. Dare I say, it&amp;rsquo;s the easiest way of getting things done &lt;em&gt;if&lt;/em&gt; you know what you&amp;rsquo;re doing. And of course, that&amp;rsquo;s a gigantic &amp;ldquo;if&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;Compare the following 2 conversations:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Bob&lt;/strong&gt;: Hey, how do I [do this] using [that] such that [something] becomes [something else] and [that particular thing] is not messed up?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alice&lt;/strong&gt;: Ah, give me a minute!&lt;/p&gt;
&lt;p&gt;[10 minutes later]&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alice&lt;/strong&gt;: Here, yank this into the terminal and run it.&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;$ dothis --use&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;that &lt;span style=&#34;color:#f1fa8c&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&lt;/span&gt;  --from&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;something &lt;span style=&#34;color:#f1fa8c&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&lt;/span&gt;  --to&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;something-else &lt;span style=&#34;color:#f1fa8c&#34;&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&lt;/span&gt;  --ignore&lt;span style=&#34;color:#ff79c6&#34;&gt;=&lt;/span&gt;that-particular-thing
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;Bob&lt;/strong&gt;: &lt;strong&gt;&lt;em&gt;Nice&lt;/em&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;vs.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Alice&lt;/strong&gt;: Hey, how do I connect to Wi-Fi?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bob&lt;/strong&gt;: There should be a Wi-Fi icon thingy in the bottom-right corner.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alice&lt;/strong&gt;: There isn&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bob&lt;/strong&gt;: There should be.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alice&lt;/strong&gt;: There isn&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bob&lt;/strong&gt;: You are using Winwoes 10, right?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alice&lt;/strong&gt;: Yes.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bob&lt;/strong&gt;: Okay, go to Control Panel.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alice&lt;/strong&gt;: How?&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bob&lt;/strong&gt;: Go to start and search for it&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alice&lt;/strong&gt;: Okay, I&amp;rsquo;m here.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bob&lt;/strong&gt;: Now, on your top-left side, you&amp;rsquo;ll see a blue button which says View. Change the view to category, then you&amp;rsquo;ll see the Network and connectivity settings, go there. You&amp;rsquo;ll see Networks tab. Go there. You&amp;rsquo;ll see wireless networks, click that. Now you should see the Wi-Fi.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alice&lt;/strong&gt;: I don&amp;rsquo;t.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Bob&lt;/strong&gt;: &lt;strong&gt;&lt;em&gt;FFFUUUUUUUUU&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now, this is obviously a hyperbole. And I&amp;rsquo;m not &lt;em&gt;bash&lt;/em&gt;ing GUIs (geddit?). I&amp;rsquo;m not saying CLIs should be the norm. I&amp;rsquo;m merely saying that learning how to use the CLI properly &lt;em&gt;will&lt;/em&gt; make you a power user.&lt;/p&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Thanks to the creators of these incredible tools mentioned above.&lt;/li&gt;
&lt;li&gt;Thanks to Rust and Go for modernizing CLIs and keeping them alive. If I&amp;rsquo;ve to take a guess, making CLIs in these new, shiny languages made them appealing to new developers.&lt;/li&gt;
&lt;/ul&gt;
&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;I started using &lt;code&gt;ripgrep&lt;/code&gt; before learning enough &lt;code&gt;grep&lt;/code&gt; so I can&amp;rsquo;t really tell how better it is in terms of UX. The benchmarks speak for the performance.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:2&#34;&gt;
&lt;p&gt;&lt;a href=&#34;https://xkcd.com/1168/&#34;&gt;You are correct&lt;/a&gt;&amp;#160;&lt;a href=&#34;#fnref:2&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&#34;fn:3&#34;&gt;
&lt;p&gt;I&amp;rsquo;m gonna learn &lt;code&gt;vi&lt;/code&gt; some day.&amp;#160;&lt;a href=&#34;#fnref:3&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
    <item>
      <title>Node.js Import Aliases</title>
      <link>https://abhijithota.com/posts/node-import-aliases/</link>
      <pubDate>Tue, 05 Jul 2022 17:09:43 +0530</pubDate>
      
      <guid>https://abhijithota.com/posts/node-import-aliases/</guid>
      <description>&lt;h2 id=&#34;the-problem&#34;&gt;The Problem&lt;/h2&gt;
&lt;p&gt;Oftentimes, as a Node.js codebase grows, this happens:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; { UserModel } from &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;../../../../db/models/index.js&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; { validate } from &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;../../../../lib/utils.js&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; { SERVICE_API_KEY } from &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;../../../../lib/constants.js&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There are a few problems with this:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Sensitivity to folder structure changes&lt;/strong&gt;: A good IDE or editor can auto-import but not all of them are without errors. Also, what if you change something outside your general IDE?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clutter&lt;/strong&gt;: It just simply looks bad&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&#34;the-solution&#34;&gt;The Solution&lt;/h2&gt;
&lt;p&gt;A new field in &lt;code&gt;package.json&lt;/code&gt; called &lt;code&gt;imports&lt;/code&gt; was &lt;strong&gt;stabilized in Node.js v14&lt;/strong&gt;. It was introduced earlier in Node.js v12. It follows certain rules and lets you &amp;ldquo;map&amp;rdquo; certain aliases (custom paths) to a path of your choice and also declare fallbacks.&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://nodejs.org/docs/latest-v14.x/api/packages.html#packages_imports&#34;&gt;Here&amp;rsquo;s the documentation&lt;/a&gt; for the same.&lt;/p&gt;
&lt;p&gt;We can solve our example problem by adding this to our &lt;code&gt;package.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;imports&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;#models&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;./src/db/models/index.js&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;#utils&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;./src/lib/utils.js&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;#constants&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;./src/lib/constants.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and use them in your code anywhere like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; { UserModel } from &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;#models&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; { Validate } from &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;#utils&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; { SERVICE_API_KEY } from &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;#constants&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;note&#34;&gt;Note&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;The entries in the &lt;code&gt;imports&lt;/code&gt; field of &lt;code&gt;package.json&lt;/code&gt; must be strings starting with &lt;code&gt;#&lt;/code&gt; to ensure they are disambiguated from package specifiers like &lt;code&gt;@&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The values should be relative paths from the root of the project. The root is where your &lt;code&gt;package.json&lt;/code&gt; is.&lt;/p&gt;
&lt;p&gt;In the above example, we assumed &lt;code&gt;package.json&lt;/code&gt; was at the root and all the relevant files were inside a &lt;code&gt;src&lt;/code&gt; directory.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You should see your application run fine but your IDE of choice may show some errors. Undesirable red and yellow squiggles are no one&amp;rsquo;s favorite. It would also auto-import from the actual relative path instead of the path alias. That&amp;rsquo;s no fun.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;jsconfig.json&lt;/code&gt; to the rescue&lt;/strong&gt;. (&lt;code&gt;tsconfig.json&lt;/code&gt; if you&amp;rsquo;re in a TypeScript project.)&lt;/p&gt;
&lt;p&gt;In your &lt;code&gt;jsconfig.json&lt;/code&gt;, add the following&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;compilerOptions&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;baseUrl&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;paths&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;#models&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;./src/db/models/index.js&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;#utils&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;./src/lib/utils.js&amp;#34;&lt;/span&gt;],
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;#constants&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;./src/lib/constants.js&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;The above configuration tells your IDE&amp;rsquo;s LSP to look for code in the given prefixes. &lt;a href=&#34;https://www.typescriptlang.org/tsconfig#paths&#34;&gt;Refer to the documentation&lt;/a&gt; of the property to know more.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Now we have sweet auto-imports from the desired location:&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;./2022-07-05-16-45-49.png&#34; alt=&#34;Screenshot of auto-import working desirably&#34;&gt;&lt;/p&gt;
&lt;h2 id=&#34;fallback-dependencies&#34;&gt;Fallback dependencies&lt;/h2&gt;
&lt;p&gt;As seen in the &lt;a href=&#34;https://nodejs.org/docs/latest-v14.x/api/packages.html#packages_subpath_imports&#34;&gt;documentation&lt;/a&gt;, you can also use this property for conditionally setting up fallback packages or polyfills. From the documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;// package.json
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;&lt;/span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;imports&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;#dep&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;node&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;dep-node-native&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;default&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;./dep-polyfill.js&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;dependencies&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;dep-node-native&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;^1.0.0&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;[Here, if the] import &lt;code&gt;#dep&lt;/code&gt; does not get the resolution of the external package &lt;code&gt;dep-node-native&lt;/code&gt; (including its exports in turn), and instead gets the local file &lt;code&gt;./dep-polyfill.js&lt;/code&gt; relative to the package in other environments.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;frontend-projects&#34;&gt;Frontend projects&lt;/h2&gt;
&lt;p&gt;I haven&amp;rsquo;t tried this approach with frontend applications. They generally use a bundling system like Webpack or Rollup which have their own way of resolving aliases. For example, for &lt;a href=&#34;https://vitejs.dev/&#34;&gt;Vite&lt;/a&gt; (which uses Rollup and ESBuild), you should add this to your &lt;code&gt;vite.config.js&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; path from &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;path&amp;#34;&lt;/span&gt;;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;default&lt;/span&gt; defineConfig({
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;//   Some other config
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;&lt;/span&gt;	resolve&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		alias&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;#&amp;#34;&lt;/span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;:&lt;/span&gt; path.resolve(__dirname, &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;./src&amp;#34;&lt;/span&gt;),
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	},
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;and in your &lt;code&gt;jsconfig.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;compilerOptions&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;baseUrl&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;.&amp;#34;&lt;/span&gt;,
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;paths&amp;#34;&lt;/span&gt;: {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			&lt;span style=&#34;color:#ff79c6&#34;&gt;&amp;#34;#/*&amp;#34;&lt;/span&gt;: [&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;src/*&amp;#34;&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The above configuration maps everything starting with &lt;code&gt;#&lt;/code&gt; to immediate folders and files below &lt;code&gt;src&lt;/code&gt;. YMMV.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;A designer knows he has arrived at perfection not when there is no longer anything to add but when there is no longer anything to take away&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;- Jon Bentley in Programming Pearls&lt;/p&gt;
&lt;/blockquote&gt;
</description>
    </item>
    
    <item>
      <title>Nerd-sniping myself over Go range expressions</title>
      <link>https://abhijithota.com/posts/nerd-sniping-myself-over-go-range-expressions/</link>
      <pubDate>Sat, 02 Jul 2022 17:03:48 +0530</pubDate>
      
      <guid>https://abhijithota.com/posts/nerd-sniping-myself-over-go-range-expressions/</guid>
      <description>&lt;h2 id=&#34;the-background&#34;&gt;The background&lt;/h2&gt;
&lt;p&gt;I stumbled across a situation while writing a Golang project where I needed to loop over a slice returned by a function.
The function being &lt;a href=&#34;https://pkg.go.dev/strings#Split&#34;&gt;&lt;code&gt;strings.Split&lt;/code&gt;&lt;/a&gt;.
No big deal.
I wrote the following:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt; _, id &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;range&lt;/span&gt; strings.&lt;span style=&#34;color:#50fa7b&#34;&gt;Split&lt;/span&gt;(path, &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6272a4&#34;&gt;// Something()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;There&amp;rsquo;s another way of writing the same thing:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;splitPath &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; strings.&lt;span style=&#34;color:#50fa7b&#34;&gt;Split&lt;/span&gt;(path, &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt; _, id &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;range&lt;/span&gt; splitPath {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#6272a4&#34;&gt;// Something()
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#6272a4&#34;&gt;&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;To the novice-eyed, like me, it would seem the latter was an &lt;em&gt;optimized&lt;/em&gt; version as the function is only called once before the loop and hence more &lt;em&gt;performant&lt;/em&gt;.
I did not care about the negligible performance gain I would get as the &lt;code&gt;path&lt;/code&gt; variable passed to the split function would be limited in length by application constraints.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;But what if it wasn&amp;rsquo;t?&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;tldr; It doesn&amp;rsquo;t matter how you write it.
They are both the same.
From the &lt;a href=&#34;https://go.dev/ref/spec#For_range&#34;&gt;Golang spec&lt;/a&gt;,&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The range expression x is evaluated once before beginning the loop, with one exception: if at most one iteration variable is present and len(x) is constant, the range expression is not evaluated.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This seems obvious once you know about it because it&amp;rsquo;s such a low-hanging fruit for the compiler.
It&amp;rsquo;s not even compiler optimization.
It&amp;rsquo;s compiler duty.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;From here, I&amp;rsquo;m going to write about how I &lt;a href=&#34;https://xkcd.com/356/&#34;&gt;nerd-sniped&lt;/a&gt; myself into finding the answer to this and naturally, spent around 4 hours benchmarking, trying to figure out assembly, checking the compiler optimization wiki, some trivial experimentation that confirmed my theory and one line in the spec that made it all come together.&lt;/p&gt;
&lt;p&gt;Before we proceed into this, have some context about the original scenario.
The function should split a separated string called &lt;code&gt;path&lt;/code&gt; with &lt;code&gt;/&lt;/code&gt; as delimiter and extract all integers into an array like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;ExtractInts&lt;/span&gt;(path &lt;span style=&#34;color:#8be9fd&#34;&gt;string&lt;/span&gt;) []&lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	pathIds &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt;{}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt; _, v &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;range&lt;/span&gt; strings.&lt;span style=&#34;color:#50fa7b&#34;&gt;Split&lt;/span&gt;(path, &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; v &lt;span style=&#34;color:#ff79c6&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			val, _ &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; strconv.&lt;span style=&#34;color:#50fa7b&#34;&gt;Atoi&lt;/span&gt;(v)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			pathIds = &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;append&lt;/span&gt;(pathIds, val)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; pathIds
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;benchmarking-the-two-functions&#34;&gt;Benchmarking the two functions&lt;/h2&gt;
&lt;p&gt;I put together a quick small project to bench the thing consisting of &lt;code&gt;main.go&lt;/code&gt; and &lt;code&gt;main_test.go&lt;/code&gt;:&lt;/p&gt;
&lt;h3 id=&#34;maingo&#34;&gt;&lt;code&gt;main.go&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;package&lt;/span&gt; main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;strconv&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;strings&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;WithOptim&lt;/span&gt;(path &lt;span style=&#34;color:#8be9fd&#34;&gt;string&lt;/span&gt;) &lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	pathIds &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt;{}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	pathIdsStr &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; strings.&lt;span style=&#34;color:#50fa7b&#34;&gt;Split&lt;/span&gt;(path, &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt; _, v &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;range&lt;/span&gt; pathIdsStr {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; v &lt;span style=&#34;color:#ff79c6&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			val, _ &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; strconv.&lt;span style=&#34;color:#50fa7b&#34;&gt;Atoi&lt;/span&gt;(v)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			pathIds = &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;append&lt;/span&gt;(pathIds, val)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;len&lt;/span&gt;(pathIds)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;WithoutOptim&lt;/span&gt;(path &lt;span style=&#34;color:#8be9fd&#34;&gt;string&lt;/span&gt;) &lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	pathIds &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; []&lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt;{}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt; _, v &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;range&lt;/span&gt; strings.&lt;span style=&#34;color:#50fa7b&#34;&gt;Split&lt;/span&gt;(path, &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;/&amp;#34;&lt;/span&gt;) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#ff79c6&#34;&gt;if&lt;/span&gt; v &lt;span style=&#34;color:#ff79c6&#34;&gt;!=&lt;/span&gt; &lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;&amp;#34;&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			val, _ &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; strconv.&lt;span style=&#34;color:#50fa7b&#34;&gt;Atoi&lt;/span&gt;(v)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;			pathIds = &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;append&lt;/span&gt;(pathIds, val)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;len&lt;/span&gt;(pathIds)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;main_testgo&#34;&gt;&lt;code&gt;main_test.go&lt;/code&gt;&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;package&lt;/span&gt; main
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;import&lt;/span&gt; (
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;strings&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;testing&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;var&lt;/span&gt; path = strings.&lt;span style=&#34;color:#50fa7b&#34;&gt;Repeat&lt;/span&gt;(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;734/956/831/811/&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#bd93f9&#34;&gt;100_000&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;var&lt;/span&gt; resultWithOptim &lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;BenchmarkWithOptim&lt;/span&gt;(b &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt;testing.B) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;var&lt;/span&gt; r &lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt; n &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#bd93f9&#34;&gt;0&lt;/span&gt;; n &amp;lt; b.N; n&lt;span style=&#34;color:#ff79c6&#34;&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		r = &lt;span style=&#34;color:#50fa7b&#34;&gt;WithOptim&lt;/span&gt;(path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	resultWithOptim = r
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;var&lt;/span&gt; resultWithoutOptim &lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;BenchmarkWithoutOptim&lt;/span&gt;(b &lt;span style=&#34;color:#ff79c6&#34;&gt;*&lt;/span&gt;testing.B) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;var&lt;/span&gt; r &lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt; n &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#bd93f9&#34;&gt;0&lt;/span&gt;; n &amp;lt; b.N; n&lt;span style=&#34;color:#ff79c6&#34;&gt;++&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		r = &lt;span style=&#34;color:#50fa7b&#34;&gt;WithoutOptim&lt;/span&gt;(path)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	resultWithoutOptim = r
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;The variables &lt;code&gt;r&lt;/code&gt;, &lt;code&gt;resultWithOptim&lt;/code&gt; and &lt;code&gt;resultWithoutOptim&lt;/code&gt; are needed to escape compiler optimizations and get reliable benchmarks.&lt;/p&gt;
&lt;p&gt;Check out &lt;a href=&#34;https://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go&#34;&gt;this section&lt;/a&gt; from the &lt;a href=&#34;https://dave.cheney.net/2013/06/30/how-to-write-benchmarks-in-go#compiler-optimisation&#34;&gt;awesome benchmarking article&lt;/a&gt; by Dave Cheney.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;results&#34;&gt;Results&lt;/h2&gt;
&lt;p&gt;I ran the benchmark a couple of times.&lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;In most cases, it was neck-and-neck:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithoutOptim-8     63	 &lt;span style=&#34;color:#bd93f9&#34;&gt;18067614&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithOptim-8        64	 &lt;span style=&#34;color:#bd93f9&#34;&gt;17833483&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3.282s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithoutOptim-8     64	 &lt;span style=&#34;color:#bd93f9&#34;&gt;17879142&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithOptim-8        66	 &lt;span style=&#34;color:#bd93f9&#34;&gt;17943536&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3.287s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithoutOptim-8     66	 &lt;span style=&#34;color:#bd93f9&#34;&gt;17915000&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithOptim-8        66	 &lt;span style=&#34;color:#bd93f9&#34;&gt;17567501&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3.292s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithoutOptim-8     56	 &lt;span style=&#34;color:#bd93f9&#34;&gt;18344452&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithOptim-8        57	 &lt;span style=&#34;color:#bd93f9&#34;&gt;17649186&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2.090s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;In some cases the one with &lt;em&gt;optimizations&lt;/em&gt; performed better:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithoutOptim-8     64	 &lt;span style=&#34;color:#bd93f9&#34;&gt;18446009&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithOptim-8        73	 &lt;span style=&#34;color:#bd93f9&#34;&gt;18054308&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3.548s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithoutOptim-8     63	 &lt;span style=&#34;color:#bd93f9&#34;&gt;18466071&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithOptim-8        70	 &lt;span style=&#34;color:#bd93f9&#34;&gt;18600002&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3.422s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithOptim-8        64	 &lt;span style=&#34;color:#bd93f9&#34;&gt;18917323&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithoutOptim-8     58	 &lt;span style=&#34;color:#bd93f9&#34;&gt;18092279&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3.215s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;But in some cases the one without any &lt;em&gt;optimizations&lt;/em&gt; performed faster!&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-sh&#34; data-lang=&#34;sh&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithOptim-8        55	 &lt;span style=&#34;color:#bd93f9&#34;&gt;18848131&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithoutOptim-8     68	 &lt;span style=&#34;color:#bd93f9&#34;&gt;19239865&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2.395s
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithOptim-8        57	 &lt;span style=&#34;color:#bd93f9&#34;&gt;18323290&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;BenchmarkWithoutOptim-8     63	 &lt;span style=&#34;color:#bd93f9&#34;&gt;17598465&lt;/span&gt; ns/op
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2.206s
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;digging-into-the-why&#34;&gt;Digging into the why&lt;/h2&gt;
&lt;p&gt;The first resource I came across was the &lt;a href=&#34;https://github.com/golang/go/wiki/CompilerOptimizations&#34;&gt;Compiler And Runtime Optimizations wiki&lt;/a&gt; which stated nothing about such behaviour.&lt;/p&gt;
&lt;p&gt;I also tried converting the code into Assembly using &lt;a href=&#34;https://go.godbolt.org/&#34;&gt;Compiler Explorer&lt;/a&gt; but couldn&amp;rsquo;t understand any of it.&lt;/p&gt;
&lt;p&gt;Was the compiler calling the function only once? Are the 2 ways of writing same? I had no way of knowing. Then I thought of something so trivial I felt dumb.&lt;/p&gt;
&lt;h2 id=&#34;the-trivial-experiment&#34;&gt;The trivial experiment&lt;/h2&gt;
&lt;p&gt;Consider the following code:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-go&#34; data-lang=&#34;go&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Nums&lt;/span&gt;() []&lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Nums called\n&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; []&lt;span style=&#34;color:#8be9fd&#34;&gt;int&lt;/span&gt;{&lt;span style=&#34;color:#bd93f9&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#bd93f9&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#bd93f9&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#bd93f9&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#bd93f9&#34;&gt;5&lt;/span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Loop&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt; _, v &lt;span style=&#34;color:#ff79c6&#34;&gt;:=&lt;/span&gt; &lt;span style=&#34;color:#ff79c6&#34;&gt;range&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;Nums&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;print&lt;/span&gt;(v)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;func&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;main&lt;/span&gt;() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#50fa7b&#34;&gt;Loop&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;And surely enough, &lt;code&gt;Nums called&lt;/code&gt; is only printed once to &lt;code&gt;STDOUT&lt;/code&gt;.
This felt so obvious once I realised it.&lt;/p&gt;
&lt;h2 id=&#34;eureka--facepalm-moment&#34;&gt;Eureka + Facepalm moment&lt;/h2&gt;
&lt;p&gt;Googling &lt;strong&gt;&amp;ldquo;go range internals&amp;rdquo;&lt;/strong&gt; gave me &lt;a href=&#34;https://garbagecollected.org/2017/02/22/go-range-loop-internals/&#34;&gt;this article by Robbie V&lt;/a&gt; which sent me to the &lt;a href=&#34;https://go.dev/ref/spec#For_range&#34;&gt;Go language specification&lt;/a&gt; where I found this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;The range expression x is evaluated once before beginning the loop, with one exception: if at most one iteration variable is present and len(x) is constant, the range expression is not evaluated.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&#34;conclusion&#34;&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;There&amp;rsquo;s nothing much to conclude but there&amp;rsquo;s a lesson to learn.
In Robbie V&amp;rsquo;s article, the Step 1 was to &lt;a href=&#34;https://en.wikipedia.org/wiki/RTFM&#34;&gt;RTFM&lt;/a&gt;.
Unlike that, I dove right into benchmarking which was like comparing two sum functions which returned &lt;code&gt;a + b&lt;/code&gt; vs. &lt;code&gt;b + a&lt;/code&gt;.
I discovered a lot but this shouldn&amp;rsquo;t have taken so much of my time.&lt;/p&gt;
&lt;p&gt;It&amp;rsquo;s a reminder on how we can take some slightly interesting things, like the one I talked about here, for granted and never realise the machinery of it.&lt;/p&gt;
&lt;p&gt;As to which function is better to write, that would be an opinion.&lt;/p&gt;
&lt;h2 id=&#34;other-languages&#34;&gt;Other languages&lt;/h2&gt;
&lt;p&gt;I tried the same thing in a few other languages I&amp;rsquo;ve coded in because I never realised this:&lt;/p&gt;
&lt;h3 id=&#34;javascript&#34;&gt;JavaScript&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-js&#34; data-lang=&#34;js&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;function&lt;/span&gt; nums() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	console.debug(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#39;Nums called&amp;#39;&lt;/span&gt;);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; [&lt;span style=&#34;color:#bd93f9&#34;&gt;1&lt;/span&gt;, &lt;span style=&#34;color:#bd93f9&#34;&gt;2&lt;/span&gt;, &lt;span style=&#34;color:#bd93f9&#34;&gt;3&lt;/span&gt;, &lt;span style=&#34;color:#bd93f9&#34;&gt;4&lt;/span&gt;, &lt;span style=&#34;color:#bd93f9&#34;&gt;5&lt;/span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;function&lt;/span&gt; loop() {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	&lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt; (&lt;span style=&#34;color:#ff79c6&#34;&gt;const&lt;/span&gt; v &lt;span style=&#34;color:#ff79c6&#34;&gt;of&lt;/span&gt; nums()) {
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;		console.debug(v);
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;	}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;loop();
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h3 id=&#34;python&#34;&gt;Python&lt;/h3&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#282a36;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-py&#34; data-lang=&#34;py&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;nums&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;print&lt;/span&gt;(&lt;span style=&#34;color:#f1fa8c&#34;&gt;&amp;#34;Nums called&amp;#34;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;return&lt;/span&gt; [&lt;span style=&#34;color:#bd93f9&#34;&gt;1&lt;/span&gt;,&lt;span style=&#34;color:#bd93f9&#34;&gt;2&lt;/span&gt;,&lt;span style=&#34;color:#bd93f9&#34;&gt;3&lt;/span&gt;,&lt;span style=&#34;color:#bd93f9&#34;&gt;4&lt;/span&gt;,&lt;span style=&#34;color:#bd93f9&#34;&gt;5&lt;/span&gt;]
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#ff79c6&#34;&gt;def&lt;/span&gt; &lt;span style=&#34;color:#50fa7b&#34;&gt;loop&lt;/span&gt;():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#ff79c6&#34;&gt;for&lt;/span&gt; l &lt;span style=&#34;color:#ff79c6&#34;&gt;in&lt;/span&gt; nums():
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#8be9fd;font-style:italic&#34;&gt;print&lt;/span&gt;(l)
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;loop()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class=&#34;footnotes&#34; role=&#34;doc-endnotes&#34;&gt;
&lt;hr&gt;
&lt;ol&gt;
&lt;li id=&#34;fn:1&#34;&gt;
&lt;p&gt;Using &lt;code&gt;go test -bench=. -run=xxx&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Specs:&lt;/p&gt;
&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;goos: linux 
goarch: amd64 
cpu: Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Order of function execution was changed a few times.&amp;#160;&lt;a href=&#34;#fnref:1&#34; class=&#34;footnote-backref&#34; role=&#34;doc-backlink&#34;&gt;&amp;#x21a9;&amp;#xfe0e;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/div&gt;
</description>
    </item>
    
  </channel>
</rss>
