<?xml version="1.0" encoding="UTF-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title>antoDev - Yet another place where a developer rants</title>
    <link href="https://www.antopiras.dev" />
    <updated>Tue Jan 27 2026 14:29:46 GMT+0000 (Coordinated Universal Time)</updated>
    <author>
        <name>Antonio Piras</name>
    </author>
    <id>https://www.antopiras.dev/</id>
    
        <entry>
            <id>https://www.antopiras.dev/blog/2021-02-15-obligatory-first-post/#0</id>
            <title>Obligatory first post</title>
            <link href="https://www.antopiras.dev/blog/2021-02-15-obligatory-first-post/#0" />
            <updated>Sat Feb 20 2021 21:18:20 GMT+0000 (Coordinated Universal Time)</updated>
            
            
            <category term="notes" />
            
            
            <summary>I guess this is where I write about the need for this blog... 🤔</summary>
            <content type="html">&lt;p&gt;&lt;img src=&quot;/images/uploads/panda_big.png&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I probably won&#39;t update this blog as much, but I felt like I needed someplace to store the occasional experiment as I continue (hopefully 🤞🏻) to learn during my career as a software developer for the web.&lt;/p&gt;
&lt;p&gt;So... stay tuned for anything that might come! 🚀&lt;/p&gt;
</content>
        </entry>
    
        <entry>
            <id>https://www.antopiras.dev/blog/2021-03-01-11ty-sass-with-gulp-sass/#1</id>
            <title>I like my eleventy with a side of SCSS</title>
            <link href="https://www.antopiras.dev/blog/2021-03-01-11ty-sass-with-gulp-sass/#1" />
            <updated>Mon Mar 01 2021 07:24:45 GMT+0000 (Coordinated Universal Time)</updated>
            
            
            <category term="11ty" />
            
            <category term="tips" />
            
            
            <summary>I haven&#39;t had an easy time setting up a SASS preprocessor, autoprefixer and minifier in my 11ty blog so I wanted to write a short guide on how I managed to do it.</summary>
            <content type="html">&lt;p&gt;If you&#39;re like me and you cannot stand writing CSS without SASS and you want to enable it for your eleventy site, this is the right place for you.&lt;/p&gt;
