<?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: Erica Pisani</title>
    <description>The latest articles on DEV Community by Erica Pisani (@ericapisani).</description>
    <link>https://dev.to/ericapisani</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%2F868753%2Fbb5f5886-54f3-4a08-90f2-82951c55a03f.jpeg</url>
      <title>DEV Community: Erica Pisani</title>
      <link>https://dev.to/ericapisani</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ericapisani"/>
    <language>en</language>
    <item>
      <title>Git Log's Hidden Gems: Using -S and -L for Powerful Code History Search</title>
      <dc:creator>Erica Pisani</dc:creator>
      <pubDate>Sun, 10 Nov 2024 21:40:02 +0000</pubDate>
      <link>https://dev.to/ericapisani/git-logs-hidden-gems-using-s-and-l-for-powerful-code-history-search-3mdo</link>
      <guid>https://dev.to/ericapisani/git-logs-hidden-gems-using-s-and-l-for-powerful-code-history-search-3mdo</guid>
      <description>&lt;p&gt;Ever needed to track down when a specific piece of code was first introduced in a project?&lt;/p&gt;

&lt;p&gt;As part of some refactoring I had to do recently, I needed to do just that for a variable on a Django model.&lt;/p&gt;

&lt;p&gt;I was already familiar with the basic git log command, but I didn't realize until I needed to find this information that git log has additional options available that give me some powerful search capabilities in the history of a codebase.&lt;/p&gt;

&lt;p&gt;The first one, and the one that helped me find the answer to my question, was &lt;code&gt;-S&lt;/code&gt;, also known as the Git 'pickaxe' option.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git log -S&lt;/code&gt; gets Git to show you only commits that changed the number of occurrences of the string that's being searched for. As an example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git log -S property_i_am_interested_in&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;In learning about this command in Git's documentation, I also noticed a &lt;code&gt;-L&lt;/code&gt; option. This enables 'line log' search, which allows you to view the history of a function or line of code in a given file. For instance:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;git log -L :some_method_name:file_whose_history_you_are_interested_in&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;And, if you need something more specific in your search in either of these cases, both of these options also support regexes.&lt;/p&gt;

&lt;p&gt;While source control providers like Github expose some of this functionality in their web interfaces, sometimes you don't want to go through the hassle of leaving the CLI, in which case these git log options can be very helpful.&lt;/p&gt;

&lt;p&gt;If you're interested in taking a closer look at the docs, along with some examples, you can check out the official Git documentation &lt;a href="https://git-scm.com/book/en/v2/Git-Tools-Searching" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>git</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Enforcement of function keyword arguments in Python</title>
      <dc:creator>Erica Pisani</dc:creator>
      <pubDate>Tue, 22 Oct 2024 03:13:30 +0000</pubDate>
      <link>https://dev.to/ericapisani/enforcement-of-function-keyword-arguments-in-python-1iej</link>
      <guid>https://dev.to/ericapisani/enforcement-of-function-keyword-arguments-in-python-1iej</guid>
      <description>&lt;p&gt;Before starting in my new role a couple of months ago, it had been a &lt;em&gt;very&lt;/em&gt; long time since I had programmed in Python.&lt;/p&gt;

&lt;p&gt;Incidentally, I kept working in roles over the past several years that involved either full-stack Javascript or mostly Javascript with a little bit of another language (most recently Go).&lt;/p&gt;

&lt;p&gt;So it's been fun to stretch my muscles a bit in a different language, especially one as accessible as Python is.&lt;/p&gt;

&lt;p&gt;One feature of the language that I'm enjoying right now is the enforcement of keyword arguments to functions using the &lt;code&gt;kw_only&lt;/code&gt; property made accessible in the &lt;a href="https://docs.python.org/3/library/dataclasses.html" rel="noopener noreferrer"&gt;&lt;code&gt;@dataclass&lt;/code&gt; decorator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It makes code that looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kw_only&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;

&lt;span class="n"&gt;person1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New York&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;raise an error, because the use of &lt;code&gt;kw_only&lt;/code&gt; expects to see something like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;dataclasses&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dataclass&lt;/span&gt;

&lt;span class="nd"&gt;@dataclass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;kw_only&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;
    &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;int&lt;/span&gt;
    &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Unknown&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;

&lt;span class="n"&gt;person1&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;Alice&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;age&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;city&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;New York&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Although the error raised:&lt;br&gt;
&lt;/p&gt;

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

Traceback (most recent call last)
Cell In[8], line 10
      7     city: str = "Unknown"

---&amp;gt; 10 person1 = Person("Alice", 30, "New York")

TypeError: Person.__init__() takes 1 positional argument but 4 were given
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is "clear" in that it will indicate to you that there are too many positional arguments being provided, if you're not familiar with &lt;code&gt;kw_only&lt;/code&gt; it can be a bit puzzling because it looks like you're invoking the function properly.&lt;/p&gt;

