<?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: Krzysztof Platis</title>
    <description>The latest articles on DEV Community by Krzysztof Platis (@krisplatis).</description>
    <link>https://dev.to/krisplatis</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%2F277429%2Fed9283f3-74c5-48f7-aa6b-dd3560c19b5a.jpg</url>
      <title>DEV Community: Krzysztof Platis</title>
      <link>https://dev.to/krisplatis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/krisplatis"/>
    <language>en</language>
    <item>
      <title>Unveiling the truth: How Google really measures your website's performance 📊</title>
      <dc:creator>Krzysztof Platis</dc:creator>
      <pubDate>Tue, 01 Apr 2025 17:23:35 +0000</pubDate>
      <link>https://dev.to/krisplatis/unveiling-the-truth-how-google-really-measures-your-websites-performance-2n90</link>
      <guid>https://dev.to/krisplatis/unveiling-the-truth-how-google-really-measures-your-websites-performance-2n90</guid>
      <description>&lt;p&gt;&lt;strong&gt;I used to think Google changed my site's ranking based on Lighthouse scores it would measure every time their bot visits my site. 🚦 I was so WRONG! 🤦‍♂️ It turns out that Chrome browsers quietly gather Core Web Vitals from real users, and Google uses the &lt;a href="https://web.dev/articles/defining-core-web-vitals-thresholds#choice-of-percentile" rel="noopener noreferrer"&gt;75th percentile&lt;/a&gt; of this data from the past 28 days to adjust rankings. In other words, 100 points Lighthouse is not your ultimate goal. Perfect in-field measurements on real users' browsers is what you're looking for.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: This article refers to &lt;a href="https://developers.google.com/speed/docs/insights/v5/about" rel="noopener noreferrer"&gt;PageSpeed Insights v5&lt;/a&gt; and &lt;a href="https://github.com/GoogleChrome/lighthouse/blob/main/changelog.md#1240-2025-02-26" rel="noopener noreferrer"&gt;Lighthouse 12.4.0&lt;/a&gt;. When you're reading it, this info might be outdated due to newer versions&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When you use &lt;a href="https://pagespeed.web.dev/" rel="noopener noreferrer"&gt;Google PageSpeed Insights&lt;/a&gt;, you'll see two sections. One is with real users' Web Vitals data with horizontal bars (not a circle) focus only on that, look no further! &lt;/p&gt;

&lt;p&gt;See &lt;a href="https://pagespeed.web.dev/analysis/https-web-dev/zjddxsiv7s?form_factor=mobile" rel="noopener noreferrer"&gt;an example report&lt;/a&gt; for the website &lt;code&gt;https://web.dev&lt;/code&gt;:&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%2Fxoj0dsdehtjf68byuz53.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%2Fxoj0dsdehtjf68byuz53.png" alt="real user data aggregated from last 28 days" width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The second section is not important for Google's ranking at all. It merely reflects the outcome of an on-demand Lighthouse simulation test that was just run on demand on a Google machine. This is just an artificial simulation, susceptible to many variable factors, and it can sometimes be misleading if you're unaware of the complex processes it performs behind the scenes — knowledge that, unfortunately, is not commonly shared.&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%2Fg481id1mnyip5toy5nct.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%2Fg481id1mnyip5toy5nct.png" alt="1-time Lighthouse test run just now" width="800" height="717"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Therefore, the Lighthouse test serves only as a "compass," not an exact "pin on a map" indicating your desired destination. It provides rough directions on where to go and what to improve. Additionally, the Lighthouse test is an artificial tool, much like a "compass," and is highly susceptible to "local magnetic field disturbances" (e.g., temporary poor network conditions). Its non-deterministic nature arises from the &lt;a href="https://calendar.perfplanet.com/2021/how-does-lighthouse-simulated-throttling-work/#averaging_optimistic_and_pessimistic_estimates" rel="noopener noreferrer"&gt;algorithm calculating two artificial scenarios—optimistic and pessimistic network call dependency graphs—and averaging them&lt;/a&gt;, which is sensitive to race condition edge cases based on your actual recorded network call dependency graph.&lt;/p&gt;

</description>
      <category>lighthouse</category>
      <category>webdev</category>
      <category>performance</category>
      <category>programming</category>
    </item>
    <item>
      <title>How to reveal all "Load Diff" sections in a GitHub PR 💫</title>
      <dc:creator>Krzysztof Platis</dc:creator>
      <pubDate>Wed, 08 Jan 2025 23:23:44 +0000</pubDate>
      <link>https://dev.to/krisplatis/how-to-reveal-all-load-diff-sections-in-a-github-pr-2ii1</link>
      <guid>https://dev.to/krisplatis/how-to-reveal-all-load-diff-sections-in-a-github-pr-2ii1</guid>
      <description>&lt;p&gt;&lt;strong&gt;Ever get stuck clicking through endless "Load diff" buttons on a giant GitHub pull request? It's the worst, right? While I’m all for using VSCode for reviews (seriously, &lt;a href="https://dev.to/krisplatis/boost-your-code-review-game-with-custom-vscode-shortcuts-3p8o"&gt;check out my other post on that&lt;/a&gt;), if you’re sticking with GitHub, you can run a simple script in your browser's console to reveal all sections for you.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Paste the script to browser's console
&lt;/h3&gt;

&lt;p&gt;The following script automates what you'd do manually - clicking all buttons to load the diffs — saving you time and effort:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Expand all "Load diff" buttons in a GitHub PR's /files page&lt;/span&gt;
&lt;span class="nx"&gt;clickLoadDiff&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;buttons&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelectorAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.load-diff-button&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)];&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;buttons&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;click&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Load diff - clicked&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nf"&gt;setTimeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;clickLoadDiff&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Load diff - no items to click&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="nf"&gt;clickLoadDiff&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Find the Buttons&lt;/strong&gt;: The script searches for all elements with the class &lt;code&gt;.load-diff-button&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Click Them&lt;/strong&gt;: It clicks each button, using &lt;code&gt;setTimeout&lt;/code&gt; to ensure each click is processed smoothly (in a separate &lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/HTML_DOM_API/Microtask_guide/In_depth" rel="noopener noreferrer"&gt;JS macrotask&lt;/a&gt;).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Repeat if Necessary:&lt;/strong&gt; After a second, it checks if there are more buttons to click and repeats the process until there are none left.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  If you really feel like buying me a coffee
&lt;/h2&gt;

