<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Ben Greenier</title>
    <description>The latest articles on DEV Community by Ben Greenier (@bengreenier).</description>
    <link>https://dev.to/bengreenier</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F282550%2F8e009995-21d4-4702-ab16-c71473cb752c.png</url>
      <title>DEV Community: Ben Greenier</title>
      <link>https://dev.to/bengreenier</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/bengreenier"/>
    <language>en</language>
    <item>
      <title>I'm Joining Rainway 🚀</title>
      <dc:creator>Ben Greenier</dc:creator>
      <pubDate>Tue, 09 Nov 2021 16:04:43 +0000</pubDate>
      <link>https://dev.to/bengreenier/im-joining-rainway-4kd8</link>
      <guid>https://dev.to/bengreenier/im-joining-rainway-4kd8</guid>
      <description>&lt;p&gt;Hello, I'm Ben Greenier. You might know me from my WebRTC work at Microsoft, where I helped create and improve things like &lt;a href="https://goodbyemixer.com"&gt;Mixer&lt;/a&gt;, &lt;a href="https://github.com/bengreenier/browserd"&gt;browserd&lt;/a&gt;, &lt;a href="https://github.com/bengreenier/webrtc-unity-plugin"&gt;webrtc-unity-plugin&lt;/a&gt;, early versions of &lt;a href="https://github.com/microsoft/winrtc"&gt;winrtc&lt;/a&gt;, and &lt;a href="https://github.com/microsoft/MixedReality-WebRTC"&gt;MixedReality-WebRTC&lt;/a&gt;. I also had a chance to work on closed-source software &lt;a href="https://devblogs.microsoft.com/cse/"&gt;directly with external engineering teams&lt;/a&gt; to solve all kinds of problems, though I primarily focused on those in the real-time media space. I chose to leave Microsoft in June 2021 to decompress after a challenging stint working on Microsoft Teams. I wanted to build some tech to &lt;a href="https://faster-games.com"&gt;help make creating games more approachable&lt;/a&gt;, and take some time to figure out what I wanted to do next. I also had the extreme privilege to be able to actually do that, so I did.&lt;/p&gt;

&lt;p&gt;In parallel, I'd been following the work Rainway was doing on their journey to create an ultra-low latency streaming solution. I first heard about them through Twitter and &lt;a href="https://rainway.com/blog/2021/04/19/xbox-cloud-gaming/"&gt;their work with Xbox Cloud Gaming&lt;/a&gt; - which is pretty impressive. It was actually through Twitter, that I found myself sitting down for a slice of pizza with Rainway's CEO, &lt;a href="http://twitter.com/andrewmd5"&gt;Andrew Sampson&lt;/a&gt; to learn more about what they're building these days. Suffice it to say I was pretty impressed. 😁&lt;/p&gt;

&lt;p&gt;You can learn more about Rainway's ongoing work on &lt;a href="https://rainway.com/blog"&gt;the Rainway blog&lt;/a&gt; - I'm especially excited about the opportunity to work with a bunch of great folks, use Rust, explore the in's and out's of &lt;a href="https://rainway.com/blog/2021/08/30/bebop-rust/"&gt;Bebop&lt;/a&gt;, and of course to help make creating ultra-low latency applications much easier for folks.&lt;/p&gt;

&lt;p&gt;I'll be starting in a few weeks, and hope to be able to share more with you about the work we'll be doing together going forward! 🚀&lt;/p&gt;

&lt;p&gt;💙🌈&lt;br&gt;
-Ben&lt;/p&gt;

</description>
      <category>career</category>
    </item>
    <item>
      <title>I'm joining Mixer 📺</title>
      <dc:creator>Ben Greenier</dc:creator>
      <pubDate>Sat, 14 Mar 2020 12:29:39 +0000</pubDate>
      <link>https://dev.to/bengreenier/i-m-joining-mixer-49oc</link>
      <guid>https://dev.to/bengreenier/i-m-joining-mixer-49oc</guid>
      <description>&lt;p&gt;Hi! I’m Ben Greenier — I’m currently an engineer at Microsoft working to create awesome open source projects with our partners. We get to &lt;a href="https://github.com/microsoft"&gt;create software&lt;/a&gt; to help solve really tricky problems, and &lt;a href="https://www.microsoft.com/developerblog"&gt;share our stories&lt;/a&gt; as we go. This means that as part of my current job I get to play with lots of new technologies, learn how to use them, and help other folks do the same.&lt;/p&gt;

&lt;p&gt;However, lately I've been feeling like my aspirations aren't quite aligned with my career - the things that I'm passionate about aren't things I focus on in my day-to-day role. I like being able to create Open Source Software (OSS) but not when I don't have the time to focus on building those OSS projects over time. I'm also finding that specific applications of technology are more exciting to me than others - and while working with customers on lots of different problems can be a great learning experience, It can also be super limiting. I already spend much of my time thinking about &lt;a href="https://mixer.com/bengreenier"&gt;Streaming&lt;/a&gt;, and how I can help to create tools and &lt;a href="https://overlayed.app"&gt;platforms&lt;/a&gt; to enable broadcasters to be more successful, so...&lt;/p&gt;

&lt;p&gt;I'm making some changes - Starting in April I'll be joining &lt;a href="https://mixer.com"&gt;Mixer&lt;/a&gt; full-time, to work on their video platform team - contributing to things like &lt;a href="https://github.com/mixer/ftl-sdk"&gt;FTL&lt;/a&gt; and the broader ingress and egress services that help make broadcasting quick, easy, and reliable on the platform. This also means I'll be moving from London to Seattle (more on that in a different post, perhaps). I'll be able to keep working at Microsoft - A company I really respect and enjoy working for - but focus on problems and technology that are much more my style. I'm super excited to get started!🎉&lt;/p&gt;

&lt;p&gt;Thanks for reading - If you'd like to further support me and see similar content, follow me on &lt;a href="https://mixer.com/bengreenier"&gt;Mixer&lt;/a&gt; and/or &lt;a href="https://twitter.com/bengreenier"&gt;Twitter&lt;/a&gt;. Curious to learn more about what a role at Mixer entails? Leave a comment below and I'll be sure to do my best to explain or connect you with the right folks.&lt;/p&gt;

&lt;p&gt;💙🌈&lt;br&gt;
-Ben&lt;/p&gt;