&lt;p&gt;If you come from a background of Javascript/Typescript like I do, or have previous experience with languages like Go or Rust that enforce this using something like structs where you're able to provide the arguments in whatever order you like as long as the properties follow the shape of the object/struct, then this will feel familiar and likely a welcome addition to your Python code.&lt;/p&gt;

&lt;p&gt;This is especially useful if you're working with a large number of arguments, some of which may be optional.&lt;/p&gt;

</description>
      <category>python</category>
    </item>
    <item>
      <title>How to install a Nerd Font on Warp</title>
      <dc:creator>Erica Pisani</dc:creator>
      <pubDate>Tue, 08 Oct 2024 22:25:13 +0000</pubDate>
      <link>https://dev.to/ericapisani/how-to-install-a-nerd-font-on-warp-1jfe</link>
      <guid>https://dev.to/ericapisani/how-to-install-a-nerd-font-on-warp-1jfe</guid>
      <description>&lt;p&gt;I started using Vim as my IDE of choice recently, and one of the things I wanted early on was a more visually appealing icon and font set.&lt;/p&gt;

&lt;p&gt;I kept reading about Nerd Fonts so I decided to try installing one, but the instructions for doing so were both clear and yet missing some small details that meant that I wasn't able to get set up as quickly as I would've expected. &lt;/p&gt;

&lt;p&gt;So here are the literal step-by-step instructions for installing a Nerd Font if you're using the Warp terminal and the Homebrew package manager:&lt;/p&gt;

&lt;h2&gt;
  
  
  Install Nerd Fonts via Homebrew
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;brew tap homebrew/cask-fonts&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;brew install --cask font-&amp;lt;FONT NAME&amp;gt;-nerd-font&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Restart Warp
&lt;/h2&gt;

&lt;p&gt;Restart the terminal and go to Warp &amp;gt; Settings &amp;gt; Appearance. There's a section called 'Text' and a dropdown labelled 'Terminal font'. &lt;/p&gt;

&lt;p&gt;Your newly installed Nerd Font from the first step will appear in that list, so you just need to select it.&lt;/p&gt;

&lt;h2&gt;
  
  
  (If using Neovim/Vim) Restart Neovim/Vim
&lt;/h2&gt;

&lt;p&gt;Once I restarted Neovim, the updated font, along with the associated icons, rendered correctly.&lt;/p&gt;

</description>
      <category>terminal</category>
      <category>cli</category>
    </item>
    <item>
      <title>A month of using Vim</title>
      <dc:creator>Erica Pisani</dc:creator>
      <pubDate>Mon, 16 Sep 2024 10:28:18 +0000</pubDate>
      <link>https://dev.to/ericapisani/a-month-of-using-vim-1kcb</link>
      <guid>https://dev.to/ericapisani/a-month-of-using-vim-1kcb</guid>
      <description>&lt;p&gt;I've wanted to dedicate time to learning Vim for probably a decade now. &lt;/p&gt;

&lt;p&gt;When I was just getting started as a junior developer, I remember thinking that the people who used it in their day-to-day were "so cool" and felt a bit of awe at how they achieved what they wanted so quickly without lifting their hands off of the keyboard.&lt;/p&gt;

&lt;p&gt;Fast forward to a month ago and I decided to take the leap - I was going to try and use Vim for a solid month and if I liked it, I'd stay with it. If I didn't, I'd switch back to VS Code (which has been my go-to IDE for almost a decade).&lt;/p&gt;

&lt;p&gt;The barriers to adopting Vim that I could see going into this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;steep learning curve;&lt;/li&gt;
&lt;li&gt;the need for plugins for most of the things that come out-of-the-box in IDEs like VS Code or JetBrains (e.g.: editing multiple instances of a word in a file at the same time); and&lt;/li&gt;
&lt;li&gt;choice paralysis because, for better or for worse, there's so many solid plugin options for solving a particular problem that it can be hard to tell for a new person what might be easier to get started with or if one tool is better suited towards a particular workflow than another.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After an initial upfront cost of spending loads of time researching, following a couple of Youtube 'initial setup' videos, reading various Reddit posts, googling  "how do I do X in vim" dozens and dozens of times, and just general fumbling around, I feel like I've gotten a decent amount of the basics down. &lt;/p&gt;

&lt;p&gt;I'm still spending a little bit of time every week tweaking things or trying to find a new plugin to achieve some functionality that I want, but it's nowhere near as overwhelming as it was at the beginning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Things I learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="http://www.lazyvim.org/" rel="noopener noreferrer"&gt;LazyVim&lt;/a&gt; is a great bootstrapped config for folks looking to just get started as quickly as possible rather than build everything from the ground up&lt;/li&gt;
&lt;li&gt;If you are looking to build from the ground up, &lt;a href="https://www.youtube.com/watch?v=w7i4amO_zaE" rel="noopener noreferrer"&gt;this video from the Primagean&lt;/a&gt; was helpful even though I ultimately ended up going with LazyVim because I wanted as close to an 'out-of-the-box' setup as I could find.&lt;/li&gt;
&lt;li&gt;It does take literally weeks before it starts feeling more natural.
You will spend lots of time getting frustrated with how the workflow isn't what you want and spending hours looking for the right plugins to install (and then wrangling with the installation) and keymappings to set.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;:h user-manual&lt;/code&gt; is a thing in Vim that covers everything. I'd been using Google to figure out how to do things (Reddit in particular was an incredibly helpful resource) and then I stumbled on this at the end of my 3rd week of learning Vim.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Am I happy with my decision to switch to Vim?
&lt;/h2&gt;