&lt;p&gt;... then feel free to do it. Many thanks! 🙌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/krisplatis" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>github</category>
      <category>pullrequest</category>
      <category>script</category>
      <category>automation</category>
    </item>
    <item>
      <title>How I restored my deleted file in VSCode: A cool trick you should know 🔮</title>
      <dc:creator>Krzysztof Platis</dc:creator>
      <pubDate>Fri, 12 Jul 2024 18:06:55 +0000</pubDate>
      <link>https://dev.to/krisplatis/how-i-restored-my-deleted-file-in-vscode-a-cool-trick-you-should-know-3k95</link>
      <guid>https://dev.to/krisplatis/how-i-restored-my-deleted-file-in-vscode-a-cool-trick-you-should-know-3k95</guid>
      <description>&lt;p&gt;&lt;strong&gt;Hey there! Let me share a crazy experience I had recently. I was working on a lengthy piece of code in a new file in VSCode. After spending hours perfecting it, I accidentally deleted the file before committing it to Git. I only realized the mistake the next day. Total nightmare, right?&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Panic Moment
&lt;/h2&gt;

&lt;p&gt;At first, I was in complete shock. I just stared at my screen, thinking, "Did that really just happen?". My heart started racing, and I felt this wave of panic wash over me. All that hard work, gone. Nothing in the Trash Bin. But then, I started googling whether it was possible to restore a deleted file from VSCode, and I found, to my surprise, a Stack Overflow question where someone in the comments suggested the following cool trick.&lt;/p&gt;

&lt;h2&gt;
  
  
  The lifesaver: Local History in VSCode
&lt;/h2&gt;

&lt;p&gt;So, there's this feature in VSCode called &lt;code&gt;"Local History: Find Entry to Restore."&lt;/code&gt; It basically keeps a history of your files locally, which means you can go back and restore previous versions even if you've deleted them! How cool is that! &lt;/p&gt;

&lt;h3&gt;
  
  
  How I got my file back
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Open command palette&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First, I opened the Command Palette by pressing &lt;code&gt;Cmd+Shift+P&lt;/code&gt; &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Find the local history command&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Then, I pasted the phrase "&lt;code&gt;Local History: Find Entry to Restore&lt;/code&gt;" in the Command Palette. It popped up in the list, so I pressed &lt;code&gt;Enter&lt;/code&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%2Fiamcimw93jut8idswo1r.png" alt="Image description" width="800" height="76"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Search for my deleted file&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Next, it asked me to type the name of the file I deleted. I did, and to my happy surprise, my deleted file was there!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Choose the right version&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After pressing &lt;code&gt;Enter&lt;/code&gt;, I was presented with a list of snapshots of my file that VSCode remembered for me. I picked the most recent version and pressed &lt;code&gt;Enter&lt;/code&gt; again. &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%2F0rgr4jv0pf0nxt7s4kke.png" alt="Image description" width="800" height="578"&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Restore the file&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finally, just like that, VSCode restored the contents of my file! It was like magic! I was so happy. Then it sufficed to just save this file contents on my disk with the hotkey &lt;code&gt;Cmd+S&lt;/code&gt; and I could commit it now with Git. 🎉&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The Happy Ending
&lt;/h2&gt;

&lt;p&gt;Seeing my code back on the screen was such a relief. I avoided a counter-productive big loss of my work. Not only did I get my work back, but I also learned a super useful trick that I'm now excited to share with you. I hope you'll never need to use it, but... it's better to be prepared 😉&lt;/p&gt;

&lt;p&gt;Feel free to buy me a coffee 😉 ☕️👇 Thank you! 🤗&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/krisplatis" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-yellow.png" alt="Buy Me A Coffee" width="545" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>panic</category>
      <category>knowyourtools</category>
      <category>lostfiles</category>
    </item>
    <item>
      <title>Boost your Code Review game with custom VSCode shortcuts ⌨️</title>
      <dc:creator>Krzysztof Platis</dc:creator>
      <pubDate>Wed, 19 Jun 2024 20:42:09 +0000</pubDate>
      <link>https://dev.to/krisplatis/boost-your-code-review-game-with-custom-vscode-shortcuts-3p8o</link>
      <guid>https://dev.to/krisplatis/boost-your-code-review-game-with-custom-vscode-shortcuts-3p8o</guid>
      <description>&lt;p&gt;&lt;strong&gt;If you're a tech lead who spends a lot of time reviewing code and helping others, you know how crucial it is to be efficient. Over time, I've set up some handy keyboard shortcuts in Visual Studio Code (VSCode) that make my life a whole lot easier. Let me show you my &lt;code&gt;keybindings.json&lt;/code&gt; and how these shortcuts can help you too.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Switch between Diff and Source
&lt;/h3&gt;

&lt;p&gt;Switching between the diff view and the source view can be such a hassle, especially during code reviews.&lt;/p&gt;

&lt;p&gt;These shortcuts make it super easy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Toggle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;between&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;editor&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cmd+ctrl+d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"gitlens.openWorkingFile"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"when"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"editorFocus &amp;amp;&amp;amp; (isInDiffEditor || editorReadonly)"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Toggle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;between&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;not&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;diff&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;editor&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cmd+ctrl+d"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"git.openChange"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"when"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"editorFocus &amp;amp;&amp;amp; !(isInDiffEditor || editorReadonly)"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How to Use&lt;/strong&gt;: Just hit &lt;code&gt;cmd+ctrl+d&lt;/code&gt; to switch between the diff and source views, no matter where you are. It feels like magic!&lt;/p&gt;

&lt;p&gt;Note: Please make sure to install the &lt;a href="https://marketplace.visualstudio.com/items?itemName=eamodio.gitlens" rel="noopener noreferrer"&gt;GitLens VSCode extension&lt;/a&gt; for the shortcut to work. Otherwise, you'd need to replace the command &lt;code&gt;"gitlens.openWorkingFile"&lt;/code&gt; with &lt;code&gt;"git.openFile"&lt;/code&gt; in the JSON above.&lt;/p&gt;

&lt;p&gt;Note 2: Of course, you might want to use any different shortcut, if you like! I gave &lt;code&gt;cmd+ctrl+d&lt;/code&gt; only as an example that works for me. &lt;/p&gt;

&lt;p&gt;Note 3: &lt;code&gt;cmd+ctrl+d&lt;/code&gt; is already a global default shortcut for the Mac's native action "Lookup Dictionary". To disable it, see instructions in &lt;a href="https://apple.stackexchange.com/a/29398" rel="noopener noreferrer"&gt;https://apple.stackexchange.com/a/29398&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Navigate Changes in File
&lt;/h3&gt;