</description>
      <category>career</category>
    </item>
    <item>
      <title>Azure: Validating B2C Token Issuers with EasyAuth</title>
      <dc:creator>Ben Greenier</dc:creator>
      <pubDate>Tue, 10 Mar 2020 11:57:14 +0000</pubDate>
      <link>https://dev.to/bengreenier/azure-validating-b2c-token-issuers-with-easyauth-21f5</link>
      <guid>https://dev.to/bengreenier/azure-validating-b2c-token-issuers-with-easyauth-21f5</guid>
      <description>&lt;p&gt;Hi! I’m Ben Greenier — I’m an engineer at Microsoft working to create awesome open source projects with our partners. We get to &lt;a href="https://github.com/microsoft"&gt;create software&lt;/a&gt; to help solve really tricky problems, and &lt;a href="https://www.microsoft.com/developerblog"&gt;share our stories&lt;/a&gt; as we go. This means that as part of my job I get to play with lots of new technologies, learn how to use them, and help other folks do the same.&lt;/p&gt;

&lt;p&gt;I'm currently working on an Azure App that runs in &lt;a href="https://docs.microsoft.com/en-us/azure/app-service/overview"&gt;Azure App Services&lt;/a&gt; and uses &lt;a href="https://docs.microsoft.com/en-us/azure/app-service/overview-authentication-authorization"&gt;EasyAuth&lt;/a&gt; to validate &lt;a href="https://docs.microsoft.com/en-gb/azure/active-directory-b2c/overview"&gt;Azure AAD B2C&lt;/a&gt; credentials before allowing a user to access the app. Overall things work pretty well for users, but it's come time to add some integration testing, and I need an automated way to retrieve a user credential so that the testing can authenticate to the service.&lt;/p&gt;

&lt;p&gt;To allow automated authentication without a browser, I've created a separate &lt;a href="https://docs.microsoft.com/en-gb/azure/active-directory-b2c/user-flow-overview"&gt;B2C user-flow&lt;/a&gt; with &lt;a href="https://docs.microsoft.com/en-us/azure/active-directory-b2c/configure-ropc?tabs=applications"&gt;ROPC authentication&lt;/a&gt; enabled. I'm then able to issue a simple POST request from my test runner, and retrieve a token! I thought I was done, but the test was still failing even when using this token - weird.&lt;/p&gt;

&lt;p&gt;I loaded both a user token and an automated token into &lt;a href="https://jwt.io"&gt;JWT.io&lt;/a&gt; and realized they had different issuers - what a pain! Since I had EasyAuth configured to verify that the issuer of all tokens matches a specific issuer (and only one issuer is supported) I'm stuck again.&lt;/p&gt;

&lt;p&gt;To get unstuck, I went spelunking in the Azure B2C portal to see if there's a way to control the issuer for different user-flows. As it turns out, there is! In the portal, you can pick one of two values for the issuer. One that is unique to the user-flow, and one that is unique to the B2C instance. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--6vsUqraD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/to92jhqbcwakatpkdjhr.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--6vsUqraD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/to92jhqbcwakatpkdjhr.PNG" alt="The Azure Portal UI showing the properties section of a B2C user flow. There is a section for selecting the issuer, with two options in a dropdown. The options are the values mentioned in the previous content in this article."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It turns out that the user-flow that my actual users leverage was using the value unique to the flow. In order for EasyAuth to validate that both tokens are issued by the same issuer, I set both user-flows to use the issuer that is unique to the B2C instance. Since both flows are in the same instance they then have the same issuer. You can see the difference in the URIs here:  &lt;/p&gt;

&lt;p&gt;Issuer that's unique to the B2C instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://authsucks.b2clogin.com/db6edc22-a637-4e4a-a6cc-e9ec7d8aae45/v2.0/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Issuer that's unique to the user-flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;https://authsucks.b2clogin.com/tfp/db6edc22-a637-4e4a-a6cc-e9ec7d8aae45/b2c_1_flow1/v2.0/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After updating both user-flows to have the issuer &lt;code&gt;https://authsucks.b2clogin.com/db6edc22-a637-4e4a-a6cc-e9ec7d8aae45/v2.0/&lt;/code&gt;, and configuring EasyAuth to use that same value for verification, tokens from both flows validated successfully and my tests started to pass!&lt;/p&gt;

&lt;p&gt;Thanks for reading - If you'd like to further support me and see similar content, follow me on &lt;a href="https://twitch.tv/ben_greenier"&gt;twitch&lt;/a&gt; and/or &lt;a href="https://twitter.com/bengreenier"&gt;twitter&lt;/a&gt;. If you're stuck on a similar problem, or you were and this helped, I'd love to learn more about that situation - leave me a note in the comments.&lt;/p&gt;

&lt;p&gt;💙🌈&lt;br&gt;
-Ben&lt;/p&gt;

&lt;p&gt;P.S: Header photo by &lt;a href="https://unsplash.com/@cbarbalis?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Chris Barbalis&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/lock?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>azure</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>Debugging Terraform with Fiddler</title>
      <dc:creator>Ben Greenier</dc:creator>
      <pubDate>Thu, 30 Jan 2020 20:43:07 +0000</pubDate>
      <link>https://dev.to/bengreenier/debugging-terraform-with-fiddler-4pap</link>
      <guid>https://dev.to/bengreenier/debugging-terraform-with-fiddler-4pap</guid>
      <description>&lt;p&gt;Hi! I’m Ben Greenier — I’m an engineer at Microsoft working to create awesome open source projects with our partners. We get to &lt;a href="https://github.com/microsoft" rel="noopener noreferrer"&gt;create software&lt;/a&gt; to help solve really tricky problems, and &lt;a href="https://www.microsoft.com/developerblog" rel="noopener noreferrer"&gt;share our stories&lt;/a&gt; as we go. This means that as part of my job I get to play with lots of new technologies, learn how to use them, and help other folks do the same.&lt;/p&gt;

&lt;p&gt;Lately I've been working with &lt;a href="https://www.terraform.io/" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt; to help manage infrastructure for a new app. The app itself isn't support important to this post, so I'll omit a description. However, it's going to run on &lt;a href="https://azure.microsoft.com" rel="noopener noreferrer"&gt;Azure&lt;/a&gt; and will be built on &lt;a href="https://azure.microsoft.com/services/functions" rel="noopener noreferrer"&gt;Azure Functions&lt;/a&gt;. To help limit downtime, the plan is to use &lt;a href="https://martinfowler.com/bliki/BlueGreenDeployment.html" rel="noopener noreferrer"&gt;Blue/Green Deployments&lt;/a&gt; backed by &lt;a href="https://docs.microsoft.com/azure/app-service/deploy-staging-slots" rel="noopener noreferrer"&gt;App Slots&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While I was configuring this setup, I ran into some platform errors (from Azure) saying that my &lt;a href="https://www.terraform.io/docs/providers/azurerm/r/app_service_slot.html" rel="noopener noreferrer"&gt;azurerm_app_service_slot&lt;/a&gt; block was failing - yet it was a really simple configuration. Again, the actual error here isn't a focus (maybe that's a good candidate for a second post) - but I couldn't find any solutions online, and felt it was time to dig deeper.&lt;/p&gt;