&lt;p&gt;Generally, yes. &lt;/p&gt;

&lt;p&gt;Don't get me wrong, I still find some rough edges that I need to get used to and learn how to use more effectively (or to find a plugin that addresses things for me), but the main factor that will keep me on Vim is I find that I'm far less distracted and feel calmer using Vim than I was using VS Code.&lt;/p&gt;

&lt;p&gt;This was not something that I ever considered would happen when adopting Vim. But thinking about it, I realized that VS Code can be noisy with a standard, out-of-the-box setup. &lt;/p&gt;

&lt;p&gt;There are notifications on the bottom right harassing me about something going wrong, some extension they suggest I install based on the language of the file I have open, and various notifications about updates being installed.&lt;/p&gt;

&lt;p&gt;Vim has this window that shows up briefly on the top right about plugins with updates that quickly disappears, but otherwise I'm never bothered again until I reopen a new session.&lt;/p&gt;

&lt;p&gt;So all in all - I'm currently feeling like this was worth the time investment. &lt;/p&gt;

&lt;p&gt;I might feel differently as I start delving more into debugging workflows (VS Code's experience is admittedly pretty nice) but I imagine it's just another thing that'll take a little time to learn and configure.&lt;/p&gt;

</description>
      <category>vim</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Edge Side Includes</title>
      <dc:creator>Erica Pisani</dc:creator>
      <pubDate>Mon, 25 Sep 2023 14:16:38 +0000</pubDate>
      <link>https://dev.to/ericapisani/edge-side-includes-4e4p</link>
      <guid>https://dev.to/ericapisani/edge-side-includes-4e4p</guid>
      <description>&lt;p&gt;A popular use case for edge computing among web and full stack developers is the injection of dynamic content into static assets and pages.&lt;/p&gt;

&lt;p&gt;This technique increases the performance of our applications by allowing us to cache more of our content at the edge or at the Content Delivery Network (CDN), and by reducing the amount of data that needs to be requested and sent to our users from the origin server.&lt;/p&gt;

&lt;p&gt;I recently saw a demo of code that leveraged Edge Side Includes (ESI) to inject dynamic content into static pages as the response was streamed back to the user, and it made me interested in how it works and if I might want to consider using it in my applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is ESI?
&lt;/h2&gt;

&lt;p&gt;ESI is XML markup that's embedded in the HTML itself. It takes the following format:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&amp;lt;esi:include src="&amp;lt;url-to-request&amp;gt;" /&amp;gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As an example, let's say that you have an e-commerce site that has a homepage that is static, unchanging content except for the shopping cart, which differs for each user.&lt;/p&gt;

&lt;p&gt;You would use ESI to make a request for the shopping cart content by doing the following:&lt;/p&gt;

&lt;p&gt;As an example, let's say that you have an e-commerce site that has a homepage that is static, unchanging content except for the shopping cart, which differs for each user.&lt;/p&gt;

&lt;p&gt;You would use ESI to make a request for the shopping cart content by doing the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;html&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;My Ecommerce Site&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"content"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"header"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;img&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/images/logo.jpg"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        **&lt;span class="nt"&gt;&amp;lt;esi:include&lt;/span&gt; &lt;span class="na"&gt;src=&lt;/span&gt;&lt;span class="s"&gt;"/shopping_cart"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;** 
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"items"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item_1"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item_2"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
        ...
        &lt;span class="nt"&gt;&amp;lt;span&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"item_n"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;...&lt;span class="nt"&gt;&amp;lt;/span&amp;gt;&lt;/span&gt;
      &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Source for code: &lt;a href="https://www.fastly.com/blog/using-esi-part-1-simple-edge-side-include" rel="noopener noreferrer"&gt;Fastly&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When the response is returned to the user, rather than see the ESI tag in the HTML, it would be the shopping cart content.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why is this useful?
&lt;/h2&gt;

&lt;p&gt;ESI allows for the 'mixing and matching' of static and dynamic content at an edge server or CDN.&lt;/p&gt;

&lt;p&gt;This is useful because HTML pages mostly contain static content on their pages with a small amount of dynamic elements. At the time that ESI was introduced in 2001, any time dynamic content existed the whole page would have been uncachable and would have had to have been served from the origin server.&lt;/p&gt;

&lt;p&gt;By caching the static elements and only requesting the dynamic ones, we'd have the ability to cache the majority of the page and have faster performance on the request for the dynamic elements since they make up a much smaller subset of the page.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where is ESI at today?
&lt;/h2&gt;

&lt;p&gt;ESI was originally proposed to &lt;a href="https://www.w3.org/TR/esi-lang/" rel="noopener noreferrer"&gt;the W3C in 2001&lt;/a&gt; but was never adopted as a standard. &lt;/p&gt;

&lt;p&gt;Various CDN providers such as Akamai, Fastly, and Cloudflare have support for ESI, but the feature sets between them vary. For example, &lt;a href="https://techdocs.akamai.com/property-mgr/docs/esi-edge-side-includes" rel="noopener noreferrer"&gt;Akamai&lt;/a&gt; and &lt;a href="https://developer.fastly.com/reference/vcl/statements/esi/" rel="noopener noreferrer"&gt;Fastly&lt;/a&gt; parse the ESI tags for you, while Cloudflare &lt;a href="(https://blog.cloudflare.com/edge-side-includes-with-cloudflare-workers/)"&gt;seems to require you to write a (simple) Cloudflare Worker&lt;/a&gt; that does the parsing of the tag and insertion of dynamic content.&lt;/p&gt;

&lt;h2&gt;
  
  
  What are the alternatives to ESI?
&lt;/h2&gt;

&lt;p&gt;Back when ESI was introduced, AJAX requests were considered the alternative approach. Rather than use ESI tags, you would use Javascript to update an empty &lt;code&gt;&amp;lt;span&amp;gt;&lt;/code&gt; with the dynamic content on the page.&lt;/p&gt;

&lt;p&gt;However, the &lt;a href="https://www.patterns.dev/posts/islands-architecture" rel="noopener noreferrer"&gt;islands architecture&lt;/a&gt; is the best alternative today that has similar outcomes to ESI, but differs in where the dynamic content is injected.&lt;/p&gt;

&lt;p&gt;In islands architecture, placeholders are included in the HTML for the dynamic content when the page is being rendered on the server. These placeholders contain both the static content needed as part of the dynamic content and the Javascript needed to fetch the necessary data.&lt;/p&gt;

&lt;p&gt;Whereas content is fetched at an edge location or at the CDN with ESI, using the islands architecture in your application means that the dynamic content is fetched using the returned Javascript on the client side.&lt;/p&gt;

&lt;p&gt;One thing to note though is that the islands architecture approach renders the static content immediately for a page while the dynamic content is being requested, whereas the ESI approach doesn't return the page until all the content is available for it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Should I use ESI in my application?
&lt;/h2&gt;

&lt;p&gt;As always - it depends on your use case. There are &lt;a href="https://www.gosecure.net/blog/2018/04/03/beyond-xss-edge-side-include-injection/" rel="noopener noreferrer"&gt;security concerns to be aware of when using ESI&lt;/a&gt;, and the internet is more available (and reliable) than it was in 2001 when ESI was first introduced.&lt;/p&gt;

&lt;p&gt;If it were me I'd go with the islands architecture approach due to the sense of 'responsiveness' users would get from having the static content rendered immediately on their pages, but it's worth knowing about ESI in case there's a time when you need to move the injection of dynamic content from the client side to the server side (or edge/CDN in this case).&lt;/p&gt;

</description>
      <category>edge</category>
      <category>webdev</category>
      <category>performance</category>
    </item>
    <item>
      <title>How edge computing can reduce your software's carbon footprint</title>
      <dc:creator>Erica Pisani</dc:creator>
      <pubDate>Thu, 17 Aug 2023 11:02:57 +0000</pubDate>
      <link>https://dev.to/ericapisani/how-edge-computing-can-reduce-your-softwares-carbon-footprint-4dif</link>
      <guid>https://dev.to/ericapisani/how-edge-computing-can-reduce-your-softwares-carbon-footprint-4dif</guid>
      <description>&lt;p&gt;I think often about how I can apply my skills as a software engineer in ways that contribute to the betterment of society. The climate crisis in particular is one where on an individual level I don't always feel like I can do much.&lt;/p&gt;

&lt;p&gt;At the QCon London 2023 conference, my favourite track was "&lt;a href="https://qconlondon.com/track/mar2023/architecture-sustainability-mind" rel="noopener noreferrer"&gt;Architecture with Sustainability in Mind&lt;/a&gt;". It left me feeling empowered to do something in my day-to-day work by showing how I could build software that has less of an impact on the environment by having both a sustainability mindset (e.g: asking how I could reduce the energy consumption of the software I build) and tools to help measure the impact of existing software.&lt;/p&gt;

&lt;p&gt;Some of the talks, particularly Sara Bergman's '&lt;a href="https://qconlondon.com/presentation/mar2023/can-green-software-engineering-solve-climate-crisis" rel="noopener noreferrer"&gt;Can Green Software Engineering Help Solve the Climate Crisis?&lt;/a&gt;'  and Adrian Cockcroft's '&lt;a href="https://qconlondon.com/presentation/mar2023/cloud-provider-sustainability-current-status-and-future-directions" rel="noopener noreferrer"&gt;Cloud Provider Sustainability, Current Status and Future Directions&lt;/a&gt;', led me to consider how edge computing fits into this, and specifically:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;How, if at all, can using the edge reduce the carbon emissions of an application?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Bergman's talk referenced this image from the International Energy Agency (IEA) that shows the increasing usage of data centres with respect to the number of workloads they run, the energy that they consume, and the energy consumed in the transmission of data in general:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frugi1c4fbnvo4dcstumx.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frugi1c4fbnvo4dcstumx.png" alt="Global trends in digital and energy indicators, 2015 to 2022" width="800" height="613"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As I've &lt;a href="https://youtu.be/Bg_lPsOhfuc" rel="noopener noreferrer"&gt;spoken about before&lt;/a&gt;, edge computing boosts the performance of our applications by processing and hosting data physically closer to our users.&lt;/p&gt;

&lt;p&gt;By being closer to our users, edge computing reduces the carbon emissions of our software resulting from energy consumption in the following areas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Data centre workloads;&lt;/li&gt;
&lt;li&gt;Data centre energy use; and&lt;/li&gt;
&lt;li&gt;Data transmission network energy use.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It achieves this through the following:&lt;/p&gt;

&lt;h2&gt;
  
  
  Lower request latencies
&lt;/h2&gt;

&lt;p&gt;Request latency is tied to the energy used in the transmission of data over the network. When we have lower request latencies, this means less electricity being used - and essentially wasted - on waiting for a network response from distant servers. &lt;/p&gt;

&lt;p&gt;Idle resources still consume energy so the less time they wait, the better.&lt;/p&gt;

&lt;h2&gt;
  
  
  Less data in the cloud
&lt;/h2&gt;

&lt;p&gt;More data stored closer to the user (such as in an offline-first application) can mean less data that needs to be stored in the cloud. &lt;/p&gt;

&lt;p&gt;This means that you won't need as large of a database which would require a bigger machine (or multiple machines if it's sharded), which reduces the energy needed to store the data at the data centre.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reduced workloads going to the data centre
&lt;/h2&gt;