&lt;p&gt;When you're deep into a code review, navigating through changes efficiently is key. These shortcuts help you jump between changes within a single file effortlessly, without needing to manually scroll to the next change:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;next&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;change&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;compare&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;editor&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ctrl+cmd+down"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workbench.action.compareEditor.nextChange"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"when"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"textCompareEditorVisible"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Go&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;previous&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;change&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;compare&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;editor&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ctrl+cmd+up"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"workbench.action.compareEditor.previousChange"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"when"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"textCompareEditorVisible"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How to Use&lt;/strong&gt;: Use &lt;code&gt;ctrl+cmd+down&lt;/code&gt; to jump to the next change and &lt;code&gt;ctrl+cmd+up&lt;/code&gt; to go back to the previous change in the compare editor. This makes navigating through changes in your code reviews quick and efficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  See Tree of all Changed Files
&lt;/h3&gt;

&lt;p&gt;During code reviews, I often need to switch between the tree of changed files and the tree of all files in the repo. This shortcut makes that transition seamless:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Focus&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;on&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;active&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;pull&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;request&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shift+cmd+l"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prStatus:github.focus"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How to Use&lt;/strong&gt;: With the official GitHub Pull Request extension installed, press &lt;code&gt;shift+cmd+l&lt;/code&gt; to quickly focus on the active pull request. This keeps your workflow smooth and uninterrupted. When you need to switch to a tree of all files in the project, you can use the default shortcut &lt;code&gt;shift+cmd+e&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Mark File as Viewed
&lt;/h3&gt;

&lt;p&gt;Once you've finished reviewing a file, you want to mark it as viewed. Normally it requires clicking a tiny checkbox in VSCODE with a mouse, but it's much faster to do it with a smart keyboard shortcut. Here's how to setup it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"cmd+ctrl+c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"runCommands"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"args"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"commands"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"pr.markFileAsViewed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prStatus:github.focus"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How to Use&lt;/strong&gt;: Press &lt;code&gt;cmd+ctrl+c&lt;/code&gt; to mark the current file as viewed. Moreover, your focus will now move to the pane of all changed files, allowing you to quickly navigate to the next file by pressing the &lt;code&gt;Arrow Down&lt;/code&gt; and &lt;code&gt;Enter&lt;/code&gt;. This small tweak can significantly streamline your review process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick GitHub Link for Current Line
&lt;/h3&gt;

&lt;p&gt;I share specific lines of our codebase from GitHub all the time. These shortcuts make copying and opening GitHub permalinks a no-brainer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Copy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;GitHub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;permalink&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shift+cmd+c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"issue.copyGithubPermalink"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Open&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;GitHub&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;permalink&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"key"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"shift+cmd+x"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"issue.openGithubPermalink"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;How to Use&lt;/strong&gt;: Press &lt;code&gt;shift+cmd+c&lt;/code&gt; to copy a permalink to your clipboard and &lt;code&gt;shift+cmd+x&lt;/code&gt; to open a permalink right in your browser. So simple and fast!&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrapping Up
&lt;/h3&gt;

&lt;p&gt;These custom VSCode shortcuts have saved me tons of time and made my work a lot smoother. Whether you’re reviewing code, sharing GitHub links or switching between diff and source file of your own changes, these shortcuts can seriously up your game. Give them a try and see how much easier your workflow can get!&lt;/p&gt;

&lt;h2&gt;
  
  
  If you really feel like buying me a coffee
&lt;/h2&gt;

&lt;p&gt;... then feel free to do it. Many thanks! 🙌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/krisplatis" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>shortcuts</category>
      <category>keybindings</category>
      <category>codereview</category>
    </item>
    <item>
      <title>Clear Site Data in Chrome - quickly, without touching your mouse 🗑️</title>
      <dc:creator>Krzysztof Platis</dc:creator>
      <pubDate>Tue, 09 Apr 2024 16:32:53 +0000</pubDate>
      <link>https://dev.to/krisplatis/clear-site-data-in-chrome-quickly-without-touching-your-mouse-22je</link>
      <guid>https://dev.to/krisplatis/clear-site-data-in-chrome-quickly-without-touching-your-mouse-22je</guid>
      <description>&lt;p&gt;&lt;strong&gt;To &lt;em&gt;Clear Site Data&lt;/em&gt; in Chrome quickly, without using your mouse:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Press &lt;code&gt;F12&lt;/code&gt;&lt;/strong&gt; to open Chrome Dev Tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Press &lt;code&gt;Cmd+Shift+P&lt;/code&gt;&lt;/strong&gt; to open the command palette.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Type "Clear site data"&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Hit &lt;code&gt;Enter&lt;/code&gt;&lt;/strong&gt; to execute. 🎉&lt;/li&gt;
&lt;/ul&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%2Flege8a1reflsjpqi4zz0.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%2Flege8a1reflsjpqi4zz0.png" alt="Image description" width="519" height="140"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;This will clear the all the &lt;code&gt;localStorage&lt;/code&gt;, &lt;code&gt;sessionStorage&lt;/code&gt;, cookies, service workers, etc. for your current site.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you really feel like buying me a coffee
&lt;/h2&gt;

&lt;p&gt;... then feel free to do it. Many thanks! 🙌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/krisplatis" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>chrome</category>
      <category>devtools</category>
      <category>chromedevtools</category>
    </item>
    <item>
      <title>ng update @my/lib@version - Which migration schematics will be executed? 🤷</title>
      <dc:creator>Krzysztof Platis</dc:creator>
      <pubDate>Sun, 04 Feb 2024 08:32:35 +0000</pubDate>
      <link>https://dev.to/krisplatis/ng-update-mylibversion-which-migration-schematics-will-be-executed-4304</link>
      <guid>https://dev.to/krisplatis/ng-update-mylibversion-which-migration-schematics-will-be-executed-4304</guid>
      <description>&lt;p&gt;&lt;strong&gt;The command &lt;code&gt;ng update @my/lib@version&lt;/code&gt; downloads the specified version of the library and launches all schematics listed in its &lt;code&gt;migrations.json&lt;/code&gt; that have an appropriate property of "version" within the semver range from &lt;code&gt;&amp;gt;installedVersion&lt;/code&gt; to &lt;code&gt;&amp;lt;=targetVersion&lt;/code&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Example
&lt;/h3&gt;