&lt;p&gt;I first used &lt;a href="https://www.terraform.io/docs/internals/debugging.html" rel="noopener noreferrer"&gt;&lt;code&gt;TF_LOG=DEBUG&lt;/code&gt;&lt;/a&gt; to get a bit more visibility, but I wanted to be able to see the full HTTP traffic (including bodies) to and from Azure, as &lt;code&gt;terraform&lt;/code&gt; ran. No amount of logging seemed able to provide that. I decided to try and hook up &lt;a href="https://www.telerik.com/fiddler" rel="noopener noreferrer"&gt;Fiddler&lt;/a&gt; - my favorite tool for this kind of thing.&lt;/p&gt;

&lt;p&gt;With Fiddler running, I disabled explicit traffic capture, and set the &lt;a href="https://github.com/golang/net/blob/master/http/httpproxy/proxy.go#L91" rel="noopener noreferrer"&gt;go's http proxy environment variables&lt;/a&gt; in my shell session to point at Fiddler. On Windows this is two quick commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;set HTTP_PROXY=http://localhost:8888
set HTTPS_PROXY=http://localhost:8888
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also went into the Fiddler options, and disabled https decryption for the Azure CLI Authentication endpoints - we're not interested in this traffic anyway, and while the CLI &lt;a href="https://github.com/Azure/azure-cli/blob/dev/doc/use_cli_effectively.md#working-behind-a-proxy" rel="noopener noreferrer"&gt;has more advanced solutions&lt;/a&gt;, we don't need them here.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9guov0is8dzja7sz5gbo.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F9guov0is8dzja7sz5gbo.PNG" alt="A screenshot of the Fiddler Options UI, showing my modified settings to ignore authentication sites"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These are the sites I disabled decryption for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;login.microsoftonline.com
graph.windows.net
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, I was able to see my Terraform traffic in Fiddler - and inspect the differences between my desired configuration and what was actually being sent to Azure over the wire. With that, I was able to fix my issue!&lt;/p&gt;

&lt;p&gt;Thanks for reading - If you'd like to further support me and see similar content, follow me on &lt;a href="https://twitch.tv/ben_greenier" rel="noopener noreferrer"&gt;twitch&lt;/a&gt; and/or &lt;a href="https://twitter.com/bengreenier" rel="noopener noreferrer"&gt;twitter&lt;/a&gt;. If you're stuck on a similar problem, or you were and this helped, I'd love to learn more about that situation - leave me a note in the comments.&lt;/p&gt;

&lt;p&gt;💙🌈&lt;br&gt;
-Ben&lt;/p&gt;

&lt;p&gt;P.S: Header Photo by &lt;a href="https://unsplash.com/@marckleen?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Marc Kleen&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/spill?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText" rel="noopener noreferrer"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>todayilearned</category>
      <category>azure</category>
      <category>infrastructure</category>
    </item>
    <item>
      <title>Why Replace React when bundling?</title>
      <dc:creator>Ben Greenier</dc:creator>
      <pubDate>Wed, 08 Jan 2020 14:20:52 +0000</pubDate>
      <link>https://dev.to/bengreenier/why-replace-react-when-bundling-1e23</link>
      <guid>https://dev.to/bengreenier/why-replace-react-when-bundling-1e23</guid>
      <description>&lt;p&gt;Hi! I’m Ben Greenier — I’m an engineer at Microsoft working to create awesome open source projects with our partners. We get to &lt;a href="https://github.com/microsoft"&gt;create software&lt;/a&gt; to help solve really tricky problems, and &lt;a href="https://www.microsoft.com/developerblog"&gt;share our stories&lt;/a&gt; as we go. This means that as part of my job I get to play with lots of new technologies, learn how to use them, and help other folks do the same.&lt;/p&gt;

&lt;p&gt;Lately I've been working on a browser app called &lt;a href="https://overlayed.app"&gt;Overlayed&lt;/a&gt; - it helps broadcasters interact with their viewers in new ways, using overlays. Under the hood, Overlayed is powered by user-defined modules (using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules"&gt;ESM&lt;/a&gt;), that export React components. You can learn more about that, &lt;a href="https://dev.to/bengreenier/introducing-overlayed-streamer-overlays-powered-by-react-17ja"&gt;here&lt;/a&gt; - but it's not what this post is about.&lt;/p&gt;

&lt;p&gt;Recently I've been investigating replacing React in bundled code for the browser. A friend asked me why I needed to do this - shouldn't the bundler do the correct thing? &lt;strong&gt;This post is about my specific use-case&lt;/strong&gt;, where-in the bundler can't do the correct thing, because it isn't aware of what's happening.&lt;/p&gt;

&lt;p&gt;The specific bundler I'm using is &lt;a href="https://rollupjs.org%5D"&gt;rollup&lt;/a&gt; - it's very good at creating &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules"&gt;ESM bundles for the modern web&lt;/a&gt;. When rollup runs, it &lt;a href="https://rollupjs.org/guide/en/#tree-shaking"&gt;tree-shakes&lt;/a&gt; your code, scope-hoisting shared dependencies as it goes. Take a look at this example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# module-1.js
import React from 'react'

export default React.createElement("p", undefined, "hello module-1");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# module-2.js
import React from 'react'

export default React.createElement("p", undefined, "hello module-2");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# app-entrypoint.js
import React from 'react'
import moduleOne from './module-1'
import moduleTwo from './module-2'

React.createElement("div", undefined, [moduleOne, moduleTwo]);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don't worry too much about the code itself, we're more interested in the &lt;code&gt;import&lt;/code&gt; statements, and their implications. If you were to step through this code the way an interpreter would, you'd probably do this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import React (into &lt;code&gt;app-entrypoint.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;li&gt;Import Module 1 (into &lt;code&gt;app-entrypoint.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;li&gt;Import React (into &lt;code&gt;module-1.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;li&gt;Import Module 2 (into &lt;code&gt;app-entrypoint.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;li&gt;Import React (into &lt;code&gt;module-2.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, you're trying to get React three times! Of course, many JavaScript runtimes (like node, for example) use &lt;a href="https://nodejs.org/api/modules.html#modules_require_cache"&gt;a module cache&lt;/a&gt; to prevent "actually" loading React many times, but to my knowledge this isn't possible in a browser - so your interpreter needs to evaluate the contents of React three times. This is where bundling (with scope-hoisting) helps us.&lt;/p&gt;