&lt;p&gt;A reduction in workloads going to the data centre means that you can potentially reduce the size of the machines that you need to run to handle your application traffic at the data centre. &lt;/p&gt;

&lt;p&gt;Smaller machines = smaller energy usage at the data centre.&lt;/p&gt;

&lt;p&gt;Smaller energy usage = a smaller carbon footprint.&lt;/p&gt;

&lt;p&gt;That's math we like to see.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;Based on the way edge computing operates as an architecture - run application logic and host data closer to our users - we can see that leveraging the edge can reduce the carbon footprint of our software through reduced energy usage.&lt;/p&gt;

&lt;p&gt;If we as software developers start adopting the edge where we can - particularly for frequently invoked functionality - we can help in reducing technology's impact on the environment.&lt;/p&gt;

&lt;p&gt;I had hoped to try and get some concrete numbers on the carbon emissions of an edge function run on a cloud computing provider relative to a serverless function hosted at a data centre using &lt;a href="https://www.climatiq.io/" rel="noopener noreferrer"&gt;Climatiq&lt;/a&gt; but unfortunately their Cloud Computing API that could potentially help here isn't part of their free Community tier.&lt;/p&gt;

&lt;p&gt;If anyone has recommendations on alternative tooling to measure this, comment on the post below!&lt;/p&gt;