&lt;p&gt;Coming from the React world I immediately thought of &lt;strong&gt;gulp&lt;/strong&gt; when I decided to include sass in my project, so I jumped at the possibility of using &lt;strong&gt;gulp tasks&lt;/strong&gt; to compile SCSS and add vendor prefixes automatically (I hate them and I google &lt;a href=&quot;http://shouldiprefix.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;What CSS to prefix?&lt;/a&gt;{rel=&amp;quot;noopener noreferrer&amp;quot; target=&amp;quot;_blank&amp;quot;} almost every day).&lt;/p&gt;
&lt;p&gt;Since we&#39;re writing gulp tasks I thought a minified CSS would also be a good idea.&lt;br&gt;
So, if you&#39;re interested in how I did it, let&#39;s begin 💪🏻&lt;/p&gt;
&lt;h2 id=&quot;what-is-gulp%3F&quot; tabindex=&quot;-1&quot;&gt;What is Gulp? &lt;a class=&quot;header-anchor&quot; href=&quot;#what-is-gulp%3F&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Gulp is a tool that lets us automate the trivial tasks that frontend web development usually requires like spinning up servers, processing SCSS and optimizing assets like images or even scripts. It also provides hot reloading when developing.&lt;/p&gt;
&lt;h2 id=&quot;setting-things-up&quot; tabindex=&quot;-1&quot;&gt;Setting things up &lt;a class=&quot;header-anchor&quot; href=&quot;#setting-things-up&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first thing I did was add the required packages, to my site&#39;s directory:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yarn add --dev gulp gulp-autoprefixer gulp-cssnano gulp-sass
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;As &lt;a href=&quot;https://github.com/hillonyechekwa&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;hillonyechekwa&lt;/a&gt; pointed out in the comments, you also need to have a &lt;em&gt;sass compiler&lt;/em&gt; installed in your project. You can install it with:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;yarn add --dev sass
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;gulp-tasks&quot; tabindex=&quot;-1&quot;&gt;Gulp tasks &lt;a class=&quot;header-anchor&quot; href=&quot;#gulp-tasks&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To use gulp we need to set up three tasks.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;a &amp;quot;css&amp;quot; task to&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;compile our SCSS files to CSS&lt;/li&gt;
&lt;li&gt;add vendor prefixes when required&lt;/li&gt;
&lt;li&gt;minify the code&lt;/li&gt;
&lt;/ul&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&amp;quot;watch&amp;quot; and &amp;quot;build&amp;quot; tasks to trigger the original &amp;quot;css&amp;quot; task when editing files (watch) or building the site (build).&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A gulp task is just a function that gets a name assigned and can be called by Gulp to edit our files.&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; gulp &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;gulp&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; sass &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;gulp-sass&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; autoprefixer &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;gulp-autoprefixer&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; cssnano &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;gulp-cssnano&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;css&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; gulp&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;src&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;./src/css/style.scss&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//source file to retrieve&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;sass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//sends the source file to the sass plugin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;autoprefixer&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//sends the source file to the autoprefixer plugin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;cssnano&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//sends the source file to the minifier plugin&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;on&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;error&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; sass&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;logError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//log errors&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;pipe&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;dest&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;./_site/css&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;//outputs the result in our public dir&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;watch&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;watch&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;./src/css/*.scss&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parallel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;css&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;task&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;build&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; gulp&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;parallel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;css&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;watch&lt;/code&gt; and &lt;code&gt;build&lt;/code&gt; tasks call &lt;code&gt;gulp.parallel()&lt;/code&gt; to nest the previous task inside them.&lt;/p&gt;
&lt;p&gt;These tasks can be called from the terminal via &lt;code&gt;gulp watch&lt;/code&gt; or &lt;code&gt;gulp build&lt;/code&gt;.&lt;/p&gt;
&lt;h2 id=&quot;run-gulp-automatically&quot; tabindex=&quot;-1&quot;&gt;Run gulp automatically &lt;a class=&quot;header-anchor&quot; href=&quot;#run-gulp-automatically&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We don&#39;t want to have to run those commands every time we edit our SCSS files, of course. To automate this, we need to add these tasks to our &lt;code&gt;package.json&lt;/code&gt; file:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token string-property property&quot;&gt;&quot;scripts&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;serve&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gulp build &amp;amp; gulp watch &amp;amp; eleventy --serve&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt; &lt;span class=&quot;token string-property property&quot;&gt;&quot;build&quot;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gulp build &amp;amp;&amp;amp; yarn eleventy&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, whenever we run one of those two yarn scripts, our gulp tasks will be called before eleventy can parse our site.&lt;/p&gt;
&lt;h2 id=&quot;do-not-be-like-me...&quot; tabindex=&quot;-1&quot;&gt;Do not be like me... &lt;a class=&quot;header-anchor&quot; href=&quot;#do-not-be-like-me...&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;...and read the eleventy documentation!&lt;/p&gt;
&lt;p&gt;When setting up all of this I was stomped for a solid hour trying to figure out why changes to my SCSS files weren&#39;t causing the browser to reload.&lt;br&gt;
As it turns out, eleventy does not automatically watch any file in our project&#39;s directory, but we can make it do so, by adding this line to our &lt;code&gt;.eleventj.js&lt;/code&gt; file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;eleventyConfig.addWatchTarget(&#39;src/css/&#39;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that eleventy will not add a watch for files or folders that are in .gitignore.&lt;br&gt;
To change that behaviour we need to add another line to &lt;code&gt;.eleventy.js&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;eleventyConfig.setUseGitIgnore(false)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;...that&#39;s it. Now you should have everything you need to compile .scss files! 🚀&lt;/p&gt;
</content>
        </entry>
    
        <entry>
            <id>https://www.antopiras.dev/blog/2021-03-13-w-s-and-no-im-not-swearing/#2</id>
            <title>Time to start learning how to regex</title>
            <link href="https://www.antopiras.dev/blog/2021-03-13-w-s-and-no-im-not-swearing/#2" />
            <updated>Sat Mar 13 2021 11:03:10 GMT+0000 (Coordinated Universal Time)</updated>
            
            
            <category term="regex" />
            
            <category term="tips" />
            
            
            <summary>I&#39;ve always had a &quot;fake it &#39;till you make it&quot; approach to writing regexes. This ends today.</summary>
            <content type="html">&lt;p&gt;It&#39;s time for me to come out: I&#39;ve been working as a professional developer for 6 years and I&#39;ve never managed to write a regex without intense googling and the help of &lt;a href=&quot;https://regex101.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;regex 101&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;This needs to stop, so I decided to take advantage of the current lockdown and spend my Saturday morning doing some googling, and as it turns out... regular expressions are not that complicated. At all.&lt;/p&gt;
&lt;figure&gt;
    &lt;img src=&quot;/images/uploads/how_to_regex.jpeg&quot; alt=&quot;How to regex&quot; title=&quot;How to regex&quot; /&gt;
    &lt;figcaption class=&quot;image-caption-text&quot;&gt;Image from &lt;a href=&quot;https://twitter.com/garabatokid&quot; rel=&quot;noopener noreferrer&quot; target=&quot;_blank&quot; aria-label=&quot;Image from garabatokid&quot;&gt;garabatokid&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;p&gt;After a couple of minutes of googling, I landed on &lt;a href=&quot;https://regexone.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;RegexOne&lt;/a&gt; and found a great and exhaustive tutorial that takes you through the basics of writing regular expressions.&lt;br&gt;
The lessons are clear and concise and offer real-world examples with a nifty little exercise at the end of each chapter.&lt;/p&gt;
&lt;p&gt;It took me about an hour to go through the 15 lessons of the basic tutorial touching everything, from the ABCs to &lt;em&gt;capturing groups.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Once you&#39;re done with all the lessons you can take the &lt;em&gt;Practice Problems&lt;/em&gt; which are useful tests that push you to write regular expressions that help in a developer&#39;s everyday life like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;matching email addresses&lt;/li&gt;
&lt;li&gt;parsing HTML elements&lt;/li&gt;
&lt;li&gt;extract pieces of information from a log file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;... and more.&lt;/p&gt;
&lt;p&gt;So, whether you&#39;re a seasoned developer or just starting in this world, I highly suggest you try out this tutorial and use &lt;em&gt;Regex101&lt;/em&gt; as a reference and code generator (this utility is very useful!) for more complex regular expressions.&lt;/p&gt;
&lt;p&gt;I&#39;ll be diving more into this and I&#39;ll probably end up writing a follow-up, but for now, I&#39;d say it&#39;s been a productive Saturday morning.&lt;/p&gt;
</content>
        </entry>
    
        <entry>
            <id>https://www.antopiras.dev/blog/2021-03-22-do-not-use-the-css-background-shorthand-as-a-prop-in-react/#3</id>
            <title>Do not use the CSS background shorthand property in React</title>
            <link href="https://www.antopiras.dev/blog/2021-03-22-do-not-use-the-css-background-shorthand-as-a-prop-in-react/#3" />
            <updated>Mon Mar 22 2021 18:07:16 GMT+0000 (Coordinated Universal Time)</updated>
            
            
            <category term="react" />
            
            <category term="javascript" />
            
            
            <summary>Why the CSS background shorthand property in React can cause problems if used with the backgroundSize property.</summary>
            <content type="html">&lt;h2 id=&quot;the-problem&quot; tabindex=&quot;-1&quot;&gt;The problem &lt;a class=&quot;header-anchor&quot; href=&quot;#the-problem&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I recently came across this bug at work and it took me a minute to figure it out.&lt;br&gt;
What I had was something like this:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;image-container&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    style&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;absolute&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;top&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;left&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;width&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;height&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;background&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;transparent url(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;image_url&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;) no-repeat center center&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;backgroundSize&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;contain&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;   &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Everything seems okay, right? Well, in theory.&lt;br&gt;
But as soon as the application started, I noticed that the &lt;code&gt;backgroundSize&lt;/code&gt; property was not working!&lt;/p&gt;
&lt;h2 id=&quot;let%E2%80%99s-get-googling&quot; tabindex=&quot;-1&quot;&gt;Let’s get googling &lt;a class=&quot;header-anchor&quot; href=&quot;#let%E2%80%99s-get-googling&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After inspecting the output HTML and a bit of googling, I came across this &lt;a href=&quot;https://github.com/facebook/react/issues/5030&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;closed issue on React&#39;s Github&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Apparently, using the CSS &lt;code&gt;background&lt;/code&gt; shorthand property with a &lt;code&gt;backgroundSize&lt;/code&gt; prop causes this last property to be cleared &lt;strong&gt;if and when&lt;/strong&gt; the &lt;code&gt;background&lt;/code&gt; property is updated.&lt;/p&gt;
&lt;h2 id=&quot;fair-enough%2C-let%E2%80%99s-fix-it&quot; tabindex=&quot;-1&quot;&gt;Fair enough, let’s fix it &lt;a class=&quot;header-anchor&quot; href=&quot;#fair-enough%2C-let%E2%80%99s-fix-it&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A quick and easy fix is to explicitly set every property by expanding the shorthand property:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;div&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    className&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;image-container&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    style&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;position&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;absolute&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;top&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;top&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;left&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;left&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;width&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;height&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;%&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;backgroundColor&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;transparent&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;backgroundImage&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;url(&lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;image_url&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;backgroundRepeat&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;no-repeat&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;backgroundPosition&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;center center&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;backgroundSize&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;contain&#39;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;   &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s all! I hope this is useful to you 💪🏻&lt;/p&gt;
</content>
        </entry>
    
        <entry>
            <id>https://www.antopiras.dev/blog/2021-03-30-usecallback-i-dont-know-her/#4</id>
            <title>useCallback? I don&#39;t know her</title>
            <link href="https://www.antopiras.dev/blog/2021-03-30-usecallback-i-dont-know-her/#4" />
            <updated>Tue Mar 30 2021 11:26:29 GMT+0000 (Coordinated Universal Time)</updated>
            
            
            <category term="react" />
            
            <category term="js" />
            
            
            <summary>Should you wrap every single function in useCallback? Or should you go for code readability and hope for the best? Well, it depends.</summary>
            <content type="html">&lt;p&gt;Spoiler alert: this is a rant that &lt;em&gt;might turn into something useful&lt;/em&gt;. Maybe.&lt;/p&gt;
&lt;h2 id=&quot;i-don%E2%80%99t-know-react&quot; tabindex=&quot;-1&quot;&gt;I don’t know React &lt;a class=&quot;header-anchor&quot; href=&quot;#i-don%E2%80%99t-know-react&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My React journey has been a constant learning experience, but there’s something about React that has been bugging me lately.&lt;/p&gt;
&lt;p&gt;Ever since I changed company last year, I found myself in a new codebase, and with it came something I never saw before: an &lt;em&gt;odd quantity&lt;/em&gt; of useCallback in every single component of the app.&lt;/p&gt;
&lt;p&gt;I have to admit I was responsible for most of a medium/big react app at my previous company and it always ran smoothly even without this heavy optimization.&lt;br&gt;
Of course, thanks to my beloved impostor syndrome I immediately thought “Oh god, I’m a terrible developer, I don’t know React, I never use memoization”. You know, the usual.&lt;/p&gt;
&lt;h2 id=&quot;pr-review-anxiety&quot; tabindex=&quot;-1&quot;&gt;PR Review anxiety &lt;a class=&quot;header-anchor&quot; href=&quot;#pr-review-anxiety&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since I was not familiar with the concept of useCallback, useMemo (and lodash &lt;code&gt;memoize&lt;/code&gt;!) I immediately documented myself, but all I could find were articles and tutorials about how to use these hooks and functions, and none of them touched deeply on the dependency array, which is something I constantly screw up!&lt;/p&gt;
&lt;p&gt;Lately, I’ve been reading a lot on the use of &lt;code&gt;useCallback&lt;/code&gt; and &lt;code&gt;useMemo&lt;/code&gt; in a React app (useful links at the end of the post ✏️) because I wasn’t comfortable with my &lt;em&gt;fake it ‘till you make it&lt;/em&gt; approach to this part of the framework and what I read was… well, more confusing than ever.&lt;/p&gt;
&lt;h2 id=&quot;you-shall-not-optimize-(blindly)&quot; tabindex=&quot;-1&quot;&gt;You shall not optimize (blindly) &lt;a class=&quot;header-anchor&quot; href=&quot;#you-shall-not-optimize-(blindly)&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;blockquote cite=&quot;https://kentcdodds.com/blog/usememo-and-usecallback&quot;&gt;
&lt;p&gt;&lt;strong&gt;Performance optimizations are not free. They ALWAYS come with a cost but do NOT always come with a benefit to offset that cost.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Therefore, &lt;em&gt;optimize responsibly&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&lt;span class=&quot;author&quot;&gt;Kent C. Dodds&lt;/span&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Pretty much every article I read said something along the lines of &amp;quot;it’s wrong to optimize before profiling the application and every optimization comes with a cost that can easily outweigh the benefit&amp;quot;.&lt;/p&gt;
&lt;p&gt;In all the articles and comments on Stack Overflow I could find, pretty much everyone agreed that there are cases where it’s pretty clear that memoization help:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Big, &lt;em&gt;very big&lt;/em&gt; lists&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Passing down components to optimized children&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Referential equality checks in hooks dependencies&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Computationally expensive functions (we’re talking prime numbers calculations!)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I’ll stop here, for now.&lt;br&gt;
My goal is to keep digging into this argument and try to profile the application I maintain at work and come up with definitive data on which components actually benefit from memoization and which are actually slower thanks to it.&lt;/p&gt;
&lt;p&gt;…stay tuned!&lt;/p&gt;
&lt;p&gt;📚 As promised, I’ll leave here the list of articles I read on the subject:&lt;/p&gt;
&lt;div class=&quot;resources&quot;&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://kentcdodds.com/blog/usememo-and-usecallback&quot; rel=&quot;noopener noreferrer&quot; target=&quot;_blank&quot; aria-label=&quot;When to useMemo and useCallback&quot;&gt;When to useMemo and useCallback&lt;/a&gt;
&lt;li&gt;&lt;a href=&quot;https://dmitripavlutin.com/dont-overuse-react-usecallback/&quot; rel=&quot;noopener noreferrer&quot; target=&quot;_blank&quot; aria-label=&quot;Your Guide to React.useCallback()&quot;&gt;Your Guide to React.useCallback()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://aheadcreative.co.uk/articles/when-to-use-react-usecallback/#:~:text=You%20should%20avoid%20seeing%20useCallback,a%20detrimental%20impact%20on%20performance.&quot; rel=&quot;noopener noreferrer&quot; target=&quot;_blank&quot; aria-label=&quot;When to use React.useCallback() | Ahead Creative&quot;&gt;When to use React.useCallback() | Ahead Creative&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reacttraining.com/blog/react-inline-functions-and-performance/&quot; rel=&quot;noopener noreferrer&quot; target=&quot;_blank&quot; aria-label=&quot;React Training: React, Inline Functions, and Performance&quot;&gt;React Training: React, Inline Functions, and Performance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.to/nioufe/you-should-not-use-lodash-for-memoization-3441&quot; rel=&quot;noopener noreferrer&quot; target=&quot;_blank&quot; aria-label=&quot;Lodash Memoize: You should not use lodash for memoization - DEV Community&quot;&gt;Lodash Memoize: You should not use lodash for memoization - DEV Community&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
</content>
        </entry>
    
        <entry>
            <id>https://www.antopiras.dev/blog/2021-04-17-add-comments-to-your-static-blog-with-utterances/#5</id>
            <title>Add comments to your static blog with utterances</title>
            <link href="https://www.antopiras.dev/blog/2021-04-17-add-comments-to-your-static-blog-with-utterances/#5" />
            <updated>Sat Apr 17 2021 11:14:35 GMT+0000 (Coordinated Universal Time)</updated>
            
            
            <category term="11ty" />
            
            <category term="comments" />
            
            
            <summary>How to add a comment section to a static blog using GitHub issues</summary>
            <content type="html">&lt;p&gt;A while ago I was looking for a way to add a comment section to my static blog and this is the result of all the googling I did on the subject 💪🏻&lt;/p&gt;
&lt;h2 id=&quot;what%E2%80%99s-on-the-menu&quot; tabindex=&quot;-1&quot;&gt;What’s on the menu &lt;a class=&quot;header-anchor&quot; href=&quot;#what%E2%80%99s-on-the-menu&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Disqus&lt;/h3&gt;
&lt;p&gt;The first solution I looked into is &lt;a href=&quot;https://blog.disqus.com/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Disqus&lt;/a&gt;, but I soon decided not to use it simply because, while it’s a valid software with a huge community, it has some glaring flaws (at least for me):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;the basic plan comes with ads&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;it tracks its users&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;if anonymous commenting is turned off, people need to create a Disqus account (more on that later)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;it’s way too complex for my needs&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Jamstack Comments Engine&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://jamstack-comments.netlify.app/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Jamstack Comments Engine&lt;/a&gt; “… is an example of how a Jamstack site can implement comments.”&lt;/p&gt;
&lt;p&gt;Ok, this is not exactly the first search result that comes up when googling “static blog comments”, but I ran into it and considered it simply because, from a developer point of view, it is a very smart approach.&lt;/p&gt;
&lt;p&gt;The solution proposed here consists of a combination of &lt;a href=&quot;https://docs.netlify.com/forms/setup/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Netlify Forms&lt;/a&gt; and its Submission API to trigger a new build of the web every time a comment is posted, after it’s approved by a moderator. It additionally explains how to create a Lambda function to get notified on Slack whenever a new comment comes in.&lt;/p&gt;
&lt;p&gt;While I found this approach very interesting, I still have a day job and didn’t want to embark on the somewhat long, even though &lt;em&gt;very well documented&lt;/em&gt;, process.&lt;/p&gt;
&lt;h2 id=&quot;utterances&quot; tabindex=&quot;-1&quot;&gt;utterances &lt;a class=&quot;header-anchor&quot; href=&quot;#utterances&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After I gave up on the comments feature (no one reads my two-month-old blog anyway), I stumbled upon &lt;a href=&quot;https://utteranc.es/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;utterances&lt;/a&gt; and it blew my mind with its simplicity. It took me 10 minutes to add it to this blog, build time included.&lt;/p&gt;
&lt;figure&gt;
    &lt;img class=&quot;rounded-corners&quot; src=&quot;/images/uploads/cleanshot-2021-04-17-at-12.53.16-2x.jpg&quot; alt=&quot;Preview of the comments on the utterances homepage&quot; title=&quot;Preview of the comments on the utterances homepage&quot; /&gt;
    &lt;figcaption class=&quot;image-caption-text&quot;&gt;This is how the comment section will appear, from utterances homepage.&lt;/a&gt;&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;h3&gt;The perks&lt;/h3&gt;
&lt;p&gt;Straight from their page:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;It’s &lt;a href=&quot;https://github.com/utterance&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;open source&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It doesn’t track users&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;No ads 👏🏻&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;All the comments data is stored in GitHub issues&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;It’s lightweight&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;So, how does it work?&lt;/h3&gt;
&lt;p&gt;First of all, it uses GitHub issues to track comments, based on the post title: the first person to comment on a blog post will trigger the creation of a related issue and future comments on the same post will end up in that issue.&lt;/p&gt;
&lt;p&gt;Smart, right? 🔮&lt;/p&gt;
&lt;p&gt;The only requirements are that the repository connected to the app needs to be public and have the &lt;a href=&quot;https://github.com/apps/utterances&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;utterances app&lt;/a&gt; installed on it.&lt;/p&gt;
&lt;p&gt;Users will comment using their GitHub account, which is perfect for a tech/programming blog.&lt;/p&gt;
&lt;p&gt;Oh, and it comes with 8 themes that will play well with most of the colour palette of the blogs out there!&lt;/p&gt;
&lt;h2 id=&quot;how-to-install-it&quot; tabindex=&quot;-1&quot;&gt;How to install it &lt;a class=&quot;header-anchor&quot; href=&quot;#how-to-install-it&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Their page is pretty straightforward: just follow the configuration steps (repository name, optional label for the issues, chosen theme and even issue title format!) and you’re left with a script tag to add to your blog template:&lt;/p&gt;
&lt;pre class=&quot;language-js&quot;&gt;&lt;code class=&quot;language-js&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;script&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    src&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://utteranc.es/client.js&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    repo&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;antoBit/antodev&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    issue&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;term&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;title&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    label&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;💬&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    theme&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;dark-blue&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    crossorigin&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;anonymous&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    async&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt;script&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that the issue label supports emojis! 🎉&lt;/p&gt;
&lt;p&gt;After that, just remember to install the &lt;em&gt;utterances app&lt;/em&gt; on the same repository you provided in the &lt;code&gt;repo&lt;/code&gt; attribute and you’re done!&lt;/p&gt;
&lt;h2 id=&quot;shameless-plug&quot; tabindex=&quot;-1&quot;&gt;Shameless plug &lt;a class=&quot;header-anchor&quot; href=&quot;#shameless-plug&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you found this post useful and you liked it, why don’t you leave a comment below? I’d like to know what you think about this.&lt;/p&gt;
&lt;p&gt;Thanks for reading!&lt;/p&gt;
</content>
        </entry>
    
        <entry>
            <id>https://www.antopiras.dev/blog/2021-05-15-using-the-mediastream-web-api-to-record-screen-camera-and-audio/#6</id>
            <title>Using the MediaStream Web API to record screen, camera and audio</title>
            <link href="https://www.antopiras.dev/blog/2021-05-15-using-the-mediastream-web-api-to-record-screen-camera-and-audio/#6" />
            <updated>Sat May 15 2021 18:07:06 GMT+0000 (Coordinated Universal Time)</updated>
            
            
            <category term="javascript" />
            
            <category term="api" />
            
            
            <summary>Record screen, camera and audio in javascript using the MediaStream Web API</summary>
            <content type="html">&lt;p&gt;Lately at work, I had to create an app to let our users record their screen or camera and audio &lt;em&gt;directly in the browser&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;While the MDN web docs are well documented, there were a couple of issues I encountered down the road and I had to do quite a bit of googling around, testing some NPM packages and fight off weird browser compatibility issues, so… I thought I would spare the souls of my fellow developers after me 😅&lt;/p&gt;
&lt;h2 id=&quot;the-idea&quot; tabindex=&quot;-1&quot;&gt;The idea &lt;a class=&quot;header-anchor&quot; href=&quot;#the-idea&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;What I want to achieve here is fairly simple: let the users record either their screen or their camera &lt;em&gt;plus audio&lt;/em&gt; and obtain a video of the recording.&lt;/p&gt;
&lt;p&gt;Recording the camera and audio is fairly simple since it uses the same API interface to record both devices and we have to work with a single stream.&lt;/p&gt;
&lt;p&gt;Recording screen and audio requires us to merge two different media streams from two different APIs, but as you will see this is not that complicated.&lt;/p&gt;
&lt;p&gt;Let’s outline what we’re going to do:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Use the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;MediaDevices interface&lt;/a&gt; to capture a &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/MediaStream&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;MediaStream&lt;/a&gt; from the user’s devices&lt;/li&gt;
&lt;li&gt;Record the media from the stream using the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;MediaRecorder API&lt;/a&gt; to generate a Blob object containing the recorded data&lt;/li&gt;
&lt;li&gt;Create a new &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/Blob&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;Blob&lt;/a&gt; from the MediaRecorder data and generate a URL from it to download the video from&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;time-to-write-some-code&quot; tabindex=&quot;-1&quot;&gt;Time to write some code &lt;a class=&quot;header-anchor&quot; href=&quot;#time-to-write-some-code&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;DISCLAIMER&lt;/em&gt;: Most of the code here is meant to be used as an example.&lt;/p&gt;
&lt;p&gt;In order to keep it as simple as possible, I won’t be worrying about checking if the browser supports the API used in the code (at the time of writing, only Chrome and Firefox do) and so I won’t add any error handling, try/catch statements, etc….&lt;/p&gt;
&lt;p&gt;Please don’t put any of this in production, I decline any responsibility in that case 🤣&lt;/p&gt;
&lt;h3&gt;Camera and audio stream&lt;/h3&gt;
&lt;p&gt;To record the webcam and the audio from a microphone (either the computer internal microphone or an external one) we can use the &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;MediaDevices&lt;/a&gt; interface:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; mediaConstraints &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;video&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;width&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1280&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;height&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;720&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;audio&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;echoCancellation&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;noiseSuppression&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;sampleRate&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;44100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;captureMediaDevices&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; stream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mediaDevices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getUserMedia&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;mediaConstraints&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; stream&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For simplicity’s sake, I’m keeping the configuration options for the screen capture (the &lt;code&gt;mediaConstraints&lt;/code&gt; object) very minimal, but there are quite a few options that can be configured, like the preferred device (useful for multiple webcam or microphone setups), sample rate, volume…&lt;/p&gt;
&lt;p&gt;You can find more details here: &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/API/DisplayMediaStreamConstraints&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;DisplayMediaStreamConstraints - Web APIs | MDN&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Screen stream&lt;/h3&gt;
&lt;p&gt;To record the user’s screen, be it a browser window, and application or the entire screen, the code is very similar:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;captureScreen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    mediaConstraints &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;video&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token literal-property property&quot;&gt;cursor&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;always&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token literal-property property&quot;&gt;resizeMode&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;crop-and-scale&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; screenStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; navigator&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;mediaDevices&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getDisplayMedia&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        mediaConstraints&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; screenStream&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Note that both examples are asynchronous functions because the MediaDevice interface returns a promise.&lt;/p&gt;
&lt;h3&gt;Record the streams&lt;/h3&gt;
&lt;p&gt;To record the stream obtained before we will use the MediaRecorder API:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; recorder &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;null&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;recordStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; stream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;captureMediaDevices&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    recorder &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MediaRecorder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stream&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; chunks &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    recorder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;ondataavailable&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;            chunks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    recorder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onstop&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; blob &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Blob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;chunks&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;            &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;video/webm;codecs=vp9&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        chunks &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; blobUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createObjectURL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;blob&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;blobUrl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    recorder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Let’s go through this step by step:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; stream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;captureMediaDevices&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;recorder &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MediaRecorder&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;stream&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; chunks &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here we just initialise the stream and the MediaRecorder with an empty &lt;code&gt;chunks&lt;/code&gt; array that will contain the recorded chunks of data.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;recorder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;ondataavailable&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;event&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;size &lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        chunks&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;push&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;event&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;data&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On the MediaRecorder &lt;code&gt;ondataavailable&lt;/code&gt; event we tell the MediaRecorder to push the recorded data inside the &lt;code&gt;chunks&lt;/code&gt; array.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;recorder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function-variable function&quot;&gt;onstop&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; blob &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Blob&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;chunks&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;type&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#39;video/webm&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    chunks &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; blobUrl &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;URL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;createObjectURL&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;blob&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;blobUrl&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;code&gt;onstop&lt;/code&gt; event handler creates a new Blob containing the recorded data stored in the &lt;code&gt;chunks&lt;/code&gt; variable and the video/webm &lt;code&gt;mymeType&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After that, a URL is created from the blob and printed to the console. This URL can be used to download the file or upload it to a server.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;recorder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;start&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This final method starts the recording with a &lt;em&gt;200ms&lt;/em&gt; time interval.&lt;/p&gt;
&lt;h3&gt;Stop the recording&lt;/h3&gt;
&lt;p&gt;In order to stop the recording and release the user’s devices, we need to call the &lt;code&gt;stop()&lt;/code&gt; method on each track of the stream:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;stopRecording&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    recorder&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;stream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getTracks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;forEach&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;track&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; track&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;stop&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;ok%2C-but-what-about-both-screen-and-audio%3F&quot; tabindex=&quot;-1&quot;&gt;Ok, but what about both screen and audio? &lt;a class=&quot;header-anchor&quot; href=&quot;#ok%2C-but-what-about-both-screen-and-audio%3F&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;To record both the screen and the audio we need to obtain two separate streams and merge them into one single stream:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; screenStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;captureScreen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;mediaConstraints &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;audio&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;echoCancellation&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;noiseSuppression&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;        &lt;span class=&quot;token literal-property property&quot;&gt;sampleRate&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;44100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token literal-property property&quot;&gt;video&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; audioStream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;captureMediaDevices&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; stream &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;MediaStream&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;screenStream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getTracks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token operator&quot;&gt;...&lt;/span&gt;audioStream&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getTracks&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I’m using the same &lt;code&gt;captureMediaDevices&lt;/code&gt; function to capture the audio from the computer by changing the &lt;code&gt;mediaConstraints&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;Then, using the &lt;code&gt;getTracks()&lt;/code&gt; method of the &lt;code&gt;MediaStream&lt;/code&gt; I’m obtaining every track of the two streams to create a new stream.&lt;/p&gt;
&lt;p&gt;The rest of the code is the same as above.&lt;/p&gt;
&lt;h2 id=&quot;wrapping-up%E2%80%A6&quot; tabindex=&quot;-1&quot;&gt;Wrapping up… &lt;a class=&quot;header-anchor&quot; href=&quot;#wrapping-up%E2%80%A6&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is everything you need to know to get started with media recording in the browser.&lt;br&gt;
The MDN docs are a helpful resource for all the other methods and configurations available.&lt;/p&gt;
&lt;p&gt;In a real-world application you would worry about checking the browser compliance with the APIs, stopping and resuming the stream, choosing between multiple devices as well as providing a real-time preview of the stream and/or of the downloaded video, something that you could do like this:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; video &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; document&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getElementById&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;video&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;video&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;srcObject &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; stream &lt;span class=&quot;token comment&quot;&gt;//to preview the stream&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;video&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;src &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; blobUrl &lt;span class=&quot;token comment&quot;&gt;// to preview the finished video&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;review-the-entire-code&quot; tabindex=&quot;-1&quot;&gt;Review the entire code &lt;a class=&quot;header-anchor&quot; href=&quot;#review-the-entire-code&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I set up a small Codepen gist with the entire code from this article, &lt;a href=&quot;https://codepen.io/antopiras89/pen/mdWEExX&quot; rel=&quot;noopener noreferrer&quot; target=&quot;_blank&quot; aria-label=&quot;MediaStream Web API example&quot;&gt;check it out here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I hope this has been helpful. If you want me to dive into it a little bit more or maybe tackle some real-world examples like choosing between multiple cameras and microphones let me know in the comments below 💪🏻&lt;/p&gt;
</content>
        </entry>
    
        <entry>
            <id>https://www.antopiras.dev/blog/2023-01-26-expose-your-work/#7</id>
            <title>Share your work with ngrok and localtunnel</title>
            <link href="https://www.antopiras.dev/blog/2023-01-26-expose-your-work/#7" />
            <updated>Thu Jan 26 2023 08:43:54 GMT+0000 (Coordinated Universal Time)</updated>
            
            
            <category term="javascript" />
            
            <category term="tips" />
            
            
            <summary>Local development made easy with ngrok and localtunnel.</summary>
            <content type="html">&lt;p&gt;Have you ever found yourself wanting to show your work to a client, but didn’t want to setup a server only for that reason? Or maybe you wanted to use the APIs of a particular service, but they didn’t allow &lt;em&gt;localhost&lt;/em&gt; as a valid IP address in their access whitelist?&lt;/p&gt;
&lt;p&gt;If the answer is yes, then this post is for you.&lt;/p&gt;
&lt;h2 id=&quot;ngrok-to-the-rescue!&quot; tabindex=&quot;-1&quot;&gt;Ngrok to the rescue! &lt;a class=&quot;header-anchor&quot; href=&quot;#ngrok-to-the-rescue!&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;From ngrok’s &lt;a href=&quot;https://ngrok.com&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;official website&lt;/a&gt; :&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;ngrok is a simplified API-first ingress-as-a-service that adds connectivity, security, and observability to your apps with no code changes.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;What!? Let’s translate this: ngrok is an application that creates a tunnel between your computer and the internet, solving a couple of the most commons hiccups when developing web applications:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Show someone else your work in progress without having to deploy it to a remote branch and running it on a hosting space&lt;/li&gt;
&lt;li&gt;Consume APIs that only accepts secure HTTPS connections (and complain when you try to whitelist &lt;em&gt;localhost&lt;/em&gt;!)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Ngrok can be installed in all major operating systems as a standalone service. Its developer license is &lt;em&gt;free&lt;/em&gt; (with some restrictions like bandwidth and usage), but &lt;em&gt;it requires the creation of an account&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;To install it in MacOS we can use brew:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;brew &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; ngrok/ngrok/ngrok&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instructions for different operating systems can be found &lt;a href=&quot;https://ngrok.com/docs/getting-started&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;in the docs&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;but-how-does-it-work%3F&quot; tabindex=&quot;-1&quot;&gt;But how does it work? &lt;a class=&quot;header-anchor&quot; href=&quot;#but-how-does-it-work%3F&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When using ngrok, we can expose a web server on our machine, for example, a Node.js application running on &lt;em&gt;localhost:8000&lt;/em&gt; to the outer world by starting ngrok. The service will create a tunnel between our machine and the internet using a &lt;em&gt;random URL&lt;/em&gt; that we can share with other people.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;ngrok http &lt;span class=&quot;token number&quot;&gt;8000&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;some-of-its-options-and-features-features&quot; tabindex=&quot;-1&quot;&gt;Some of its options and features features &lt;a class=&quot;header-anchor&quot; href=&quot;#some-of-its-options-and-features-features&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3&gt;Automated SSL/TLS certificates&lt;/h3&gt;
&lt;p&gt;Ngrok supports HTTPS out of the box, and we have a couple of ways to set this up.&lt;br&gt;
The easiest way is to specify it as a complete address:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;ngrok http https://localhost:8000&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Another way to do that is by connecting ngrok on port 443. It will assume by default that we want to use the HTTPS protocol:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;ngrok http &lt;span class=&quot;token number&quot;&gt;443&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Custom domains&lt;/h3&gt;
&lt;p&gt;Custom domains are a paid feature, however, custom subdomains can be configured easily and work with the free plan.&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;ngrok http &lt;span class=&quot;token parameter variable&quot;&gt;--subdomain&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;antopiras &lt;span class=&quot;token number&quot;&gt;80&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Authentication&lt;/h3&gt;
&lt;p&gt;Ngrok also supports basic authentication (specify user and password when setting it up), OAuth 2.0 (Google/GitHub account), and other forms of authentication.&lt;br&gt;
We can add authentication with:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;ngrok http --basic-auth&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;username:password&quot;&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8080&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Or&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;ngrok http &lt;span class=&quot;token number&quot;&gt;8000&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--oauth&lt;/span&gt; google&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;use-it-in-your-node.js-application&quot; tabindex=&quot;-1&quot;&gt;Use it in your Node.js application &lt;a class=&quot;header-anchor&quot; href=&quot;#use-it-in-your-node.js-application&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If we don’t want to have to set up and manually start ngrok every time we come back to our laptop or we are looking for a more automated solution, we can use &lt;a href=&quot;https://github.com/bubenshchykov/ngrok&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;this Node.js wrapper&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; express &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;express&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; ngrok &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;ngrok&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; app &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;express&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; port &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;8000&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; &lt;span class=&quot;token constant&quot;&gt;NGROK_AUTH_TOKEN&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; ‘&lt;span class=&quot;token constant&quot;&gt;NGROK_AUTH_TOKEN&lt;/span&gt;’&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;get&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;/&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token parameter&quot;&gt;req&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; res&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;  res&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;send&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;Hello World!&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; ngrok&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;authtoken&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token constant&quot;&gt;NGROK_AUTH_TOKEN&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;  &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; url &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; ngrok&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;connect&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Example app listening on port &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;port&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;  console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;ngrok tunnel url: &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Once we have connected, we can retrieve the ngrok URL and use it inside our application.&lt;/p&gt;
&lt;h2 id=&quot;an-alternative-to-ngrok&quot; tabindex=&quot;-1&quot;&gt;An alternative to ngrok &lt;a class=&quot;header-anchor&quot; href=&quot;#an-alternative-to-ngrok&quot; aria-label=&quot;Link to this section&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;&lt;i class=&quot;icon-link text-accent_alt&quot; aria-hidden=&quot;true&quot;&gt;&lt;/i&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you find ngrok too complex to use and want an easy and quick-to-use alternative for Node, check out &lt;a href=&quot;https://theboroer.github.io/localtunnel-www/&quot; target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot;&gt;localtunnel&lt;/a&gt;:&lt;/p&gt;
&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token function&quot;&gt;npm&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; localtunnel //use &lt;span class=&quot;token parameter variable&quot;&gt;-g&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; you want to &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; it globally on your machine&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It’s an NPM package and it is pretty similar to ngrok, but it doesn’t require you to create an account. It also supports subdomains.&lt;/p&gt;
&lt;p&gt;To use it in our simple application we just need to change a couple of lines:&lt;/p&gt;
&lt;pre class=&quot;language-javascript&quot;&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; localtunnel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;require&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;localtunnel&#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;//…&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;app&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;listen&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;port&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;async&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; tunnel &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;await&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;localtunnel&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; port &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token template-string&quot;&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;Example app listening on port &lt;/span&gt;&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;${&lt;/span&gt;port&lt;span class=&quot;token interpolation-punctuation punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token template-punctuation string&quot;&gt;`&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;    console&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;log&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&#39;localtunnel tunnel url: &#39;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; tunnel&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;url&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;highlight-line&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;…and that’s it! I hope you found this little guide useful. Leave a comment if you have more questions about this 😄&lt;/p&gt;
</content>
        </entry>
    
</feed>