&lt;p&gt;Rollup can statically analyze the above code, and realize that many things will need React. Therefore, when it creates a bundle (recall that a bundle contains all dependencies and the authored source) it can include React once, and effectively pass "references" to it in all cases. In other words, scope-hosting gives us:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import React (into an isolated scope, let's call it &lt;code&gt;bundled&lt;/code&gt; scope)&lt;/li&gt;
&lt;li&gt;Reference React from &lt;code&gt;bundled&lt;/code&gt; scope (into &lt;code&gt;app-entrypoint.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;li&gt;Import Module 1 (into &lt;code&gt;app-entrypoint.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;li&gt;Reference React from &lt;code&gt;bundled&lt;/code&gt; scope (into &lt;code&gt;module-1.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;li&gt;Import Module 2 (into &lt;code&gt;app-entrypoint.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;li&gt;Reference React from &lt;code&gt;bundled&lt;/code&gt; scope (into &lt;code&gt;module-2.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As a result, only one instance of React is included, meaning our bundled source size is smaller (only one copy of React, not three). This is good news, because it means our browser needs to download and interpret less code. And it's all supported "for free" with Rollup - how great!&lt;/p&gt;

&lt;p&gt;Now we can talk about why I'm &lt;a href="https://dev.to/bengreenier/replacing-js-imports-with-rollup-10ol"&gt;investigating replacing these imports&lt;/a&gt; for &lt;a href="https://overlayed.app"&gt;Overlayed&lt;/a&gt;. Overlayed has an architecture that allows for third-party developers to create plugins. This is great for extensibility, but bad for bundling.&lt;/p&gt;

&lt;p&gt;Recall that in the example above we use static analysis to determine what can be scope-hoisted. If Rollup can't determine what is being loaded when it runs (during the "build" phase of Overlayed) it can't choose to only import one copy. This presents a problem with the plugin architecture - if a plugin depends on React, and is "built" using a separate run of Rollup (as a plugin is a separate project, maintained by a third-part developer) it won't know that it's being bundled for Overlayed (and therefore will already have a copy of React) and will include a copy. This eventually leads to a slow experience for plugins, because they all contain (and load/interpret) React, even though we already have an instance loaded.&lt;/p&gt;

&lt;p&gt;To workaround this issue, we can write a rollup plugin (or use an existing one) to replace React in the plugin's bundle, with a small "shim" that simply references React in the parent scope. We can be confident the parent scope will contain React, as plugins are only designed to be loaded by Overlayed - they won't run anywhere else.&lt;/p&gt;

&lt;p&gt;Take the example code above. If we introduce the following as a "shim" module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# react-shim.js
export default globalThis.React
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Bundle our code with a plugin that rewrites &lt;code&gt;import React from 'react'&lt;/code&gt; to &lt;code&gt;import React from './react-shim'&lt;/code&gt;, and split &lt;code&gt;module-1.js&lt;/code&gt; off into it's own third-party plugin (with it's own build) we end up with the following flow:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overlayed app build:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import React (into an isolated scope, let's call it &lt;code&gt;bundled&lt;/code&gt; scope)&lt;/li&gt;
&lt;li&gt;Reference React from &lt;code&gt;bundled&lt;/code&gt; (into &lt;code&gt;app-entrypoint.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;li&gt;Import Module 2 (into &lt;code&gt;app-entrypoint.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;li&gt;Reference React from &lt;code&gt;bundled&lt;/code&gt; scope (into &lt;code&gt;module-2.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Module 1 build:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import React from &lt;code&gt;./react-shim&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Configure global reference (Referencing React from  &lt;code&gt;bundled&lt;/code&gt; above)&lt;/li&gt;
&lt;li&gt;Reference React from &lt;code&gt;bundled&lt;/code&gt; (above)&lt;/li&gt;
&lt;li&gt;Import Module 1 (into &lt;code&gt;app-entrypoint.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;li&gt;Reference React from &lt;code&gt;bundled&lt;/code&gt; scope (above, into &lt;code&gt;module-1.js&lt;/code&gt; scope)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By replacing React with an explicit reference in the "Module 1 build", we're able to remove React from the plugin bundle, while still loading the correct instance of React at runtime, from the parent (Overlayed) environment.&lt;/p&gt;

&lt;p&gt;Phew! This got complicated quickly. Hopefully this can help to clarify why Overlayed isn't able to leverage the "free" scope-hoisting of React in the plugin case. If it's still not quite clear, let me know in the comments. Perhaps some revisions will be needed.&lt;/p&gt;

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

&lt;p&gt;💙🌈&lt;br&gt;
-Ben&lt;/p&gt;

&lt;p&gt;P.S: Photo by &lt;a href="https://unsplash.com/@ruralexplorer?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Rural Explorer&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/tree-shake?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
    </item>
    <item>
      <title>Replacing JS Imports with Rollup</title>
      <dc:creator>Ben Greenier</dc:creator>
      <pubDate>Tue, 07 Jan 2020 16:01:52 +0000</pubDate>
      <link>https://dev.to/bengreenier/replacing-js-imports-with-rollup-10ol</link>
      <guid>https://dev.to/bengreenier/replacing-js-imports-with-rollup-10ol</guid>
      <description>&lt;p&gt;Hi! I’m Ben Greenier — I’m an engineer at Microsoft working to create awesome open source projects with our partners. We get to &lt;a href="https://github.com/microsoft"&gt;create software&lt;/a&gt; to help solve really tricky problems, and &lt;a href="https://www.microsoft.com/developerblog"&gt;share our stories&lt;/a&gt; as we go. This means that as part of my job I get to play with lots of new technologies, learn how to use them, and help other folks do the same.&lt;/p&gt;

&lt;p&gt;Lately I've been working on a browser app called &lt;a href="https://overlayed.app"&gt;Overlayed&lt;/a&gt; - it helps broadcasters interact with their viewers in new ways, using overlays. Under the hood, Overlayed is powered by user-defined modules (using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules"&gt;ESM&lt;/a&gt;), that export React components. You can learn more about that, &lt;a href="https://dev.to/bengreenier/introducing-overlayed-streamer-overlays-powered-by-react-17ja"&gt;here&lt;/a&gt; - but it's not what this post is about.&lt;/p&gt;

&lt;p&gt;Previously, I wrote about &lt;a href="https://dev.to/bengreenier/accessing-globals-inside-js-modules-esm-1eo5"&gt;accessing globals from within modules&lt;/a&gt; which is a precursor to what I'd like to share today - Replacing imports with &lt;a href="https://rollupjs.org"&gt;rollup&lt;/a&gt;. Rollup is a JS bundler, meaning it's job is to combine some code, along with all of it's dependencies, into one file. Let's take a look at a pattern I discovered (not invented) for replacing dependencies with alternate versions when Rollup runs.&lt;/p&gt;

&lt;p&gt;First, we need to define a valid replacement. Let's use React as an example, and build on our example from the last post. We can define a React replacement like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export default globalThis.React
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Which will just provide a &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export"&gt;default export&lt;/a&gt; that's value is set to that of the &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis"&gt;globalThis&lt;/a&gt; React variable. It only makes sense to do this if you know React will be provided in the global scope - Like in a browser where React is included as a script dependency, that loads before your script.&lt;/p&gt;

&lt;p&gt;We can then use Rollup and &lt;a href="https://babeljs.io/"&gt;Babel&lt;/a&gt; to rewrite any React imports that look like &lt;code&gt;import React from 'react'&lt;/code&gt; to &lt;code&gt;import React from "our-replacement.js"&lt;/code&gt;, effectively. This makes use of &lt;a href="https://github.com/tleunen/babel-plugin-module-resolver"&gt;babel-plugin-module-resolver&lt;/a&gt;. You might be wondering why Babel is introduced here. It's a great question, that I don't have an answer to. The &lt;a href="https://github.com/pikapkg/builders/tree/master/packages/plugin-bundle-web"&gt;build logic I modified to get this working&lt;/a&gt; uses it, presumably for a great reason. Given that I'm still learning, I've stuck with it to minimize variables.&lt;/p&gt;

&lt;p&gt;Here's the babel configuration addition that makes this possible:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: You may need to modify some other &lt;a href="https://github.com/tleunen/babel-plugin-module-resolver#getting-started"&gt;configuration&lt;/a&gt;, depending on your setup.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "plugins": [
    ["module-resolver", {
      "alias": {
        "react": "./react-shim.js",
      }
    }]
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  In conclusion
&lt;/h2&gt;

&lt;p&gt;Using Rollup, Babel, and babel-plugin-module-resolver, I was able to redirect React imports to a custom module, that loads React from the global environment, which reduces the size of the produced browser bundle, and prevents duplicated versions of React appearing in sibling modules. However, this only works if React exists in the global environment.&lt;/p&gt;

&lt;p&gt;I plan on learning more about this approach, and using it for &lt;a href="https://overlayed.app"&gt;overlayed&lt;/a&gt; going forward. Hopefully that will come with more tangible examples.&lt;/p&gt;

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

&lt;p&gt;💙🌈&lt;br&gt;
-Ben&lt;/p&gt;

&lt;p&gt;P.S: Header Photo by &lt;a href="https://unsplash.com/@pinjasaur?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Paul Esch-Laurent&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/javascript?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>Accessing globals inside JS modules (ESM)</title>
      <dc:creator>Ben Greenier</dc:creator>
      <pubDate>Fri, 03 Jan 2020 12:23:10 +0000</pubDate>
      <link>https://dev.to/bengreenier/accessing-globals-inside-js-modules-esm-1eo5</link>
      <guid>https://dev.to/bengreenier/accessing-globals-inside-js-modules-esm-1eo5</guid>
      <description>&lt;p&gt;Hi! I’m Ben Greenier — I’m an engineer at Microsoft working to create awesome open source projects with our partners. We get to &lt;a href="https://github.com/microsoft"&gt;create software&lt;/a&gt; to help solve really tricky problems, and &lt;a href="https://www.microsoft.com/developerblog"&gt;share our stories&lt;/a&gt; as we go. This means that as part of my job I get to play with lots of new technologies, learn how to use them, and help other folks do the same.&lt;/p&gt;

&lt;p&gt;Lately I've been working on a browser app called &lt;a href="https://overlayed.app"&gt;Overlayed&lt;/a&gt; - it helps broadcasters interact with their viewers in new ways, using overlays. Under the hood, Overlayed is powered by user-defined modules (using &lt;a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Modules"&gt;ESM&lt;/a&gt;), that export React components. You can learn more about that, &lt;a href="https://dev.to/bengreenier/introducing-overlayed-streamer-overlays-powered-by-react-17ja"&gt;here&lt;/a&gt; - but it's not what this post is about.&lt;/p&gt;

&lt;p&gt;While working on getting things ready to import remote modules, I've been investigating replacing shared dependencies with a single version. For instance, since all remote modules will depend on React, I want to load React only once, and allow the modules to reference that single version.&lt;/p&gt;

&lt;p&gt;As far as I could tell, this &lt;strong&gt;should&lt;/strong&gt; just work, but I couldn't find any documentation that explicitly stated this. So, after a bit of googling around, I built a quick test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing
&lt;/h2&gt;

&lt;p&gt;To be sure this worked as expected, I created a quick test using a locally served "module" and JSFiddle to do the import. I tested with both Chrome and Firefox, and saw the  expected results! 🎉&lt;/p&gt;

&lt;p&gt;Here's the module code I used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"use strict";

// notify that our esm bundle loaded
console.log("loaded");

// see if we have a react global
console.log(React);

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

&lt;/div&gt;



&lt;p&gt;And the loader code (Note: React is imported by JSFiddle, so we don't need any code to do that):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// validate React is set
console.log(React)

// load our esm bundle
import('http://localhost:5000/test.js')
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here's the results:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--FGFG_yh8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/8vetwjkau8qm3yes0uad.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FGFG_yh8--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/8vetwjkau8qm3yes0uad.PNG" alt="A screenshot of the firefox test, running successfully in the browser. In the image you can see JSFiddle, the browser console, and the expected output."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In Firefox, everything looks great!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--12UTd5Jn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6f8wbabhlwpb93hej1or.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--12UTd5Jn--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/6f8wbabhlwpb93hej1or.PNG" alt="A screenshot of the chrome test, running successfully in the browser. In the image you can see JSFiddle, the browser console, and the expected output."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In Chrome, everything looks great!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you can see, the test is pretty simple - just a JSFiddle that loads React, and runs our &lt;code&gt;import&lt;/code&gt;, and a locally served module, that logs &lt;code&gt;loaded&lt;/code&gt; when it loads, and prints the &lt;code&gt;React&lt;/code&gt; value from inside the module. Given that the &lt;code&gt;React&lt;/code&gt; object both at the parent level and inside the module look the same, I'm happy to conclude this works great.&lt;/p&gt;

&lt;h2&gt;
  
  
  In conclusion
&lt;/h2&gt;

&lt;p&gt;Globals (that is - things defined in the environment from which &lt;code&gt;import&lt;/code&gt; will run) "just work" inside modules (the code inside the module, that &lt;code&gt;import&lt;/code&gt; is running for us). That's the take-away. 😁&lt;/p&gt;

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

&lt;p&gt;💙🌈&lt;br&gt;
-Ben&lt;/p&gt;

&lt;p&gt;P.S: Header photo by &lt;a href="https://unsplash.com/@kelli_mcclintock?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Kelli McClintock&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/box?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>todayilearned</category>
    </item>
    <item>
      <title>Learning Go - Delivering my first contribution to AzBrowse</title>
      <dc:creator>Ben Greenier</dc:creator>
      <pubDate>Tue, 10 Dec 2019 11:52:53 +0000</pubDate>
      <link>https://dev.to/bengreenier/learning-go-delivering-my-first-contribution-to-azbrowse-30k3</link>
      <guid>https://dev.to/bengreenier/learning-go-delivering-my-first-contribution-to-azbrowse-30k3</guid>
      <description>&lt;p&gt;Hi! I’m Ben Greenier — I’m an engineer at Microsoft working to create awesome open source projects with our partners. We get to &lt;a href="https://github.com/microsoft"&gt;create software&lt;/a&gt; to help solve really tricky problems, and &lt;a href="https://www.microsoft.com/developerblog"&gt;share our stories&lt;/a&gt; as we go. This means that as part of my job I get to play with lots of new technologies, learn how to use them, and help other folks do the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is AzBrowse
&lt;/h2&gt;

&lt;p&gt;AzBrowse is an interactive CLI for interacting with Azure resources - inspired by &lt;a href="https://resources.azure.com"&gt;https://resources.azure.com&lt;/a&gt;. It was created by a few of my colleagues here at Microsoft to allow for faster Azure resource management directly from the shell. Written entirely in Go and maintained by folks down the hall, AzBrowse seemed like the best candidate for me to learn a new language and start contributing quickly.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--566lAguM--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/lawrencegripper"&gt;
        lawrencegripper
      &lt;/a&gt; / &lt;a href="https://github.com/lawrencegripper/azbrowse"&gt;
        azbrowse
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      An interactive CLI for browsing Azure, inspired by http://resources.azure.com/
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;h1&gt;
AzBrowse&lt;/h1&gt;
&lt;p&gt;An interactive CLI for browsing azure resources, inspired by &lt;a href="https://resources.azure.com" rel="nofollow"&gt;resources.azure.com&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href="https://goreportcard.com/report/github.com/lawrencegripper/azbrowse" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/86fea6f799c8a4f6e0d7c4a65916242e4e1db51c2af87f7c6b333c1b4b8716f8/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f6c617772656e6365677269707065722f617a62726f7773653f7374796c653d666c61742d737175617265" alt="Go Report Card"&gt;&lt;/a&gt;
&lt;a href="http://godoc.org/github.com/lawrencegripper/azbrowse" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/5fe1b0b51ac761a22d2dc4ec570a5a1ccb314f0566a75f852ca8d5a1d9737dd0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f676f646f632d7265666572656e63652d626c75652e7376673f7374796c653d666c61742d737175617265" alt="Go Doc"&gt;&lt;/a&gt;
&lt;a href="https://github.com/lawrencegripper/azbrowse/releases/latest"&gt;&lt;img src="https://camo.githubusercontent.com/2a7a33f7809ed9a14e2d63003cdac194a05b8ce3df329b9cd19834c0837df391/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652f6c617772656e6365677269707065722f617a62726f7773652e7376673f7374796c653d666c61742d737175617265" alt="Release"&gt;&lt;/a&gt;
&lt;a href="https://github.com/lawrencegripper/azbrowse/actions?query=workflow%3Arelease+branch%3Amain"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--9dKVf0Hs--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://github.com/lawrencegripper/azbrowse/workflows/release/badge.svg" alt="release"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Status&lt;/h2&gt;
&lt;p&gt;This is a pet project which has matured thanks to support from awesome contributions.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://asciinema.org/a/325237" rel="nofollow"&gt;&lt;img src="https://camo.githubusercontent.com/32d0f069489802a09361c5024cf32b5847b1186431614fca17729c04b346cbd8/68747470733a2f2f61736369696e656d612e6f72672f612f3332353233372e737667" alt="asciicast"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Warning: Please familiarize yourself with the code and the how-to's before using it in a production environment.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
Cool what else can it do?&lt;/h2&gt;
&lt;p&gt;Lots &lt;a href="https://github.com/lawrencegripper/azbrowsedocs/getting-started.md"&gt;check out the guided tour here&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Edit/Update resource&lt;/li&gt;
&lt;li&gt;Multi-resource delete&lt;/li&gt;
&lt;li&gt;Actions on resources such as restart and list-keys&lt;/li&gt;
&lt;li&gt;ASCII Graphs for resource metrics&lt;/li&gt;
&lt;li&gt;Interactive command panel for filtering and more&lt;/li&gt;
&lt;li&gt;Build custom views from &lt;a href="https://github.com/lawrencegripper/azbrowse./docs/azure-resource-graph.md"&gt;Azure Resource Graph Queries&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For advanced &lt;a href="https://github.com/lawrencegripper/azbrowsedocs/config.md"&gt;config review the settings page here&lt;/a&gt;. For &lt;a href="https://github.com/lawrencegripper/azbrowse./docs/commandline/azbrowse.md"&gt;command line arguments and docs see this page&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
Contributing&lt;/h2&gt;
&lt;p&gt;Take a look at the guide here &lt;a href="https://github.com/lawrencegripper/azbrowsedocs/design/README.md"&gt;for a guide on the design of azbrowse&lt;/a&gt; and then a look here &lt;a href="https://github.com/lawrencegripper/azbrowseCONTRIBUTING.md"&gt;for how to get started on deving&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
Install/Run&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;Pre-req: Ensure you have the &lt;a href="https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest" rel="nofollow"&gt;&lt;code&gt;az&lt;/code&gt; command from Azure CLI&lt;/a&gt; setup on your…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/lawrencegripper/azbrowse"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
 
&lt;h2&gt;
  
  
  Learning Go
&lt;/h2&gt;

&lt;p&gt;I decided I needed to learn &lt;a href="https://golang.org"&gt;Go&lt;/a&gt; given it's increasing prominence in backend stacks like Kubernetes. As I begin to need to work with folks using these technologies, being able to understand and even modify these Go implementations will be super helpful. To begin, I read the entirety of the &lt;a href="https://golang.org/doc/effective_go.html"&gt;Effective Go&lt;/a&gt; documentation. That was a great start, and genuinely a well written resource. However for more practical stuff, I found myself using &lt;a href="https://gobyexample.com/"&gt;Go by Example&lt;/a&gt; quite a bit - My colleague recommended it and it doesn't disappoint. Go By Example includes little snippets of code for solving common Go problems - so not only do you get a brief description of a topic, but a fully runnable code example as well.&lt;/p&gt;

&lt;p&gt;My first actual Go task was to add some additional regex parsing logic, and increase the test coverage of that logic. It was actually just &lt;a href="https://github.com/lawrencegripper/azbrowse/issues/175"&gt;an open issue&lt;/a&gt; on AzBrowse that one of the core maintainers directed me to. It ended up being a pretty great place to start, given that I had an understanding of regex already, so the only new thing was Go.&lt;/p&gt;
&lt;h2&gt;
  
  
  Regex in Go
&lt;/h2&gt;

&lt;p&gt;AzBrowse was already using &lt;a href="https://golang.org/pkg/regexp/"&gt;regexp&lt;/a&gt; for regex parsing, which as I understand it is the "Way to do it" in Go. I actually found the package documentation to be a little convoluted - I was surprised that the docs referenced other sections of the same doc for seemingly simple concepts. For example, &lt;a href="https://golang.org/pkg/regexp/#Regexp.FindAllStringSubmatch"&gt;FindAllStringSubmatch&lt;/a&gt; references a definition of &lt;code&gt;All&lt;/code&gt; that isn't linked nor inline. This added a tiny bit of extra friction to the development process that I wasn't expecting. That said, the library itself seems pretty feature rich - &lt;a href="https://regex101.com/"&gt;Regex101&lt;/a&gt; even has support for it's regex pattern format. This made it easy to test the regex as I was working with it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://regex101.com/r/gNqCAN/2/tests"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--BglNTbpP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/oc4bu5usgqmkwc4j51oe.PNG" alt="Regex101 Example" width="880" height="655"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Testing in Go
&lt;/h2&gt;

&lt;p&gt;AzBrowse uses &lt;a href="//github.com/stretchr/testify"&gt;testify&lt;/a&gt; for authoring and running tests. This was pretty easy to get up to speed on - In fact, I didn't even need to read the docs. A few existing examples and previous experience with other test frameworks was sufficient. This made authoring and modifying tests even faster.&lt;/p&gt;

&lt;p&gt;One challenge I did face was invalid assertion messages. When I broke the existing tests, the assertion failure messages were all the same. It was obvious to me that the assertions (all on different values) were &lt;strong&gt;not&lt;/strong&gt; all failing for the same reason. Can you find the issue in the code below?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// testCases is an array of objects, where each object contains fields:
// desc, input, output
// describing the test, providing the input, and the expected output
for _, test := range testCases {
    t.Run(test.desc, func(t *testing.T) {
        t.Parallel()
        output := stripSecretVals(test.input)
        assert.Equal(t, output, test.expected)
    })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you can, that's awesome! If not don't worry, neither could I. The answer is lies in how &lt;a href="https://github.com/golang/go/wiki/CommonMistakes#using-goroutines-on-loop-iterator-variables"&gt;go closure scopes&lt;/a&gt; work. As I understand it, this occurs because our actual test run occurs inside a closure, and at some point in the future. Because of that, the variable test is bound to the last value in the actual slice (&lt;code&gt;testCases&lt;/code&gt;) for all assertions. &lt;/p&gt;

&lt;p&gt;To fix this, and make the assertion failures correct, I used &lt;a href="https://yourbasic.org/golang/gotcha-shadowing-variables/"&gt;shadowing&lt;/a&gt; - to ensure that the value of test would be correctly bound to the right value in each iteration of the loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// testCases is an array of objects, where each object contains fields:
// desc, input, output
// describing the test, providing the input, and the expected output
for _, test := range testCases {
    // shadow test value to ensure assertion failures
    // print the correct test.expected value
    test := test

    t.Run(test.desc, func(t *testing.T) {
        t.Parallel()
        output := stripSecretVals(test.input)
        assert.Equal(t, output, test.expected)
    })
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After making that change, my assertions correctly displayed the right errors! That made it pretty easy to add more entries to &lt;code&gt;testCases&lt;/code&gt; to add more data-driven tests to the project.&lt;/p&gt;

&lt;h2&gt;
  
  
  New features
&lt;/h2&gt;

&lt;p&gt;With my newly learned Go skills applied, I was able to open &lt;a href="https://github.com/lawrencegripper/azbrowse/pull/194"&gt;a PR&lt;/a&gt; that added more masking of secret values to the &lt;code&gt;--demo&lt;/code&gt; mode of AzBrowse. This mode is super useful for demos or videos, where you want to prevent displaying these sensitive values. I tried it out with my Azure subscription, and got to see everything working! The new masking is added from &lt;a href="https://github.com/lawrencegripper/azbrowse/releases/tag/v1.2.531"&gt;v1.2.531&lt;/a&gt; and up.&lt;/p&gt;

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

&lt;p&gt;Learning the basics of Go was pretty straightforward, thanks to the great documentation put together by the Go team, and some external resources on the web. I was able to transition from learning Go to contributing in under 3 days!&lt;/p&gt;

&lt;p&gt;Thanks for reading. If you've had a chance to learn and use Go, let me know what you thought about the process in the comments below. If you'd like to support me personally, follow me on &lt;a href="https://twitch.tv/ben_greenier"&gt;twitch&lt;/a&gt; and/or &lt;a href="https://twitter.com/bengreenier"&gt;twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;💙🌈&lt;br&gt;
-Ben&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/lawrencegripper/azbrowse"&gt;AzBrowse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://golang.org/doc/effective_go.html"&gt;Effective Go&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gobyexample.com"&gt;Go by Example&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="//github.com/stretchr/testify"&gt;Testify&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Title Photo by &lt;a href="https://unsplash.com/@guogete?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;小谢&lt;/a&gt; on &lt;a href="https://unsplash.com/s/photos/keyboard?utm_source=unsplash&amp;amp;utm_medium=referral&amp;amp;utm_content=creditCopyText"&gt;Unsplash&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>azure</category>
    </item>
    <item>
      <title>Introducing Overlayed - Streamer Overlays Powered By React.</title>
      <dc:creator>Ben Greenier</dc:creator>
      <pubDate>Sat, 30 Nov 2019 20:53:02 +0000</pubDate>
      <link>https://dev.to/bengreenier/introducing-overlayed-streamer-overlays-powered-by-react-17ja</link>
      <guid>https://dev.to/bengreenier/introducing-overlayed-streamer-overlays-powered-by-react-17ja</guid>
      <description>&lt;p&gt;Hi! I’m Ben Greenier — I’m an engineer at Microsoft working to create awesome open source projects with our partners. We get to &lt;a href="https://github.com/microsoft"&gt;create software&lt;/a&gt; to help solve really tricky problems, and &lt;a href="https://www.microsoft.com/developerblog"&gt;share our stories&lt;/a&gt; as we go. This means that as part of my job I get to play with lots of new technologies, learn how to use them, and help other folks do the same.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Overlayed
&lt;/h2&gt;

&lt;p&gt;Recently I've been thinking about how we might create tools that can enable broadcasters to interact with their viewers in new ways. I spend a lot of time watching broadcasters on platforms like &lt;a href="https://twitch.tv"&gt;twitch&lt;/a&gt;, and feel pretty strongly that today's tools for interaction aren't where they could be. I'd like to experiment with some ways I think this interaction could be improved. Overlayed is the first meaningful step toward this experimentation. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/bengreenier/overlayed2"&gt;Overlayed&lt;/a&gt; is a tool that enables streamers to see their overlays atop their desktop. I built it to interact more seamlessly with my viewers. If you want to interact in faster, more interesting ways it may be built for you too. ❤️&lt;/p&gt;

&lt;p&gt;I'll be honest, I haven't done much work on this project over the last year. Part of that is due to some big life changes (international moves are time consuming 🎉). However, part of that is because I wasn't quite sure where I wanted the project to go. That last bit has changed - now I think I know what I want Overlayed to become. &lt;/p&gt;

&lt;h2&gt;
  
  
  React-powered
&lt;/h2&gt;

&lt;p&gt;At it's core, Overlayed is a platform for running small visualizations that are surfaced as a part of a 2D video feed. An explicit goal of the project is for those small visualizations to be easy to &lt;strong&gt;create&lt;/strong&gt; as well as consume. React seems like a logical choice for this creation, given &lt;a href="https://insights.stackoverflow.com/survey/2019#technology-_-web-frameworks"&gt;it's adoption numbers&lt;/a&gt; and (in my opinion) it's ease of use.&lt;/p&gt;

&lt;p&gt;In Overlayed, broadcasters pull in React components, align them on a grid, and get streaming. That means creation of new overlays, is as simple as writing a new React component. For instance, take a look at &lt;a href="https://github.com/bengreenier/overlayed/blob/master/src/app/plugin/Clock/ClockPlugin.tsx"&gt;this clock overlay&lt;/a&gt;. This also means that if something already exists as a React component (say, on NPM, for instance) then it's already a valid overlay.&lt;/p&gt;

&lt;p&gt;Okay okay - Nothing is ever that simple. Of course there's configuration to consider. Balancing broadcaster use-ability and developer-like options (sometimes your component just &lt;strong&gt;needs&lt;/strong&gt; 2129 props 😉) is quite a trick. So far, my approach is to use a contribution model, just like VS Code. Consider the clock example from above - it supports a configurable locale to render time in. From a developer perspective, the author simply &lt;a href="https://github.com/bengreenier/overlayed/blob/master/src/app/plugin/Clock/package.json#L8"&gt;demands that this configuration be contributed&lt;/a&gt;. Once that's in place, Overlayed knows to prompt the broadcaster for such configuration. It does so using &lt;a href="https://github.com/overlayed-app/contributes-form"&gt;contributes-form&lt;/a&gt; a small module that generates a webform using the json-schema content from the contributes entry. For the clock example, the end result that the broadcaster sees looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jUam8uQU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/pxpvlfpbr6hatt60dabk.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jUam8uQU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/pxpvlfpbr6hatt60dabk.PNG" alt='A white html page, rendering a single input field labeled "locale"'&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I think this is a pretty solid model, but there's definitely work to be done, and room for feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Electron-support
&lt;/h2&gt;

&lt;p&gt;One of the value propositions of Overlayed (in my opinion) is that it leverages electron to create full-screen overlays that can be embedded in your desktop, atop all your windows, or behaving like normal windows. This means that as a broadcaster, you're able to see the content your overlays provide, in exactly the same way your viewers can. Electron makes this possible, giving us a cross-platform way to create these os-specific windows (and behaviors) as well as enumerate overlays (remember, these are react components) from disk.&lt;/p&gt;

&lt;p&gt;The experience this enables is pretty cool. On my dev machine right now I have a folder in my user directory of overlays, and when I start up overlayed, electron loads them into a transparent full screen window on top of all my other stuff.&lt;/p&gt;

&lt;p&gt;Again, there's still work to be done (especially with regard to the interaction model - ie: can you type into an overlay? Always? Sometimes?) but I'm pretty excited about where things are headed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Roadmap
&lt;/h2&gt;

&lt;p&gt;I've never come up with a roadmap for a side project before, so I fully expect this to be a bit off. That said, here's the stuff that I'd like to focus on, to improve Overlayed in the near future. If you'd like to help, starting a conversation with me about one of these things is probably the best place to begin.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;del&gt;New product site&lt;/del&gt; (&lt;strong&gt;Live at &lt;a href="https://overlayed.app"&gt;overlayed.app&lt;/a&gt;&lt;/strong&gt;)&lt;/li&gt;
&lt;li&gt;Find reliable cross-platform testers&lt;/li&gt;
&lt;li&gt;Prettier configuration UI&lt;/li&gt;
&lt;li&gt;Support running in browser (without electron)&lt;/li&gt;
&lt;li&gt;Better dev environment&lt;/li&gt;
&lt;li&gt;Better overlay alignment options&lt;/li&gt;
&lt;li&gt;Layout management (different, loadable layouts)&lt;/li&gt;
&lt;li&gt;Camera example&lt;/li&gt;
&lt;li&gt;Audio example&lt;/li&gt;
&lt;li&gt;WebGL example&lt;/li&gt;
&lt;li&gt;Testing. There is currently no testing. There should be testing. 😓&lt;/li&gt;
&lt;li&gt;Overlay "store"&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  That's all for now
&lt;/h2&gt;

&lt;p&gt;Phew - looks like a lot of stuff ahead, better get off DEV and go write some actual code. Thanks for reading! In the future, I'll post deeper dives into the technology choices (and hurdles) that made Overlayed into what it is today. As we add new stuff going forward, I'll be sure to post about that too (this post is part of a series just for this kind of thing).&lt;/p&gt;

&lt;p&gt;If you'd like to support this work financially, &lt;a href="https://www.buymeacoffee.com/bengreenier"&gt;buy me a coffee&lt;/a&gt;. If you'd like to support it with love, follow me on &lt;a href="https://twitch.tv/ben_greenier"&gt;twitch&lt;/a&gt; and/or &lt;a href="https://twitter.com/bengreenier"&gt;twitter&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;💙🌈&lt;br&gt;
-Ben&lt;/p&gt;

</description>
      <category>react</category>
      <category>electron</category>
      <category>showdev</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Hello, World.</title>
      <dc:creator>Ben Greenier</dc:creator>
      <pubDate>Fri, 29 Nov 2019 22:05:58 +0000</pubDate>
      <link>https://dev.to/bengreenier/hello-world-4093</link>
      <guid>https://dev.to/bengreenier/hello-world-4093</guid>
      <description>&lt;p&gt;Hi DEV - I'm new here. I used to post stuff over on &lt;a href="https://medium.com/@bengreenier"&gt;Medium&lt;/a&gt; but have heard great things about this platform and wanted to give it a shot. Hell - if things are even remotely as easy to use as setup has been, I've got high hopes.&lt;/p&gt;

&lt;p&gt;I'll be posting more and more (I hope) about &lt;a href="https://overlayed.app"&gt;overlayed&lt;/a&gt; as I focus on building it out (live on &lt;a href="https://twitch.tv/ben_greenier"&gt;stream&lt;/a&gt; btw)...so stick around.&lt;/p&gt;

&lt;p&gt;Right well, that's all I've got for now - have a lovely evening.&lt;/p&gt;

&lt;p&gt;💙🌈&lt;br&gt;
-Ben&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