&lt;p&gt;Finally, if you'd like to learn more about building Green Software, I'd start with taking a look at the &lt;a href="https://greensoftware.foundation/" rel="noopener noreferrer"&gt;Green Software Foundation&lt;/a&gt;. They have a bunch of helpful resources and tools.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>edge</category>
      <category>greensoftware</category>
    </item>
    <item>
      <title>Why are custom headers missing in "304 (Not Modified)" responses?</title>
      <dc:creator>Erica Pisani</dc:creator>
      <pubDate>Tue, 23 Aug 2022 02:35:13 +0000</pubDate>
      <link>https://dev.to/ericapisani/why-are-custom-headers-missing-in-304-not-modified-responses-2bj4</link>
      <guid>https://dev.to/ericapisani/why-are-custom-headers-missing-in-304-not-modified-responses-2bj4</guid>
      <description>&lt;p&gt;&lt;code&gt;304 (Not Modified)&lt;/code&gt; responses minimize the amount of information that needs to be transferred in subsequent requests made after an initial &lt;code&gt;200 (OK)&lt;/code&gt; response if the resources being requested are unchanged&lt;sup id="fnref1"&gt;1&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;This has performance benefits for a website, particularly where larger assets such as images are involved.&lt;/p&gt;

&lt;p&gt;If you are developing a website that makes use of custom headers in  responses, it's worth noting a behaviour with respect to headers that &lt;code&gt;304&lt;/code&gt; responses have that differ from &lt;code&gt;200&lt;/code&gt; responses.&lt;/p&gt;