&lt;p&gt;For instance, consider the following conditions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The locally installed version of &lt;code&gt;@my/lib&lt;/code&gt; in my project is &lt;code&gt;1.1.0&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The latest published npm version of &lt;code&gt;@my/lib&lt;/code&gt; is &lt;code&gt;4.8.9&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Now, when we run &lt;code&gt;ng update @my/lib&lt;/code&gt; (or &lt;code&gt;...@my/lib@4&lt;/code&gt; or &lt;code&gt;...@my/lib@4.8&lt;/code&gt; or &lt;code&gt;...@my/lib@4.8.9&lt;/code&gt;, it doesn't matter),&lt;/li&gt;
&lt;li&gt;and the file &lt;code&gt;migration.json&lt;/code&gt; of &lt;code&gt;@my/lib&lt;/code&gt; contains migrations for the &lt;code&gt;"version"&lt;/code&gt; &lt;code&gt;2.0.0&lt;/code&gt; and &lt;code&gt;4.5.0&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"schematics"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"migration-v2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2.0.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"factory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./migration-v2#migrate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Migration for v2.0.0"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"migration-v4.5"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"4.5.0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"factory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./migration-v4_5#migrate"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Migration for v4.5.0"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...then the following migrations will be executed, in ascending order of version:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Migration for v2.0.0&lt;/li&gt;
&lt;li&gt;Migration for v4.5.0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is because they fall between the currently installed version (&lt;code&gt;&amp;gt;1.1.0&lt;/code&gt;) and the target version (&lt;code&gt;&amp;lt;=4.8.9&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Note: If we were to run &lt;code&gt;ng update @my/lib@&lt;/code&gt; with the target version lower than &lt;code&gt;4.5.0&lt;/code&gt;, for example, &lt;code&gt;ng update @my/lib@3&lt;/code&gt;, only the following migration would be executed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Migration for v2.0.0&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, the &lt;code&gt;Migration for v4.5.0&lt;/code&gt; would not run.&lt;/p&gt;

&lt;h3&gt;
  
  
  Angular CLI source code analysis
&lt;/h3&gt;

&lt;p&gt;Here's a proof in the source code of the Angular CLI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If the "version" field from &lt;code&gt;migrations.json&lt;/code&gt; belongs to &lt;em&gt;the appropriate semver range&lt;/em&gt;, then this migration is launched (see &lt;a href="https://github.com/angular/angular-cli/blob/e880531de68f01ee7b7a3e84007a8eeefc1c4f9d/packages/angular/cli/src/commands/update/cli.ts#L373" rel="noopener noreferrer"&gt;source&lt;/a&gt;). &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;em&gt;The appropriate semver range&lt;/em&gt; means something between &lt;code&gt;&amp;gt;fromVersion&lt;/code&gt; and &lt;code&gt;&amp;lt;=toVersion&lt;/code&gt; (see sources: &lt;a href="https://github.com/angular/angular-cli/blob/e880531de68f01ee7b7a3e84007a8eeefc1c4f9d/packages/angular/cli/src/commands/update/cli.ts#L357-L359" rel="noopener noreferrer"&gt;executeMigration()&lt;/a&gt; and &lt;a href="https://github.com/angular/angular-cli/blob/e880531de68f01ee7b7a3e84007a8eeefc1c4f9d/packages/angular/cli/src/commands/update/cli.ts#L860-L861" rel="noopener noreferrer"&gt;invocation of executeMigration()&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The &lt;code&gt;fromVersion&lt;/code&gt; and &lt;code&gt;toVersion&lt;/code&gt; respectively mean: &lt;code&gt;installed.version&lt;/code&gt; and &lt;code&gt;target.version&lt;/code&gt; (see &lt;a href="https://github.com/angular/angular-cli/blob/e880531de68f01ee7b7a3e84007a8eeefc1c4f9d/packages/angular/cli/src/commands/update/schematic/index.ts#L336-L341" rel="noopener noreferrer"&gt;source&lt;/a&gt;).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Therefore, all migrations between &lt;code&gt;&amp;gt;installed.version&lt;/code&gt; and &lt;code&gt;&amp;lt;=target.version&lt;/code&gt; are launched.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you really feel like buying me a coffee
&lt;/h2&gt;

&lt;p&gt;... then feel free to do it. Many thanks! 🙌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/krisplatis" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>schematics</category>
    </item>
    <item>
      <title>My essential tools for authoring Angular code</title>
      <dc:creator>Krzysztof Platis</dc:creator>
      <pubDate>Tue, 10 Oct 2023 10:43:22 +0000</pubDate>
      <link>https://dev.to/krisplatis/my-essential-tools-for-authoring-angular-code-27kn</link>
      <guid>https://dev.to/krisplatis/my-essential-tools-for-authoring-angular-code-27kn</guid>
      <description>&lt;h2&gt;
  
  
  VSCode extensions
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=Angular.ng-template" rel="noopener noreferrer"&gt;Angular Language Service&lt;/a&gt; - for code completion and error checking in the source code&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=infinity1207.angular2-switcher" rel="noopener noreferrer"&gt;angular2-switcher&lt;/a&gt; - for easy switching in between HTML, TS, SPEC files of the same component/service with 3 simple hotkeys&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker" rel="noopener noreferrer"&gt;Code Spell Checker&lt;/a&gt; - to aviod typos in the codde 😉&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  VSCode Settings
&lt;/h2&gt;

&lt;p&gt;Open to VSCode &lt;code&gt;settings.json&lt;/code&gt; file (how: open command palette with &lt;code&gt;Cmd+Shift+P&lt;/code&gt; then type: &lt;code&gt;Preferences: Open User Settings (JSON)&lt;/code&gt;&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%2Ftbgyzvep8xq70nkdymys.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%2Ftbgyzvep8xq70nkdymys.png" alt="Image description" width="800" height="211"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;and then add the following settings:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"editor.codeActionsOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source.organizeImports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source.addMissingImports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"editor.formatOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  If you really feel like buying me a coffee
&lt;/h2&gt;

&lt;p&gt;... then feel free to do it. Many thanks! 🙌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/krisplatis" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>setup</category>
      <category>angular</category>
      <category>vscode</category>
      <category>tooling</category>
    </item>
    <item>
      <title>Mastering Chrome DevTools: Edit production code on-the-fly in your browser ✏️</title>
      <dc:creator>Krzysztof Platis</dc:creator>
      <pubDate>Fri, 21 Jul 2023 16:44:10 +0000</pubDate>
      <link>https://dev.to/krisplatis/mastering-chrome-devtools-edit-production-code-on-the-fly-in-your-browser-1ial</link>
      <guid>https://dev.to/krisplatis/mastering-chrome-devtools-edit-production-code-on-the-fly-in-your-browser-1ial</guid>
      <description>&lt;p&gt;&lt;strong&gt;Chrome DevTools allows not only for pretty formatting and debugging the minified JS code of any production website, but also (which was surprising to me!) gives you ability to edit this production code in your browser on the fly! You can apply your custom local edits to any source JS file and after the next page refresh your code will run instead of the default one. You just need to enable the hidden feature of Devtools, called &lt;em&gt;&lt;a href="https://developer.chrome.com/docs/devtools/overrides/#make-changes" rel="noopener noreferrer"&gt;local overrides&lt;/a&gt;&lt;/em&gt;. Thanks to that, you can not only conveniently inspect the production code of any website, but also comfortably even try out an idea of a possible bugfix in this production code without a need to deploy the updated version of code, but just making edits locally in your browser!&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Edit JS code locally in your browser!
&lt;/h2&gt;

&lt;p&gt;To edit any file of any website, you need to first make sure you have enabled the feature of Chrome DevTools called &lt;em&gt;&lt;a href="https://developer.chrome.com/docs/devtools/overrides/#make-changes" rel="noopener noreferrer"&gt;local overrides&lt;/a&gt;&lt;/em&gt;. Here's how to do it quickly: in DevTools window open the command palette by pressing the hotkey &lt;code&gt;Cmd+Shift+P&lt;/code&gt; (similar to what you would do e.g. in &lt;em&gt;Visual Studio Code&lt;/em&gt;) and then type &lt;em&gt;Enable override network requests&lt;/em&gt;, and hit &lt;code&gt;Enter&lt;/code&gt;. It suffices that you enable this feature once.&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%2F70rzla681mamrpwlrra1.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%2F70rzla681mamrpwlrra1.png" alt="Image description" width="800" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Don't worry when you see that your &lt;code&gt;Network&lt;/code&gt; tab now shows a warning sign "⚠️" - it only indicates that some of the files might be now replaced by your customized versions:&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%2F4w8r540tsk6f9fj88mso.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%2F4w8r540tsk6f9fj88mso.png" alt="Image description" width="800" height="144"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then you can edit any source file of the website! Just right-click at any source code filename and from the opened contextual menu please select the option &lt;em&gt;Save for overrides&lt;/em&gt;. &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%2Ftwyfv5uinmbvp8hst3qw.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%2Ftwyfv5uinmbvp8hst3qw.png" alt="Image description" width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You might notice a small pink dot near the icon of this filename - it's signaling that your local version will take precedence over the default source code (but only after the page refresh).&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%2Fdpzcgkx4pk6mxd9i6351.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%2Fdpzcgkx4pk6mxd9i6351.png" alt="Image description" width="406" height="50"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So now you can edit this file and save your changes many times with pressing the hotkey &lt;code&gt;Cmd+S&lt;/code&gt;. And after you refresh the page, your customized source code should be used instead of the default one! This way you can for instance conveniently try out an idea of a possible bugfix in the production website, without a need to deploy a new version of code, but just make edits locally in your browser!&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%2Ft8nyigfrpqxyrysxvmsl.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%2Ft8nyigfrpqxyrysxvmsl.png" alt="Image description" width="800" height="405"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Notes
&lt;/h3&gt;

&lt;p&gt;The same technique can be applied to override also HTML files, not only JS ones.&lt;/p&gt;

&lt;p&gt;For more, see the official Chrome DevTools docs on the &lt;a href="https://developer.chrome.com/docs/devtools/changes/#view-changes" rel="noopener noreferrer"&gt;Local network overrides&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you really feel like buying me a coffee
&lt;/h2&gt;

&lt;p&gt;... then feel free to do it. Many thanks! 🙌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/krisplatis" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-yellow.png" alt="Buy Me A Coffee" width="545" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Appendix: Pretty print and debug minified JS code
&lt;/h3&gt;



&lt;h4&gt;
  
  
  Pretty print the minified JS code
&lt;/h4&gt;

&lt;p&gt;Open the Chrome DevTools' tab &lt;code&gt;Sources&lt;/code&gt; and in the left hand pane open a file that interests you. Then click the icon with curly braces &lt;code&gt;{ }&lt;/code&gt; in the bottom left corner of the central view with the source code. &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%2Fc4zj52n2c0lr3uhcuo61.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%2Fc4zj52n2c0lr3uhcuo61.png" alt="Image description" width="800" height="408"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After clicking this button, the source code should get a nice formatting and lines indentation, to allow to better readability of the code:&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%2Fu6c9rn33f9sxvk03re17.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%2Fu6c9rn33f9sxvk03re17.png" alt="Image description" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Inspect and debug the code
&lt;/h4&gt;

&lt;p&gt;Now you can conveniently set anywhere a breakpoint, which will stop the execution of the code in a line that interests you, allowing for inspecting deeper the context, values of variables, the other functions higher in the stacktrace, etc. &lt;/p&gt;

&lt;p&gt;Here's a screenshot of setting a breakpoint:&lt;br&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%2Fictfu5jqrmqpynbph1yp.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%2Fictfu5jqrmqpynbph1yp.png" alt="Image description" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The screenshot below shows how the execution was paused at this line after refreshing the page (and therefore rerunning the code). Please also note in the right-hand pane, that you can inspect values of all &lt;code&gt;Local&lt;/code&gt; variables while the execution stopped at this line&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%2Fo6zz224t27j55orwcjob.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%2Fo6zz224t27j55orwcjob.png" alt="Image description" width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you scroll down the right-hand pane you will be able to also review the &lt;em&gt;Call Stack&lt;/em&gt; of the currently paused code. Thanks to that you can understand which higher functions led to eventually executing the currently paused line of code.&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%2Fxch3vif9bem8zaaknm3b.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%2Fxch3vif9bem8zaaknm3b.png" alt="Image description" width="800" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Moreover, inside the &lt;em&gt;Call Stack&lt;/em&gt; section you can also click any of those higher functions' names and then you will see the source code of the higher function. For instance below you can see the body of the 3rd function in the &lt;em&gt;Call Stack&lt;/em&gt; which I clicked &lt;code&gt;(anonymous)&lt;/code&gt;:&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%2Fgdln240h60x8zse2h2sf.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%2Fgdln240h60x8zse2h2sf.png" alt="Image description" width="800" height="303"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While having this higher function's body opened, we can scroll up the right-hand pane and inspect &lt;code&gt;Local&lt;/code&gt; variables from the context and time of this higher function's invocation!&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%2Fjdnwehsk5ixcwgsatfol.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%2Fjdnwehsk5ixcwgsatfol.png" alt="Image description" width="800" height="298"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;That's it, I hope you find it useful! Happy debugging and editing the production code 😉&lt;/p&gt;

</description>
      <category>debugging</category>
      <category>chrome</category>
      <category>devtools</category>
      <category>production</category>
    </item>
    <item>
      <title>The importance of order in Angular Dependency Injection providers 🔀</title>
      <dc:creator>Krzysztof Platis</dc:creator>
      <pubDate>Mon, 10 Jul 2023 09:42:18 +0000</pubDate>
      <link>https://dev.to/krisplatis/the-importance-of-order-in-angular-dependency-injection-providers-4g31</link>
      <guid>https://dev.to/krisplatis/the-importance-of-order-in-angular-dependency-injection-providers-4g31</guid>
      <description>&lt;p&gt;&lt;strong&gt;The order of providers in Angular Dependency Injection matters.&lt;br&gt;
If you provide a custom implementation "before" the default implementation is provided, then the default implementation will take precedence. The "last provided" wins. Angular traverses the tree of modules, grabs all providers and flatten them all to one list. In case of conflicts, then the last provided in the list wins.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Angular traverses modules tree, starting from the root module (often named &lt;code&gt;AppModule)&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;first are providers from imported modules (depth-first), e.g. &lt;code&gt;imports: [SomeModule, ...]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;then providers from static methods of imported modules, e.g. &lt;code&gt;imports: [SomeModule.forRootOrWhateverMethodName(), ...]&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;then providers from the currently analyzed module &lt;code&gt;providers: [...]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As ab evidence, see the &lt;a href="https://stackblitz.com/edit/stackblitz-starters-g1rblhib?file=src%2Fapp%2Fapp.component.ts,src%2Fapp%2Fapp.component.html,src%2Fapp%2Fapp.module.ts" rel="noopener noreferrer"&gt;example Stackblitz&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you really feel like buying me a coffee
&lt;/h2&gt;

&lt;p&gt;... then feel free to do it. Many thanks! 🙌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/krisplatis" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>dependencyinjection</category>
      <category>short</category>
    </item>
    <item>
      <title>Angular SSR v16: saying goodbye to a sneaky trick - macrotask wrapping for HTTP calls 👋</title>
      <dc:creator>Krzysztof Platis</dc:creator>
      <pubDate>Mon, 03 Jul 2023 06:41:11 +0000</pubDate>
      <link>https://dev.to/krisplatis/angular-ssr-v16-saying-goodbye-to-a-sneaky-trick-macrotask-wrapping-for-http-calls-487b</link>
      <guid>https://dev.to/krisplatis/angular-ssr-v16-saying-goodbye-to-a-sneaky-trick-macrotask-wrapping-for-http-calls-487b</guid>
      <description>&lt;p&gt;&lt;strong&gt;Since version 16, Angular SSR no longer counts outgoing HTTP requests as macrotasks in &lt;code&gt;Zone.js&lt;/code&gt;, but uses an internal http interceptor function instead. As a consequence, if you used a technique of &lt;a href="https://dev.to/krisplatis/how-to-find-out-why-angular-ssr-hangs-track-ngzone-tasks-4nbd"&gt;tracking &lt;code&gt;NgZone&lt;/code&gt; macrotasks for debugging hanging SSR&lt;/a&gt;, it will no longer reveal long pending HTTP requests for you. But the good news is you can still implement yourself a custom &lt;a href="https://angular.io/api/common/http/HttpInterceptor" rel="noopener noreferrer"&gt;&lt;code&gt;HttpInterceptor&lt;/code&gt;&lt;/a&gt; for counting pending requests.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Before Angular 16 - wrapping HTTP requests as macrotasks
&lt;/h3&gt;

&lt;p&gt;Before version 16, Angular created in &lt;code&gt;Zone.js&lt;/code&gt; an artificial macrotask named &lt;a href="https://github.com/angular/angular/blob/15.2.x/packages/platform-server/src/http.ts#L85-L86" rel="noopener noreferrer"&gt;&lt;code&gt;ZoneMacroTaskWrapper.subscribe&lt;/code&gt;&lt;/a&gt; for &lt;a href="https://github.com/angular/angular/blob/15.2.x/packages/platform-server/src/http.ts#L121" rel="noopener noreferrer"&gt;each outgoing HTTP request&lt;/a&gt; in the &lt;a href="https://github.com/angular/angular/blob/15.2.x/packages/platform-server/src/http.ts#L105-L106" rel="noopener noreferrer"&gt;special HttpHandler&lt;/a&gt;. Angular completed manually such an artifical macrotask &lt;a href="https://github.com/angular/angular/blob/15.2.x/packages/platform-server/src/http.ts#L58" rel="noopener noreferrer"&gt;when the HTTP request completed&lt;/a&gt;. Thanks to this trick, &lt;code&gt;Zone.js&lt;/code&gt; treated every pending outgoing HTTP request as a macrotask, even though by nature HTTP requests are not JavaScript macrotasks.&lt;/p&gt;

&lt;p&gt;The observable &lt;a href="https://angular.io/api/core/ApplicationRef#isStable" rel="noopener noreferrer"&gt;&lt;code&gt;ApplicationRef.isStable&lt;/code&gt;&lt;/a&gt;, which is used internally by Angular SSR &lt;a href="https://github.com/angular/angular/blob/16.0.x/packages/platform-server/src/utils.ts#L59" rel="noopener noreferrer"&gt;to hold the serialization of HTML until the app is stable&lt;/a&gt;, depended directly on the &lt;a href="https://github.com/angular/angular/blob/15.2.x/packages/core/src/application_ref.ts#L799-L804" rel="noopener noreferrer"&gt;&lt;code&gt;NgZone.onStable&lt;/code&gt;&lt;/a&gt;, which emitted only when there were no pending microtasks and macrotasks (so also when there were no pending outgoing HTTP requests).&lt;/p&gt;

&lt;h2&gt;
  
  
  Since Angular 16 - no more wrapping HTTP requests as macrotasks
&lt;/h2&gt;

&lt;p&gt;Since version 16, Angular removed the trick of wrapping HTTP calls as &lt;code&gt;Zone.js&lt;/code&gt; macrotasks. And Angular came up with a new, complementary solution for waiting until HTTP requests complete. Now Angular tracks pending HTTP requests with a special new class &lt;a href="https://github.com/angular/angular/blob/16.0.x/packages/core/src/initial_render_pending_tasks.ts#L24" rel="noopener noreferrer"&gt;&lt;code&gt;InitialRenderPendingTasks&lt;/code&gt;&lt;/a&gt; which counts every pending http call via a new Angular's &lt;a href="https://github.com/angular/angular/blob/16.1.x/packages/common/http/src/interceptor.ts#L182-L184" rel="noopener noreferrer"&gt;internal http interceptor&lt;/a&gt; function. &lt;br&gt;
Now &lt;code&gt;ApplicationRef.isStable&lt;/code&gt; takes into account &lt;a href="https://github.com/angular/angular/blob/16.0.x/packages/core/src/application_ref.ts#L848-L850" rel="noopener noreferrer"&gt;not only the observable &lt;code&gt;NgZone.onStable&lt;/code&gt;, but also &lt;code&gt;InitialRenderPendingTasks.hasPendingTasks&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So the old behavior is preserved - SSR is waiting for outgoing HTTP requests to complete. But it's just achieved differently now, with the help of the new class &lt;code&gt;InitialRenderPendingTasks&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Side note: the new class &lt;a href="https://github.com/angular/angular/blob/16.0.x/packages/router/src/router.ts#L181" rel="noopener noreferrer"&gt;&lt;code&gt;InitialRenderPendingTasks&lt;/code&gt; is used also by Angular Router&lt;/a&gt; to &lt;a href="https://github.com/angular/angular/blob/16.0.x/packages/router/src/router.ts#L732-L737" rel="noopener noreferrer"&gt;ensure waiting for the initial navigation to complete&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  How can I track outgoing requests in SSR?
&lt;/h2&gt;

&lt;p&gt;You can write a custom Angular &lt;a href="https://angular.io/api/common/http/HttpInterceptor" rel="noopener noreferrer"&gt;&lt;code&gt;HTTP_INTERCEPTOR&lt;/code&gt;&lt;/a&gt;, which will track pending outgoing requests. The following is an example implementation of such a custom interceptor:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Injectable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/core&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;HttpInterceptor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpHandler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpEvent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;HttpResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@angular/common/http&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;tap&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;rxjs/operators&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;RequestDetails&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;requestTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;responseTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Date&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="nd"&gt;Injectable&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;DebuggingInterceptor&lt;/span&gt; &lt;span class="k"&gt;implements&lt;/span&gt; &lt;span class="nx"&gt;HttpInterceptor&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nx"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;RequestDetails&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;

  &lt;span class="nf"&gt;intercept&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpRequest&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpHandler&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nx"&gt;Observable&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;HttpEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;requests&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;requestTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="na"&gt;responseTime&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;next&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;request&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;pipe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="nf"&gt;tap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;event&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;HttpEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;HttpResponse&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;requestDetails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;requestDetails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;responseTime&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: the above implementation is just an example and can be enhanced by adding more request's details, for example the response HTTP status.&lt;br&gt;
Note 2: Such an interceptor can be also implemented when using Angular versions prior to 16. &lt;/p&gt;

&lt;h2&gt;
  
  
  ZoneJS still triggers change detection on HTTP request completion
&lt;/h2&gt;

&lt;p&gt;Even though HTTP requests are no longer wrapped as artifical macrotasks in Angular's internals, the change detection in Angular app still will be triggered after an outgoing request completes. It's possioble, because &lt;code&gt;Zone.js&lt;/code&gt; tracks also native event listeners (including native event listeners responsible for outgoing http request) and then triggers &lt;a href="https://github.com/angular/angular/blob/16.0.x/packages/core/src/zone/ng_zone.ts#L418" rel="noopener noreferrer"&gt;&lt;code&gt;NgZone.onLeave()&lt;/code&gt;&lt;/a&gt;, which triggers an internal function &lt;a href="https://github.com/angular/angular/blob/16.0.x/packages/core/src/zone/ng_zone.ts#L480" rel="noopener noreferrer"&gt;&lt;code&gt;checkStable()&lt;/code&gt;&lt;/a&gt;, which triggers emission of  &lt;a href="https://github.com/angular/angular/blob/16.0.x/packages/core/src/zone/ng_zone.ts#L345" rel="noopener noreferrer"&gt;&lt;code&gt;NgZone.onMicrotaskEmpty&lt;/code&gt;&lt;/a&gt; (btw. I wonder why it wasn't named &lt;code&gt;NgZone.onTaskEmpty&lt;/code&gt;, because it's not only about microtasks, but also event listeners), which triggers emission of  &lt;a href="https://github.com/angular/angular/blob/16.0.x/packages/core/src/application_ref.ts#L1231-L1234" rel="noopener noreferrer"&gt;&lt;code&gt;ApplicationRef.tick()&lt;/code&gt;&lt;/a&gt;, which performs the &lt;a href="https://github.com/angular/angular/blob/16.0.x/packages/core/src/application_ref.ts#L1052" rel="noopener noreferrer"&gt;change detection&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  If you really feel like buying me a coffee
&lt;/h2&gt;

&lt;p&gt;... then feel free to do it. Many thanks! 🙌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/krisplatis" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>angular</category>
      <category>ssr</category>
      <category>angularuniversal</category>
      <category>zonejs</category>
    </item>
    <item>
      <title>Self-Reg and Spotify: How I automated my music listening experience 🎵</title>
      <dc:creator>Krzysztof Platis</dc:creator>
      <pubDate>Mon, 17 Apr 2023 22:07:12 +0000</pubDate>
      <link>https://dev.to/krisplatis/self-reg-and-spotify-how-i-automated-my-music-listening-experience-ock</link>
      <guid>https://dev.to/krisplatis/self-reg-and-spotify-how-i-automated-my-music-listening-experience-ock</guid>
      <description>&lt;p&gt;&lt;strong&gt;Are you tired of spending too much time searching for the perfect Spotify playlist for your current mood? I have found a solution that has saved me time and frustration.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The struggle
&lt;/h2&gt;

&lt;p&gt;As someone who enjoys music, I have over 100 Spotify playlists in my favorites list. However, when it comes to choosing the right playlist for my current level of alertness, I often found myself struggling to find the perfect one. Sometimes the music was too soft, other times it was too loud. I needed a way to instantly search and find a playlist that would match my current level of alertness, so it would help me in my activity rather than irritate me.&lt;/p&gt;

&lt;h2&gt;
  
  
  The solution
&lt;/h2&gt;

&lt;p&gt;My solution was to create a database in Notion of all my playlists and classify them based on their level of alertness: &lt;strong&gt;low&lt;/strong&gt;, &lt;strong&gt;attentive&lt;/strong&gt;, &lt;strong&gt;reactive&lt;/strong&gt;, or &lt;strong&gt;active&lt;/strong&gt;. Whenever I wanted to listen to music, I would ask myself a quick question about my current level of alertness, and then I would open my database, filter by the chosen alertness type, and pick a random playlist.&lt;/p&gt;

&lt;p&gt;But why stop there? I wanted to make this process even more efficient. So, I created an iOS shortcut that would ask me to choose one of the four given alertness types. The shortcut would then connect in the background to my Notion database, get one random playlist from the chosen alertness type, and open Spotify to play it.&lt;/p&gt;

&lt;p&gt;Now, with just a few clicks, I can listen to the perfect Spotify playlist that matches my current level of alertness. No more wasting time searching for the right music, and no more frustration with mismatched playlists. This solution has made listening to music a more enjoyable and efficient experience. &lt;/p&gt;

&lt;p&gt;I'm aware my solution is very specific. But it's a nice example of optimizing your life. And I hope it will inspire you.&lt;/p&gt;

&lt;h2&gt;
  
  
  Levels of alertness by Dr. Stuart Shanker
&lt;/h2&gt;

&lt;p&gt;Dr. Stuart Shanker's book &lt;a href="https://www.goodreads.com/en/book/show/27774752" rel="noopener noreferrer"&gt;"Self-Reg"&lt;/a&gt; discusses the importance of recognizing and responding to different levels of alertness in order to effectively self-regulate and manage stress. Shanker emphasizes the significance of understanding our own levels of alertness and recognizing when we are becoming dysregulated. By doing so, we can take steps to restore balance and promote well-being.&lt;/p&gt;

&lt;p&gt;In Shanker's model, there are five levels of arousal or alertness, which include &lt;strong&gt;low&lt;/strong&gt; arousal, &lt;strong&gt;attentive&lt;/strong&gt; arousal, &lt;strong&gt;reactive&lt;/strong&gt; arousal, &lt;strong&gt;active&lt;/strong&gt; arousal, and &lt;strong&gt;hyper&lt;/strong&gt;-arousal. By classifying my playlists according to the first 4 levels, I am more aware of my current level of alertness and can quickly find the perfect playlist that matches my mood.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This process has been a game-changer in my daily routine, and I hope it inspires you to create your own system that matches your needs and preferences. Happy listening! 🎧&lt;/p&gt;

&lt;h2&gt;
  
  
  If you really feel like buying me a coffee
&lt;/h2&gt;

&lt;p&gt;... then feel free to do it. Many thanks! 🙌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/krisplatis" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fdefault-orange.png" alt="Buy Me A Coffee" width="434" height="100"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>automation</category>
      <category>music</category>
      <category>work</category>
      <category>wellbeing</category>
    </item>
    <item>
      <title>Auto-add missing imports on file save in VS Code ✨</title>
      <dc:creator>Krzysztof Platis</dc:creator>
      <pubDate>Fri, 17 Mar 2023 17:04:00 +0000</pubDate>
      <link>https://dev.to/krisplatis/auto-add-missing-imports-on-file-save-in-vs-code-1b89</link>
      <guid>https://dev.to/krisplatis/auto-add-missing-imports-on-file-save-in-vs-code-1b89</guid>
      <description>&lt;p&gt;&lt;strong&gt;Do you spend precious time manually organizing imports and fixing missing ones while coding in VS Code? There's a faster and more efficient way. By enabling a simple but powerful feature in the settings, you can automate these tasks upon file save and significantly boost your coding productivity. Let's explore how this feature works and how you can start using it today.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Auto-add missing imports on file save
&lt;/h2&gt;

&lt;p&gt;Using the Command Palette (&lt;code&gt;CMD + SHIFT + P&lt;/code&gt;), open the option &lt;code&gt;Preferences: Open User Settings (JSON)&lt;/code&gt;:&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%2Faw7n4khtb0s5qnkm32sy.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%2Faw7n4khtb0s5qnkm32sy.png" alt="Image description" width="800" height="94"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then add the following settings to your opened &lt;em&gt;User&lt;/em&gt; &lt;code&gt;settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nl"&gt;"editor.codeActionsOnSave"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source.organizeImports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"source.addMissingImports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: When there is more than one possible suggested import path for a token, &lt;a href="https://github.com/microsoft/vscode/issues/139131#issuecomment-995354561" rel="noopener noreferrer"&gt;such a missing import won’t be auto-added&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keyboard Shortcut to add missing imports
&lt;/h2&gt;

&lt;p&gt;However, you can configure a keyboard shortcut to auto-add missing imports (and it can handle a situation when many import paths are suggested; e.g. choose the first one by default). &lt;/p&gt;

&lt;p&gt;Using the Command Palette (&lt;code&gt;CMD + SHIFT + P&lt;/code&gt;), open the option &lt;code&gt;Preferences: Open Keyboard Shortcuts (JSON)&lt;/code&gt;:&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%2Fmstzkq3ukdbe7btzkbd8.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%2Fmstzkq3ukdbe7btzkbd8.png" alt="Image description" width="800" height="118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And add the following setting to your opened &lt;code&gt;keybindings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  {
    "key": "ctrl+s",
    "command": "editor.action.sourceAction",
    "args": {
      "kind": "source.addMissingImports",
      "apply": "first"
    }
  }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and then press &lt;code&gt;[CTRL + S]&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Save the file!
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Before 🙄
&lt;/h3&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%2F4qxq1ix5t2cdhs7nkfrb.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%2F4qxq1ix5t2cdhs7nkfrb.png" alt="Image description" width="529" height="253"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  After 🤩
&lt;/h3&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%2Felzb6d4ui4m20de8vslx.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%2Felzb6d4ui4m20de8vslx.png" alt="Image description" width="504" height="417"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Disclaimer
&lt;/h2&gt;

&lt;p&gt;Please expect that sometimes VS Code might suggest using a not your preferred path (e.g. not from the proper relative file or from a proper sub entry point &lt;code&gt;@package/xxx/yyy&lt;/code&gt;, but from an index.ts barrel or from absolute directory - which depending on your setup might cause compilation errors later on). So please be vigilant with VS Code resolving import paths for you. 😉&lt;/p&gt;

&lt;h2&gt;
  
  
  If you really feel like buying me a coffee
&lt;/h2&gt;

&lt;p&gt;... then feel free to do it. Many thanks! 🙌&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.buymeacoffee.com/krisplatis" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn.buymeacoffee.com%2Fbuttons%2Fv2%2Fdefault-yellow.png" alt="Buy Me A Coffee" width="545" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>vscode</category>
      <category>productivity</category>
      <category>javascript</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