&lt;p&gt;If a visitor to the website were to inspect their network requests and look at a &lt;code&gt;200&lt;/code&gt; response, they can expect to see not only custom headers defined for the response, but the following headers which relate to the caching of the resource&lt;sup id="fnref2"&gt;2&lt;/sup&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cache-Control&lt;/li&gt;
&lt;li&gt;Content-Location&lt;/li&gt;
&lt;li&gt;Date&lt;/li&gt;
&lt;li&gt;ETag&lt;/li&gt;
&lt;li&gt;Expires&lt;/li&gt;
&lt;li&gt;Vary&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In a &lt;code&gt;304&lt;/code&gt; response however, the specification details that&lt;sup id="fnref1"&gt;1&lt;/sup&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;... a sender &lt;em&gt;SHOULD NOT&lt;/em&gt; generate representation metadata...unless said metadata exists for the purpose of guiding cache updates.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means that that same request, if the resources are cached on the browser, will receive a response that will generally be missing the additional metadata (in this case the custom headers) since they don't tend to serve 'the purpose of guiding cache updates'.&lt;/p&gt;

&lt;p&gt;As an example to illustrate this behaviour, let's use a demo site that Netlify has for the Next.js framework. The specific page that we're interested in can be found &lt;a href="https://netlify-plugin-nextjs-demo.netlify.app/old/image/" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Looking at the 'Network' tab within the browser console, the request fetching the image on the page is the one that we'll take a closer look at. It should look something like:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GET https://netlify-plugin-nextjs-demo.netlify.app/_ipx/w_3840,q_75/%2F_next%2Fstatic%2Fmedia%2Funsplash.9a14a3b9.jpg?url=%2F_next%2Fstatic%2Fmedia%2Funsplash.9a14a3b9.jpg&amp;amp;w=3840&amp;amp;q=75&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;and the &lt;code&gt;200&lt;/code&gt; response headers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;span class="na"&gt;age&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;0&lt;/span&gt;
&lt;span class="na"&gt;cache-control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;public, max-age=0, must-revalidate&lt;/span&gt;
&lt;span class="na"&gt;content-type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;image/jpeg&lt;/span&gt;
&lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Tue, 23 Aug 2022 01:05:36 GMT&lt;/span&gt;
&lt;span class="na"&gt;etag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"3b-XMihzCU33fI+mTMhk6V4yc9TZww"&lt;/span&gt;
&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Netlify&lt;/span&gt;
&lt;span class="na"&gt;strict-transport-security&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;max-age=31536000&lt;/span&gt;
&lt;span class="na"&gt;x-nf-request-id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;01GB43QGZ949EAFF6HBMX480RG&lt;/span&gt;
&lt;span class="na"&gt;x-test&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;foobar&lt;/span&gt;
&lt;span class="na"&gt;X-Firefox-Spdy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;h2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now if we were to refresh the page, we'll see a &lt;code&gt;304&lt;/code&gt; response for that request instead:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;304&lt;/span&gt; &lt;span class="ne"&gt;Not Modified&lt;/span&gt;
&lt;span class="na"&gt;cache-control&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;public, max-age=0, must-revalidate&lt;/span&gt;
&lt;span class="na"&gt;date&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Tue, 23 Aug 2022 01:08:03 GMT&lt;/span&gt;
&lt;span class="na"&gt;etag&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"3b-XMihzCU33fI+mTMhk6V4yc9TZww"&lt;/span&gt;
&lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Netlify&lt;/span&gt;
&lt;span class="na"&gt;x-nf-request-id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;01GB43W0VGYVR87CHSMZ70T4HQ&lt;/span&gt;
&lt;span class="na"&gt;X-Firefox-Spdy&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s"&gt;h2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice how the &lt;code&gt;x-test&lt;/code&gt; custom header near the bottom of the list for the &lt;code&gt;200&lt;/code&gt; response is now missing from the &lt;code&gt;304&lt;/code&gt; response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;I hadn't realized until recently that the minimization of data in a &lt;code&gt;304&lt;/code&gt; response extended to the response headers, and so for those who have run into this behaviour and were also a bit puzzled as to why this happens, I hope this quick explanation was helpful.&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://httpwg.org/specs/rfc7232.html#status.304" rel="noopener noreferrer"&gt;https://httpwg.org/specs/rfc7232.html#status.304&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304" rel="noopener noreferrer"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/304&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Bypassing Git Hooks</title>
      <dc:creator>Erica Pisani</dc:creator>
      <pubDate>Thu, 18 Aug 2022 02:43:22 +0000</pubDate>
      <link>https://dev.to/ericapisani/bypassing-git-hooks-1do5</link>
      <guid>https://dev.to/ericapisani/bypassing-git-hooks-1do5</guid>
      <description>&lt;p&gt;Git hooks are a useful mechanism for performing code quality checks in your local development environment before committing that code or pushing it up to a remote branch. A common quality check that a git hook can perform is running the project's code linter, such as &lt;a href="https://eslint.org/" rel="noopener noreferrer"&gt;eslint&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;While it can be good practice to have these hooks configured within a project, at times they can be annoying when you're trying to share a work-in-progress branch with a team mate by pushing the changes to a remote branch. In such situations, they can feel like they're an impediment towards getting meaningful work done. &lt;/p&gt;

&lt;p&gt;A workaround to this (until you're able to come back and address those issues), is the &lt;code&gt;--no-verify&lt;/code&gt; flag, which bypasses these hooks.&lt;/p&gt;

&lt;p&gt;It's worth noting that because the use of &lt;code&gt;--no-verify&lt;/code&gt; is not able to be suppressed entirely (as far as I'm aware), it's good practice to have the same checks that are performed by the git hooks also be performed as part of a continuous integration/continous delivery pipeline. Doing so will guarantee that code violating quality checks run by configured git hooks are always (eventually) addressed.&lt;/p&gt;

</description>
      <category>git</category>
      <category>programming</category>
    </item>
    <item>
      <title>Useful Github Search Capabilities for Issues and Pull Requests</title>
      <dc:creator>Erica Pisani</dc:creator>
      <pubDate>Mon, 01 Aug 2022 11:48:42 +0000</pubDate>
      <link>https://dev.to/ericapisani/useful-github-search-capabilities-for-issues-and-pull-requests-44ag</link>
      <guid>https://dev.to/ericapisani/useful-github-search-capabilities-for-issues-and-pull-requests-44ag</guid>
      <description>&lt;p&gt;In my day-to-day I often find myself wanting to search for pull requests and issues that I've commented on without necessarily being the author of the pull request/issue. Fortunately, Github has a couple of pretty useful search options for just this purpose!&lt;/p&gt;

&lt;h2&gt;
  
  
  Search by commenter
&lt;/h2&gt;

&lt;p&gt;This is a filter I now use multiple times a day when I'm chatting with someone and have a "I know I've been in a conversation about this somewhere on Github already" moment.&lt;/p&gt;

&lt;p&gt;The syntax for this is &lt;a href="https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests#search-by-commenter" rel="noopener noreferrer"&gt;&lt;code&gt;commenter:&amp;lt;a github username&amp;gt;&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Search for a user that's involved in an issue or pull request
&lt;/h2&gt;

&lt;p&gt;More broad than the 'search by commenter' filter mentioned above, this works as an &lt;code&gt;OR&lt;/code&gt; between the &lt;code&gt;author&lt;/code&gt;, &lt;code&gt;assignee&lt;/code&gt;, &lt;code&gt;mentions&lt;/code&gt;, and &lt;code&gt;commenter&lt;/code&gt; filters.&lt;/p&gt;

&lt;p&gt;The syntax for this is &lt;a href="https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests#search-by-a-user-thats-involved-in-an-issue-or-pull-request" rel="noopener noreferrer"&gt;&lt;code&gt;involves:&amp;lt;a github username&amp;gt;&lt;/code&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap up
&lt;/h2&gt;

&lt;p&gt;If you're interested in taking a look at some of the other search options that Github has (and I highly encourage doing so), you can find their full documentation about this topic &lt;a href="https://docs.github.com/en/search-github/searching-on-github/searching-issues-and-pull-requests" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>github</category>
      <category>programming</category>
      <category>beginners</category>
      <category>productivity</category>
    </item>
    <item>
      <title>Testing a project contained in a monorepo</title>
      <dc:creator>Erica Pisani</dc:creator>
      <pubDate>Sat, 02 Jul 2022 21:29:22 +0000</pubDate>
      <link>https://dev.to/ericapisani/testing-a-project-contained-in-a-monorepo-594i</link>
      <guid>https://dev.to/ericapisani/testing-a-project-contained-in-a-monorepo-594i</guid>
      <description>&lt;p&gt;A 'monorepo' is the term used to describe the organization of multiple distinct projects with well-defined relationships into a single code repository&lt;sup id="fnref1"&gt;1&lt;/sup&gt; rather than having each project be in its own dedicated repository.&lt;/p&gt;

&lt;p&gt;Monorepos have been around for a while, but if you haven't worked with them before, figuring out how to test changes made in one of the projects contained within a monorepo in a local or deployed staging environment might not be the most intuitive.&lt;/p&gt;

&lt;p&gt;For this guide, we're going to assume that we're dealing with Node projects and packages.&lt;/p&gt;

&lt;h2&gt;
  
  
  Local environment
&lt;/h2&gt;

&lt;p&gt;To test a project that lives within a monorepo in your local environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;npm link&lt;/code&gt; within the directory of the monorepo project that you want to test&lt;/li&gt;
&lt;li&gt;Run &lt;code&gt;npm link&lt;/code&gt; within a project that has the monorepo project listed as a dependency that you will be using to test the changes made in the monorepo project&lt;/li&gt;
&lt;li&gt;Run the test project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you're interested in learning more about how &lt;code&gt;npm link&lt;/code&gt; works under the hood that leads to this working, there's a really great Medium article by Alexis Hevia that can be read &lt;a href="https://medium.com/@alexishevia/the-magic-behind-npm-link-d94dcb3a81af" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Staging environment
&lt;/h2&gt;

&lt;p&gt;If you're looking to test your changes in a deployed environment instead, you'll have to do something a little bit different.&lt;/p&gt;

&lt;p&gt;When projects are in their own dedicated repository, it's usually possible to push the changes to a git branch and then reference that branch as the version of the project in the &lt;code&gt;package.json&lt;/code&gt; file such as &lt;code&gt;&amp;lt;your organization or user&amp;gt;/&amp;lt;project repository&amp;gt;#&amp;lt;branch&amp;gt;&lt;/code&gt; (rather than &lt;code&gt;^1.2.3&lt;/code&gt;). &lt;/p&gt;

&lt;p&gt;Due to expectations on the structure of the backing repository needing to match a modules' published structure which doesn't exist in a monorepo project&lt;sup id="fnref2"&gt;2&lt;/sup&gt;, we instead will create a tarball of the modified project and store the tarball on a predictable path to be referenced as the version of the project in the &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;

&lt;p&gt;To do this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Run &lt;code&gt;npm pack&lt;/code&gt; within the directory of the monorepo project that you want to test&lt;/li&gt;
&lt;li&gt;Commit the tarball to a git branch that you're using for testing purposes&lt;/li&gt;
&lt;li&gt;Push the branch to github&lt;/li&gt;
&lt;li&gt;Update the version of the monorepo project to reference the tarball file - &lt;code&gt;"https://github.com/&amp;lt;username&amp;gt;/&amp;lt;repo&amp;gt;/raw/&amp;lt;branch&amp;gt;/[path]/&amp;lt;tarball&amp;gt;"&lt;/code&gt; - within the project that has the monorepo project listed as a dependency that's being used to help test the changes&lt;/li&gt;
&lt;li&gt;Deploy the test project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Credit for the above workaround goes to Stephen Peck and the &lt;a href="https://gist.github.com/stephen-peck/719ec5419c670677f94e97f7ea40ab56" rel="noopener noreferrer"&gt;gist&lt;/a&gt; he made.&lt;/p&gt;

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

&lt;p&gt;While requiring a little bit of work, testing a project contained within a monorepo is not too bad once you're made aware of the setup needed to allow npm to install the modified project correctly.&lt;/p&gt;

&lt;p&gt;Hopefully this was helpful, happy testing!&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://monorepo.tools/" rel="noopener noreferrer"&gt;https://monorepo.tools/&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/stephen-peck/719ec5419c670677f94e97f7ea40ab56" rel="noopener noreferrer"&gt;https://gist.github.com/stephen-peck/719ec5419c670677f94e97f7ea40ab56&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>testing</category>
      <category>javascript</category>
      <category>node</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Write how much work is required, not the work itself</title>
      <dc:creator>Erica Pisani</dc:creator>
      <pubDate>Fri, 24 Jun 2022 15:56:57 +0000</pubDate>
      <link>https://dev.to/ericapisani/write-how-much-work-is-required-not-the-work-itself-5d00</link>
      <guid>https://dev.to/ericapisani/write-how-much-work-is-required-not-the-work-itself-5d00</guid>
      <description>&lt;p&gt;The format for outlining what work needs to be done to achieve an outcome varies from company to company.&lt;/p&gt;

&lt;p&gt;It can be challenging to convey a sense of scope when writing what work needs to be completed, and the result can sometimes amount to ‘do X so a user can do Y’ with the hope that the developer doing the work understands what the writer is getting at or to have a sense of who to ask follow up questions to if they’re unsure.&lt;/p&gt;

&lt;p&gt;Writing as a skill has always been important, but as workplaces become increasingly distributed, it’s even more crucial.&lt;/p&gt;

&lt;p&gt;Misunderstood Github issues, Jira tickets, or however work is tracked, often leads to wasted time and effort. It also makes onboarding new developers difficult as they won’t have a sense of where pieces of functionality live within a codebase.&lt;/p&gt;

&lt;p&gt;Some companies use templates for outlining different types of work such as features, bugs, and chore work (e.g: data migrations), but at others - particularly smaller companies with no formalized process - the format used depends on the individual writer.&lt;/p&gt;

&lt;p&gt;A senior developer&lt;sup id="fnref1"&gt;1&lt;/sup&gt; on a team I previously worked on proposed during a estimation session that instead of writing what the work itself is (“do X so a user can do Y”), we should instead focus on writing how much work is required.&lt;/p&gt;

&lt;p&gt;For example, this change needs to apply to X amount of files, and some of these are frequently used code paths with no test coverage so manual testing will be required.&lt;/p&gt;

&lt;p&gt;By focusing on how much work is required when writing what work needs to be completed, we can get a better sense of the scope of changes needed to accomplish a desired outcome.&lt;/p&gt;

&lt;p&gt;While there will still be gaps in knowledge and work missed when following this format, this tended to give a better sense of scope of the work, which in turn helped feed into better estimations for project planning purposes, and improved the onboarding experience for newer developers on the team.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;&lt;a href="https://www.linkedin.com/in/deon/" rel="noopener noreferrer"&gt;Deon Groenewald&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>agile</category>
      <category>productivity</category>
      <category>writing</category>
    </item>
  </channel>
</rss>
