<?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: Simon Porter</title>
    <description>The latest articles on DEV Community by Simon Porter (@sporter).</description>
    <link>https://dev.to/sporter</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%2F163951%2F35e26d50-8242-41f7-816f-26d89882ac29.png</url>
      <title>DEV Community: Simon Porter</title>
      <link>https://dev.to/sporter</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sporter"/>
    <language>en</language>
    <item>
      <title>Adding Vercel analytics to your static Astro site</title>
      <dc:creator>Simon Porter</dc:creator>
      <pubDate>Mon, 08 Apr 2024 23:42:00 +0000</pubDate>
      <link>https://dev.to/sporter/adding-vercel-analytics-to-your-static-astro-site-1eob</link>
      <guid>https://dev.to/sporter/adding-vercel-analytics-to-your-static-astro-site-1eob</guid>
      <description>&lt;p&gt;Vercel analytics is a great way to track your Astro site usage if you're already using Vercel for hosting, and the hobby plan bundles it for free!&lt;/p&gt;

&lt;p&gt;There are &lt;a href="https://vercel.com/docs/analytics/limits-and-pricing"&gt;some limits for the hobby plans&lt;/a&gt;, but if you're just getting started with a project, it certainly beats involving something heavy like Google Analytics. Vercel's analytics script comes in at a tiny &lt;strong&gt;1.1kb&lt;/strong&gt; with no extra account setup. For that you get page views, unique visitors, and referrers.&lt;/p&gt;

&lt;p&gt;As you grow you may find your analytics needs increase, but for a simple site, this is a great way to get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;It's a one click process to enable it in your account. So let's head on over to our Vercel dashboard &amp;gt; select the project we want to enable analytics for &amp;gt; select the analytics tab and then hit the &lt;strong&gt;Enable&lt;/strong&gt; button to get started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhrr2ztjejqwospx190z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwhrr2ztjejqwospx190z.png" alt="A screenshot of the Vercel dashboard for our project showing the Enable analytics button script." width="800" height="177"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We then have a couple of different options to configure it for either &lt;strong&gt;server&lt;/strong&gt; or &lt;strong&gt;hybrid&lt;/strong&gt; output modes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Option A - Using Vercel's adaptor
&lt;/h3&gt;

&lt;p&gt;Vercel has written up the instructions for adding the analytics script to your Astro site when using their adaptor in their &lt;a href="https://vercel.com/docs/frameworks/astro#using-vercel%27s-features-with-astro"&gt;documentation&lt;/a&gt;. This is the easiest way to get started, as it fits right alongside your Astro config.&lt;/p&gt;

&lt;p&gt;First, use &lt;code&gt;astro&lt;/code&gt; to install the Vercel adaptor, or manually install it with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pnpm astro add vercel
&lt;span class="c"&gt;# or manually install&lt;/span&gt;
pnpm add @vercel/astro

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

&lt;/div&gt;



&lt;p&gt;Then specify the Vercel adaptor in your Astro config and enable the analytics feature:&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="c1"&gt;// for static/ssg output&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;vercel&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;@astrojs/vercel/static&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="c1"&gt;// for server/ssr output&lt;/span&gt;
&lt;span class="c1"&gt;// import vercel from '@astrojs/vercel/serverless';&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="nf"&gt;defineConfig&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;static&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;vercel&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;webAnalytics&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;enabled&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&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;After deploying this to change to production, we'll see the Vercel adaptor load our 1.1kb analytics script from the CDN &lt;code&gt;https://cdn.vercel-insights.com/v1/script.js&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Option B - Manual install
&lt;/h3&gt;

&lt;p&gt;This option is good for when we're running our Astro site in &lt;strong&gt;static&lt;/strong&gt; output mode &lt;sup id="fnref1"&gt;1&lt;/sup&gt; and don't want to involve the Vercel adaptor into our flow. &lt;strong&gt;static&lt;/strong&gt; is the default mode for Astro, and it's the most performant way to run your site as all our pages are pre-rendered at build time.&lt;/p&gt;

&lt;p&gt;To do this, we just need to add an additional script into our common &lt;strong&gt;Head&lt;/strong&gt; or common &lt;strong&gt;Layout&lt;/strong&gt;:&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;script&amp;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;inject&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;@vercel/analytics&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nf"&gt;inject&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After adding this, we should start to see the analytics data in our Vercel dashboard. Loading the site also shows us the request being made to the &lt;code&gt;https://${ourDomain}/_vercel/insights/script.js&lt;/code&gt; endpoint to load the tiny 1.1kb script.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmi6mui7ebyykuttncd6k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmi6mui7ebyykuttncd6k.png" alt="A screenshot of the developer tools network tab with the Vercel Analytics script MiddlewareCantBeLoaded." width="800" height="194"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And with that we're done!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ &lt;strong&gt;note&lt;/strong&gt;&lt;br&gt;
If a user of your site has a decent Adblocker, or is using a privacy focused browser, they may not be tracked by the Vercel analytics script.&lt;/p&gt;

&lt;p&gt;In my testing Brave seemed to still block the custom domain hosted &lt;code&gt;script.js&lt;/code&gt; file too.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Thanks for reading! 💜 This article was originally published on &lt;a href="https://simonporter.co.uk/posts/adding-vercel-analytics-to-your-static-astro-site"&gt;simonporter.co.uk&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;SSG is static site generation. It's a way to pre-render your site at build time, and serve the static files to users. This is in contrast to SSR or 'server' mode (server-side rendering) where the server generates the HTML on each request. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>astro</category>
      <category>vercel</category>
      <category>analytics</category>
      <category>ssg</category>
    </item>
    <item>
      <title>Pre-Push Time Saver</title>
      <dc:creator>Simon Porter</dc:creator>
      <pubDate>Thu, 25 May 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/sporter/pre-push-time-saver-m8h</link>
      <guid>https://dev.to/sporter/pre-push-time-saver-m8h</guid>
      <description>&lt;p&gt;Git has &lt;a href="https://git-scm.com/docs/githooks"&gt;a range of hooks&lt;/a&gt; that you can use to protect yourself against mistakes, or ensure code standards are kept across your team. I recently had a need to add a &lt;code&gt;pre-push&lt;/code&gt; hook to save myself some time when pushing up new PR's.&lt;/p&gt;

&lt;p&gt;Our test suite can take quite a while to run, so I'll typically push up, and then move onto other things to come back in a little bit after CI has finished in case tweaks are needed that I missed or didn't run into locally.&lt;/p&gt;

&lt;p&gt;Occasionally, I'll be working on a part of the code that looks okay in VSCode, but then fails our typechecking or lint checks because a part of my change broke a file I didn't have open. This pre-push hook makes sure I don't forget to run typechecking before I push up any changes, and will block the push if it fails. Meaning I get a much quicker feedback loop locally rather than needing to wait for CI.&lt;/p&gt;

&lt;p&gt;While this does slow down my initial pushes, it's saved me more times than it probably should have and let me fix things up before the CI gets a chance to run.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to install
&lt;/h3&gt;

&lt;p&gt;To get this running in a project, we can create a file in &lt;code&gt;.git/hooks/pre-push&lt;/code&gt; and make it executable with &lt;code&gt;chmod +x .git/hooks/pre-push&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/zsh&lt;/span&gt;

&lt;span class="nv"&gt;cmd&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"yarn run typecheck"&lt;/span&gt; &lt;span class="c"&gt;# replace with your typechecking/linting command&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"running typecheck before push..."&lt;/span&gt;
&lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="nv"&gt;$cmd&lt;/span&gt;
&lt;span class="nv"&gt;result&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$?&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;eval&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$cmd&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Failed typecheck! Fix before pushing or force push: &lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt;git push --no-verify&lt;/span&gt;&lt;span class="se"&gt;\`&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2
&lt;span class="nb"&gt;exit &lt;/span&gt;1
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  VSCode integration
&lt;/h3&gt;

&lt;p&gt;To &lt;a href="https://github.com/microsoft/vscode/issues/132778#issuecomment-1047763835"&gt;get this working in VSCode&lt;/a&gt;, we also need to add the &lt;code&gt;push&lt;/code&gt; command to the &lt;code&gt;git.commandsToLog&lt;/code&gt; setting inside our VSCode preferences. This allows us to view the error log on failure from within VSCode too.&lt;/p&gt;

&lt;p&gt;With these two things in place, we're off to the races!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;ℹ️ &lt;strong&gt;note&lt;/strong&gt;&lt;br&gt;
In case you ever need to "just get it pushed", you can force push&lt;br&gt;
    your branch by using the &lt;a href="https://git-scm.com/docs/git-push#Documentation/git-push.txt---no-verify"&gt;--no-verify&lt;/a&gt; flag: &lt;code&gt;git push --no-verify&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;This article was originally published on &lt;a href="https://www.simonporter.co.uk/posts/pre-push-time-saver"&gt;simonporter.co.uk&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

</description>
      <category>dx</category>
      <category>git</category>
    </item>
    <item>
      <title>Weekend Reading</title>
      <dc:creator>Simon Porter</dc:creator>
      <pubDate>Sat, 15 Apr 2023 22:30:00 +0000</pubDate>
      <link>https://dev.to/sporter/weekend-reading-3dk0</link>
      <guid>https://dev.to/sporter/weekend-reading-3dk0</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mzs5rplvt0vutslkuz.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mzs5rplvt0vutslkuz.jpeg" alt="Women sits at a cafe reading" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  hello folks!
&lt;/h2&gt;

&lt;p&gt;A fairly quiet week this week in the land of React. Lots of folks seem to be gearing up for conferences and presentations, and the Easter holidays continued. So perhaps people were enjoying some time unplugged.&lt;/p&gt;

&lt;p&gt;Elsewhere the *ust foundation tried to implode on itself and we had a new Chrome release, so let's jump in.&lt;/p&gt;




&lt;p&gt;Anthony found a neat little trick I'd not seen before in GitHub, the ability to generate tables from slash commands! Neat.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1644719245690048513-711" src="https://platform.twitter.com/embed/Tweet.html?id=1644719245690048513"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1644719245690048513-711');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1644719245690048513&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Devon shows off some of the new React Aria design system we mentioned last week. I want to give this a try, as it does look super neat.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1645465276874407938-23" src="https://platform.twitter.com/embed/Tweet.html?id=1645465276874407938"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1645465276874407938-23');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1645465276874407938&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;This is a nice little idea to help onboard new developers to your team if using VSCode. A file that recommends extension installation when opening the project.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1645459301249458177-842" src="https://platform.twitter.com/embed/Tweet.html?id=1645459301249458177"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1645459301249458177-842');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1645459301249458177&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Delba gives a real tidy overview of the new file based metadata API that Vercel released last week. Still wanting to give the new API a try!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1645840553597362176-4" src="https://platform.twitter.com/embed/Tweet.html?id=1645840553597362176"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1645840553597362176-4');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1645840553597362176&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Dominik (of React Query) was on This Dot Media this week discussing &lt;a href="https://www.youtube.com/watch?v=iUrGK4Hxrz8"&gt;what it's like to maintain a successful open source project&lt;/a&gt;. This one's currently on my "to-watch" list.&lt;/p&gt;

&lt;p&gt;Freecodecamp had an article about &lt;a href="https://twitter.com/freeCodeCamp/status/1645759134548078593?s=20"&gt;Git branching commands&lt;/a&gt;. I still struggle with my Git-fu, and prefer to rely on VSCode, but still need to reach for the CLI on occasion. Which inevitably involves a Google 😅 Hopefully more articles like this can cement some knowledge.&lt;/p&gt;

&lt;p&gt;GitHub announced it's &lt;a href="https://github.blog/2023-04-12-github-accelerator-our-first-cohort-and-whats-next/"&gt;first 20 contributors&lt;/a&gt; to receive it's $20K grant to attempt to create sustainable open source. Some recognizable names in the list, most notably TRPC of course!&lt;/p&gt;

&lt;p&gt;Trash has been tweeting quite a few TS tips recently. Completing Matt's Total TypeScript course seems to have rekindled some TS ❤️ Love this TS magic.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1646294594135691268-565" src="https://platform.twitter.com/embed/Tweet.html?id=1646294594135691268"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1646294594135691268-565');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1646294594135691268&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Speaking of, Matt has released his new TS helper library, shoehorn. To help with types during testing when you aren't working with a complete data set&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1646409044620460033-70" src="https://platform.twitter.com/embed/Tweet.html?id=1646409044620460033"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1646409044620460033-70');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1646409044620460033&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Josh has been testing out a new way of working that I'd not heard of before. It rings true from the occasions this has happened to me, but I hadn't thought of doing it intentionally. Sounds interesting!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1646658776890580994-99" src="https://platform.twitter.com/embed/Tweet.html?id=1646658776890580994"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1646658776890580994-99');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1646658776890580994&amp;amp;theme=dark"
  }



&lt;/p&gt;




&lt;h2&gt;
  
  
  This Week In React
&lt;/h2&gt;

&lt;p&gt;Congrats Seb on 20K subscribers! 😱 My top picks for &lt;a href="https://thisweekinreact.com/"&gt;TWIR&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Interesting RFC from Vercel on &lt;a href="https://github.com/vercel/next.js/discussions/48256"&gt;integrating third-party scripts&lt;/a&gt; using next/third-parties (and next/script)&lt;/p&gt;

&lt;p&gt;With create-react-app officially dead (according to the new React docs) it's interesting to see the &lt;a href="https://www.netlify.com/blog/framework-popularity-on-netlify/"&gt;framework popularity on netlify&lt;/a&gt; and how this will change this year.&lt;/p&gt;

&lt;p&gt;Nice reminder from ClarityDev on the &lt;a href="https://claritydev.net/blog/the-most-common-mistakes-when-using-react"&gt;most common mistakes when using react&lt;/a&gt;. A lot here I try and keep in the forefront, but sometimes forget in the moment. A useful list to print out!&lt;/p&gt;




&lt;h2&gt;
  
  
  CSS Weekly
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://ishadeed.com/article/css-text-wrap-balance/"&gt;A nice rundown&lt;/a&gt; of the experimental support for &lt;code&gt;text-wrap: balance&lt;/code&gt; by Ahmed&lt;/p&gt;

&lt;p&gt;Ryan shows off &lt;a href="https://ryanmulligan.dev/blog/sticky-header-scroll-shadow"&gt;intersection observers with sticky headers&lt;/a&gt;. Pretty neat!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://atlasicons.vectopus.com/"&gt;Atlas Icons&lt;/a&gt; has 2.7K free icons for use, including a Figma library, very cool.&lt;/p&gt;

&lt;p&gt;Until next time. Thanks for reading!&lt;/p&gt;

</description>
      <category>news</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Weekend Reading</title>
      <dc:creator>Simon Porter</dc:creator>
      <pubDate>Sat, 08 Apr 2023 09:00:00 +0000</pubDate>
      <link>https://dev.to/sporter/weekend-reading-3enn</link>
      <guid>https://dev.to/sporter/weekend-reading-3enn</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mzs5rplvt0vutslkuz.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mzs5rplvt0vutslkuz.jpeg" alt="Women sits at a cafe reading" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello folks!
&lt;/h2&gt;

&lt;p&gt;Happy Easter weekend for those celebrating! Whether it's family time, work, or stuffing your face full with your own body weight in chocolate - let's take a moment to look back over the past week.&lt;/p&gt;

&lt;p&gt;Lot going on in the Twitter-verse as usual, quite a bit of Vercel/Next.JS news, and more fun and games with server components.&lt;/p&gt;

&lt;p&gt;Let's jump in shall we?&lt;/p&gt;




&lt;p&gt;Ben was at it again with server components. He's now updated his simple-rsc repo (co-authored with Dan himself) to have a fresh README and annotated all source code to help explain what's happening. Super useful if you wanted to get an idea of what's going on under the hood.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1642629178871742471-588" src="https://platform.twitter.com/embed/Tweet.html?id=1642629178871742471"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1642629178871742471-588');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1642629178871742471&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;There was a very cool tip from Meng on using Midjourney for web vector graphics. I love this idea, as it's often the problem that as a frontend developer you'll have a great idea, but it needs some illustrations or vectors to really come to life. I have a hard enough time keeping up with and constantly learning JS without adding graphic design to my plate 😅 this is a super nice shortcut!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1642619090337427460-877" src="https://platform.twitter.com/embed/Tweet.html?id=1642619090337427460"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1642619090337427460-877');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1642619090337427460&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Bun is going to have RSC support in v0.6.0&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1642821108402630657-601" src="https://platform.twitter.com/embed/Tweet.html?id=1642821108402630657"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1642821108402630657-601');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1642821108402630657&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;JP Camara blogs about their experience &lt;a href="https://jpcamara.com/2023/03/07/making-tanstack-table.html"&gt;hunting down a performance bottleneck&lt;/a&gt; when using Tanstack Table, and ultimately, the 1000x speed improvements they gained with a one line change. Really love the way they set out the article and followed the train of thought. Great little read and a stellar result.&lt;/p&gt;

&lt;p&gt;Some nice Array functions are in Stage 4,a nd already shipped with Chrome 110.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1643428683909066753-621" src="https://platform.twitter.com/embed/Tweet.html?id=1643428683909066753"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1643428683909066753-621');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1643428683909066753&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Simon reminds us he has some free Tailwind content just by signing up to his mailing list. If you're interested in dipping your toes into Tailwind, this could be worth a quick punt.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1643390840298156032-238" src="https://platform.twitter.com/embed/Tweet.html?id=1643390840298156032"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1643390840298156032-238');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1643390840298156032&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Lee released a new video detailing &lt;a href="https://www.youtube.com/watch?v=gSSsZReIFRk"&gt;the new Next.JS App router&lt;/a&gt; (what I'm using with this blog!) which gives a nice look over the features in a quick 15 minute review.&lt;/p&gt;

&lt;p&gt;Ben isn't the only one jumping into RSC's, vite had an update about their vite-rsc experiment which now supports mutations, very cool stuff.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1643626567405322244-258" src="https://platform.twitter.com/embed/Tweet.html?id=1643626567405322244"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1643626567405322244-258');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1643626567405322244&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;CSS Selector nesting got added to Chrome Beta this week! Slowly but surely moving it's way to the prime time.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1643607943386914816-149" src="https://platform.twitter.com/embed/Tweet.html?id=1643607943386914816"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1643607943386914816-149');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1643607943386914816&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;The Adobe React Spectrum team dropped a brand new design system, React Aria Components. Unstyled, and built on top of React Aria hooks, this looks like a neat design system if you like the composable and customizable kind (rather than off the shelf such as Mantine or MUI).&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1643988004577619971-997" src="https://platform.twitter.com/embed/Tweet.html?id=1643988004577619971"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1643988004577619971-997');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1643988004577619971&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Zod, more Zod. I can't get enough of Zod at the moment as I'm working on adding it to more of our production code at work at the moment. Such a neat library, and Vercel just added it into Next for router type safety. Amazing.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1644112096475619328-947" src="https://platform.twitter.com/embed/Tweet.html?id=1644112096475619328"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1644112096475619328-947');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1644112096475619328&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Speaking of Next.JS, &lt;a href="https://nextjs.org/blog/next-13-3"&gt;version 13.3 was released this week&lt;/a&gt; with a few new cool features. I can't wait to try out the File Based Metadata API and Dynamic OG Images. Lot of buzz on Twitter for the Parallel Routes and Interception too.&lt;/p&gt;




&lt;h2&gt;
  
  
  This Week In React
&lt;/h2&gt;

&lt;p&gt;My top picks for &lt;a href="https://thisweekinreact.com/"&gt;TWIR&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=qZzmUVspiEo"&gt;Theo's recap about the Twitter spaces&lt;/a&gt; with Dan, Ryan, and a bunch of other clever people, is a great watch. I 💯 agree with the take on Vercel/Next.JS and the hype and excitement that it brings. I also agree with the 'use client' name, but not so much 'use interactive' either 😅 but, luckily, this is just naming semantics. I think something as simple as 'use browser' could be equally as descriptive. It's not that it runs in server or client, but it's targeting the browser, Theo's 'interactivity'.&lt;/p&gt;

&lt;p&gt;I still haven't solidified my mental model on refs. They feel like the dark arts, and I'm sure I'm missing a lot of useful use cases. &lt;a href="https://www.developerway.com/posts/refs-from-dom-to-api"&gt;This article from Nadia&lt;/a&gt; was a good read, that I'm sure I'll need to refer back to again!&lt;/p&gt;

&lt;p&gt;Jim writes about &lt;a href="https://blog.jim-nielsen.com/2023/types-in-jsdoc-with-zod/"&gt;types in JS files by using JSDoc&lt;/a&gt; instead of TypeScript. While I think even for personal, quick projects, I'd much prefer to use TS, it's always interesting to see other ways of doing things. And while the JSDocs don't float my boat right now, who knows if it could be a good solution for a particular case in the future. (and hey, more zod!)&lt;/p&gt;




&lt;p&gt;CSS Weekly is back but we're out of time for this week. See you on the other side!&lt;/p&gt;

</description>
      <category>news</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Weekend Reading</title>
      <dc:creator>Simon Porter</dc:creator>
      <pubDate>Sat, 01 Apr 2023 09:18:00 +0000</pubDate>
      <link>https://dev.to/sporter/weekend-reading-4g1</link>
      <guid>https://dev.to/sporter/weekend-reading-4g1</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mzs5rplvt0vutslkuz.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mzs5rplvt0vutslkuz.jpeg" alt="Women sits at a cafe reading" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello folks!
&lt;/h2&gt;

&lt;p&gt;Back again with another instalment. Where &lt;em&gt;did&lt;/em&gt; that week go? I hope your week was filled with merges and closed Jira's.&lt;/p&gt;

&lt;p&gt;We had quite a few releases this week, from Vanilla Extract to VSCode. Developers keep churning out the next GPT app, so plenty more of them too. And Twitter didn't disappoint for another week with some long but interesting threads.&lt;/p&gt;

&lt;p&gt;Oh, and of course, the small matter of releasing the Twitter algorithm to the public where &lt;a href="https://twitter.com/tannerlinsley/status/1641888080620814338?s=20"&gt;all hell broke loose&lt;/a&gt;, as probably expected.&lt;/p&gt;

&lt;p&gt;Let's jump in shall we?&lt;/p&gt;




&lt;p&gt;VSCode &lt;a href="https://code.visualstudio.com/updates/v1_77"&gt;released their March update&lt;/a&gt; this week, nothing overly exciting, but the TS/JS switch case completions is nice.&lt;/p&gt;

&lt;p&gt;Vanilla Extract added cascade layer support. I still haven't played with this style of CSS yet, but it looks interesting!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1640576883573276672-954" src="https://platform.twitter.com/embed/Tweet.html?id=1640576883573276672"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1640576883573276672-954');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1640576883573276672&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Tyler, of ui dot dev, announced a new React course is on the way. Neat looking intro page, might be worth a watch as it sounds exciting.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1640820940018728960-987" src="https://platform.twitter.com/embed/Tweet.html?id=1640820940018728960"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1640820940018728960-987');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1640820940018728960&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Theo laments the database performance of Prisma in &lt;a href="https://youtu.be/3P7jnolWfHw"&gt;his latest video&lt;/a&gt;. It feels like the migration has begun to &lt;a href="https://twitter.com/DrizzleOrm"&gt;DrizzleORM&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Josh shares some more coolness with the &lt;code&gt;:has()&lt;/code&gt; selector. There's so much neat stuff this can do, I only wish it had more support so I could dig into it at work.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1640699471905390594-443" src="https://platform.twitter.com/embed/Tweet.html?id=1640699471905390594"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1640699471905390594-443');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1640699471905390594&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Dan reminds us they're still working on the React Forget compiler, the promise-land of not needing fiddly useEffects and array dependencies.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1640842748243714050-512" src="https://platform.twitter.com/embed/Tweet.html?id=1640842748243714050"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1640842748243714050-512');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1640842748243714050&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;If you've been playing with next 13 as I have, you might have ran into a few problems here and there. Lee posted a thread with the most common questions/gotchas and what's coming next!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1641109623154388992-965" src="https://platform.twitter.com/embed/Tweet.html?id=1641109623154388992"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1641109623154388992-965');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1641109623154388992&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;A new week, a new GPT app. &lt;a href="https://domainsg.pt"&gt;DomainsGPT&lt;/a&gt; got a fair amount of eyes this week it seemed 👀&lt;/p&gt;

&lt;p&gt;Wes was asking whether people prefer enums over &lt;code&gt;as const&lt;/code&gt;. Surprisingly well split actually given a lot of Twitter TS stars seem to be in the avoid camp.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1641481020720525317-570" src="https://platform.twitter.com/embed/Tweet.html?id=1641481020720525317"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1641481020720525317-570');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1641481020720525317&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I haven't had time to watch it this week but &lt;a href="https://www.youtube.com/watch?v=Fctw7WjmxpU"&gt;Ben recorded a stream session with Dan&lt;/a&gt; where they built out RSC's in a micro framework and go in depth on the inner workings. Sounded super cool, can't wait to watch. 4 hours though! 😅&lt;/p&gt;




&lt;p&gt;Seb's having a week off from This Week In React this week, so that's all we've got! Until next time.&lt;/p&gt;

</description>
      <category>news</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Weekend Reading</title>
      <dc:creator>Simon Porter</dc:creator>
      <pubDate>Sat, 25 Mar 2023 21:00:00 +0000</pubDate>
      <link>https://dev.to/sporter/weekend-reading-2269</link>
      <guid>https://dev.to/sporter/weekend-reading-2269</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mzs5rplvt0vutslkuz.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mzs5rplvt0vutslkuz.jpeg" alt="Image description" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello folks!
&lt;/h2&gt;

&lt;p&gt;Another week come and gone, and the tech world is still abuzz with GPT-4. Though it does seem to have calmed down a bit doesn't it? 😅&lt;/p&gt;

&lt;p&gt;In other news, bit of a hiccup for GitHub this week as they had to roll their SSH private key after &lt;a href="https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/"&gt;accidentally exposing it in a public repo&lt;/a&gt;, yowch. Twitch layoffs continued in a horrendous fashion.&lt;/p&gt;

&lt;p&gt;Still, plenty of React and JS news to keep us sidetracked. Grab your drink, pull up a chair, lets have us some weekend reading!&lt;/p&gt;




&lt;p&gt;Gajus points out a quick tip to make our DX easier with TypeScript. I can't believe how many times I've been sent to the type definition files rather than the proper code, when it's such an easy fix!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1636641120477384705-736" src="https://platform.twitter.com/embed/Tweet.html?id=1636641120477384705"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1636641120477384705-736');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1636641120477384705&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Seb posed a question on variable naming and whether you should avoid one letter names. 219 replies, and 210k views. We apparently care a lot about our variable names! So why is it so hard? 😅&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1638146370191208449-918" src="https://platform.twitter.com/embed/Tweet.html?id=1638146370191208449"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1638146370191208449-918');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1638146370191208449&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Dominik notes that React Query v5 is just around the corner! There's some neat stuff in this release but I also love the object properties by default, and switching back isLoading/isInitialLoading.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1637763194021093379-37" src="https://platform.twitter.com/embed/Tweet.html?id=1637763194021093379"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1637763194021093379-37');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1637763194021093379&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Daishi has published a learning "course" for Zustand v4. As he notes, it's such a small library that he's released it fairly cheap.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1638177097528246274-832" src="https://platform.twitter.com/embed/Tweet.html?id=1638177097528246274"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1638177097528246274-832');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1638177097528246274&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Tim, the lead from Vercel, announces that &lt;code&gt;create-next-app&lt;/code&gt; will now ask if you want to get started with Tailwind CSS instead of CSS modules. This got mixed reactions on Twitter, as it alwasy does when someone mentions Tailwind, but this seems like a nice DX improvement to me. You still don't &lt;em&gt;have&lt;/em&gt; to use it if you hate it that much.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1636654046474805249-217" src="https://platform.twitter.com/embed/Tweet.html?id=1636654046474805249"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1636654046474805249-217');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1636654046474805249&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Dan is &lt;a href="https://twitter.com/dan_abramov/status/1638334250440089601?s=20"&gt;still being given grief&lt;/a&gt; about RSC's from a lot of folks on Twitter. It's a difficult spot to be in, because it's brand new and they want to gauge how best to implement it, and not all the pieces are in place yet. I love this summary from Dan Jutan of Astro and Solid.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1639283519863005187-6" src="https://platform.twitter.com/embed/Tweet.html?id=1639283519863005187"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1639283519863005187-6');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1639283519863005187&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=jF0yA-JLQW0"&gt;PlayWright released 1.32&lt;/a&gt; this week, which brought with it UI mode and time travelling debug, akin to Cypress. Earlier they made React Testing Library a first class citizen, and this could now mean it's well worth a look if you weren't enjoying Cypress, or wanted to try it on a new project.&lt;/p&gt;




&lt;h2&gt;
  
  
  This Week In React
&lt;/h2&gt;

&lt;p&gt;My top picks for &lt;a href="https://thisweekinreact.com/"&gt;TWIR&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Pretty neat &lt;a href="https://julesblom.com/writing/map-of-react-api"&gt;mapping of all the available React APIs&lt;/a&gt; with some background reading behind them. Interesting way to document this information, hope to see more of it!&lt;/p&gt;

&lt;p&gt;Brad writes about a list of &lt;a href="https://reacttraining.com/blog/hooks-you-probably-dont-need"&gt;React's more eccentric hooks&lt;/a&gt;, with a few common ones that shouldn't be used all that much thrown in too. No surprises &lt;code&gt;useEffect&lt;/code&gt; makes the list, which I feel gets overused as an easy escape hatch quite a lot.&lt;/p&gt;

&lt;p&gt;Both &lt;a href="https://github.com/vitejs/vite/blob/main/packages/vite/CHANGELOG.md#420-2023-03-16"&gt;Vite&lt;/a&gt; and &lt;a href="https://github.com/prettier/prettier/releases/tag/2.8.5"&gt;Prettier&lt;/a&gt; had some new releases this week. I don't think there's anything earth shattering here but it's nice to see some TS 5.0 support in Prettier already.&lt;/p&gt;

&lt;p&gt;There's an interesting read about &lt;a href="https://www.builder.io/blog/signals-vs-observables"&gt;signals vs observables &lt;/a&gt; on the builder.io blog this week, which is fairly topical given I've been diving into React Query lately. Didn't pay &lt;em&gt;too&lt;/em&gt; much attention to the signals hype as I had too much on, but this is a nice rundown for anyon who missed it.&lt;/p&gt;

&lt;p&gt;Josh wrote about his feelings on AI and &lt;a href="https://www.joshwcomeau.com/blog/the-end-of-frontend-development/"&gt;the future of development&lt;/a&gt;. Definitely match his sentiment that AI isn't going to be getting people fired anytime soon, but it can be a huge help if used properly.&lt;/p&gt;

&lt;p&gt;See you next week!&lt;/p&gt;

</description>
      <category>news</category>
      <category>javascript</category>
      <category>react</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Slicing Data with Tanstack Query</title>
      <dc:creator>Simon Porter</dc:creator>
      <pubDate>Sat, 25 Mar 2023 14:00:00 +0000</pubDate>
      <link>https://dev.to/sporter/slicing-data-with-tanstack-query-48kj</link>
      <guid>https://dev.to/sporter/slicing-data-with-tanstack-query-48kj</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9rps7lero7vdavfjp7q.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo9rps7lero7vdavfjp7q.jpeg" alt="Image description" width="800" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've been working with &lt;a href="https://tanstack.com"&gt;Tanstack Query&lt;/a&gt; for a while now and I'm a big, big, fan. I love how it works within my apps, nestled amongst my standard React code without needing a tonne of boilerplate, and how it takes care of the hard bits of caching for me.&lt;/p&gt;

&lt;p&gt;Nobody wants to roll their own solutions to these hard problems&lt;sup id="fnref1"&gt;1&lt;/sup&gt;, and Tanstack Query "&lt;em&gt;just works&lt;/em&gt;" for the projects I've used it on.&lt;/p&gt;

&lt;p&gt;Big props to &lt;a href="https://twitter.com/TkDodo"&gt;TkDodo&lt;/a&gt; for his continued support!&lt;/p&gt;

&lt;h2&gt;
  
  
  Slicing Data
&lt;/h2&gt;

&lt;p&gt;Lately, I've been looking at slicing data with the &lt;code&gt;select&lt;/code&gt; feature. TkDodo explains this on his blog: &lt;a href="https://tkdodo.eu/blog/react-query-data-transformations"&gt;React Query Data Transformations&lt;/a&gt; but I thought I'd write up my learnings&lt;sup id="fnref2"&gt;2&lt;/sup&gt; and talk about how to use them with TypeScript.&lt;/p&gt;

&lt;p&gt;The select feature behaves like a redux selector. That is, it lets you take a larger piece of state, and slice it to extract just the parts you're interested in.&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Example
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://codesandbox.io/s/quizzical-herschel-95rryw"&gt;View the sample on Codesandbox!&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The above example uses the &lt;code&gt;useGetUser()&lt;/code&gt; custom hook which calls &lt;code&gt;useQuery&lt;/code&gt; to request &lt;code&gt;User&lt;/code&gt; data from our backend.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    export function useGetUser&amp;lt;T = User&amp;gt;({
        userId,
        options
    }: {
        userId: number;
        options?: {
            select?: (user: User) =&amp;gt; T;
        };
    }) {
    return useQuery({
        queryKey: ["user", { userId }],
        queryFn: async () =&amp;gt; {
            return dataOne as User;
        },
        ...options
    });
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've then created a custom &lt;code&gt;useGetGender()&lt;/code&gt; hook which uses &lt;strong&gt;select&lt;/strong&gt; to slice off just the &lt;code&gt;gender&lt;/code&gt; value from this data.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    const selectGender = (user: User) =&amp;gt; user?.gender;

    export function useGetGender({ userId }: { userId: number }) {
        return useGetUser({
            userId,
            options: {
                select: selectGender,
            },
        })
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is really powerful!&lt;/p&gt;

&lt;p&gt;You can re-use the same state and slice off the bits you want without needing to make extra requests to other endpoints for the exact same data. Preventing more request waterfalls&lt;sup id="fnref3"&gt;3&lt;/sup&gt; and potentially reducing rerenders&lt;sup id="fnref4"&gt;4&lt;/sup&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  TypeScript Settings
&lt;/h2&gt;

&lt;p&gt;You may have been expecting some &lt;em&gt;Generic Gymnastics&lt;/em&gt; in the code above, in order to type the return values and support all options with &lt;code&gt;UseQueryOptions&amp;lt;&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;For the most part, the recommendation is to let TypeScript do it's thing and infer the values for you. I know, cheating right?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    return useQuery({
        queryKey: ["user", { userId }],
        queryFn: async () =&amp;gt; {
            return dataOne as User;
        },
        ...options
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is lying to TS to tell it we're returning a &lt;code&gt;User&lt;/code&gt;, but unless you plan on adding &lt;a href="https://tkdodo.eu/blog/type-safe-react-query#zod"&gt;Zod&lt;/a&gt;, this is about the best you can do.&lt;/p&gt;

&lt;p&gt;This then lets TS infer the return of our own custom hook, because &lt;code&gt;useQuery&lt;/code&gt; infers what data it will return from the &lt;strong&gt;queryFn&lt;/strong&gt; and so our custom hook infers the same return type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftl7s3pmubth59hdiqci1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftl7s3pmubth59hdiqci1.png" alt="Image description" width="800" height="382"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This makes sense, but what about the &lt;strong&gt;select&lt;/strong&gt; ReturnType? That doesn't return the same data, and we could have multiple select's returning different data couldn't we?&lt;/p&gt;

&lt;p&gt;We could always return what we need for this particular select, but that won't work for others with other data types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    export function useGetUser({
        userId,
        options
    }: {
        userId: number;
        options?: {
            select?: (user: User) =&amp;gt; string // Help??;
        };
    }) {
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rather than start making unions for each data type you want returned, the solution is to use a generic on the custom hook to adjust the Return Type with a default.&lt;/p&gt;

&lt;p&gt;This way if we use a &lt;strong&gt;select&lt;/strong&gt; function in another custom hook, the &lt;em&gt;return type of the select&lt;/em&gt; is passed through.&lt;/p&gt;

&lt;p&gt;Otherwise, if no select is used, it defaults to the data we expect (the &lt;code&gt;User&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnyxamipshyv6g9ohzqdr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnyxamipshyv6g9ohzqdr.png" alt="Image description" width="800" height="410"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Considerations
&lt;/h2&gt;

&lt;p&gt;This isn't the only way to set these up though. You could go full hog and provide all the Generics, all the time, and type all the options (with &lt;code&gt;UseQueryOptions&amp;lt;&amp;gt;&lt;/code&gt;) but... &lt;a href="https://tkdodo.eu/blog/react-query-and-type-script#infer-all-the-things"&gt;it's not recommended&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;TkDodo has said that new Generics will be introduced in v5, and if you are currently only provide the existing ones, this may break on upgrade.&lt;/p&gt;

&lt;p&gt;I'm happy with the trade offs from the above setup though, most inferrance with least duplication.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;"&lt;em&gt;There are only two hard things in Computer Science: cache invalidation and naming things.&lt;/em&gt;" - &lt;a href="https://martinfowler.com/bliki/TwoHardThings.html"&gt;Phil Karlton&lt;/a&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;In my &lt;a href="https://dev.to/posts/yet-another-developer-blog"&gt;initial blog post&lt;/a&gt;, I write about why I wanted to write about my learnings. To cement my knowedge mostly, and if it's beneifical to others, that's a plus too! ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Take a look at &lt;a href="https://gtmetrix.com/blog/how-to-read-a-waterfall-chart-for-beginners/"&gt;the GTMetrix blog&lt;/a&gt; for an explanation of request waterfalls. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn4"&gt;
&lt;p&gt;It's actually a little more involved than that, while it can help, you should be aware of &lt;a href="https://tkdodo.eu/blog/react-query-render-optimizations"&gt;render optimizations in React Query&lt;/a&gt; first. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>react</category>
      <category>javascript</category>
      <category>typescript</category>
      <category>reactquery</category>
    </item>
    <item>
      <title>Weekend Reading</title>
      <dc:creator>Simon Porter</dc:creator>
      <pubDate>Sat, 18 Mar 2023 21:35:00 +0000</pubDate>
      <link>https://dev.to/sporter/weekend-reading-16i7</link>
      <guid>https://dev.to/sporter/weekend-reading-16i7</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mzs5rplvt0vutslkuz.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mzs5rplvt0vutslkuz.jpeg" alt="Image description" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello folks!
&lt;/h2&gt;

&lt;p&gt;It was a different acronym that took over this week, it seems that there was nothing but GPT-4.&lt;/p&gt;

&lt;p&gt;"&lt;em&gt;GPT-4 has changed our lives!&lt;/em&gt;", "&lt;em&gt;GPT-4 is blowing my mind!&lt;/em&gt;", whilst others preferred to focus else where 😅&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1636355189652291585-125" src="https://platform.twitter.com/embed/Tweet.html?id=1636355189652291585"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1636355189652291585-125');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1636355189652291585&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Still, there was still some good stuff to be catching up on with React and TypeScript, so get your coffee, put your feet up, and let's catch up with some weekend reads.&lt;/p&gt;




&lt;p&gt;Adam was looking to &lt;a href="https://twitter.com/adamwathan/status/1635310388001775616"&gt;gauge iterest in adding ESM/TS support&lt;/a&gt; for TailWind config, which after a 65% poll in favour, ended up being implemented on his birthday! Happy birthday Adam 🎂 but this is pretty neat.&lt;/p&gt;

&lt;p&gt;It was always possible to import the TailWind Types via comment for VS Code intellisense&lt;sup id="fnref1"&gt;1&lt;/sup&gt;, but this makes it a firm feature which is a move in the right direction for sure. Hopefully more libraries follow suit.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1636113129691029507-852" src="https://platform.twitter.com/embed/Tweet.html?id=1636113129691029507"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1636113129691029507-852');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1636113129691029507&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Kent absolutely won the troll game with so much GPT-4 going around. Pure joy 😆&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1636206739820519424-10" src="https://platform.twitter.com/embed/Tweet.html?id=1636206739820519424"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1636206739820519424-10');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1636206739820519424&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;I really love this style of info dumping. Short bursts via whiteboard from Ben with his &lt;a href="https://twitter.com/hashtag/WhiteboardTheWeb"&gt;WhiteboardTheWeb series&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you aren't following already, it's well worth a go. This weeks is on point with React Suspense and Client/Server side fetching.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1636427842236866560-845" src="https://platform.twitter.com/embed/Tweet.html?id=1636427842236866560"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1636427842236866560-845');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1636427842236866560&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Matt meanwhile was having fun with &lt;a href="https://twitter.com/mattpocockuk/status/1636407437413548033?s=20"&gt;React types&lt;/a&gt; and running into some problems. So much so that Dan jumped on to ask how he could help fix them.&lt;/p&gt;

&lt;p&gt;It's so great to see this work in the open and the boffins coming together to work on solutions. Catch &lt;a href="https://www.youtube.com/watch?v=u_zoRJh9krU"&gt;Matt's live stream replay&lt;/a&gt; for the full rundown.&lt;/p&gt;

&lt;p&gt;Speaking of TypeScript, we had &lt;a href="https://devblogs.microsoft.com/typescript/announcing-typescript-5-0/"&gt;TS 5.0 release this week&lt;/a&gt;! There's a few new interesting features, my fave being the const params is now a thing (&lt;em&gt;goodbye as const!&lt;/em&gt;) and decorators.&lt;/p&gt;

&lt;p&gt;Not sure how I feel about decorators, as it reminds me far too much of OOP that we shy away from in JS-land, but I'm willing to be swayed.&lt;/p&gt;

&lt;p&gt;Another big release this week was the new React docs finally going live from beta. This has been a multi year project and it's great to see it finally come to fruition.&lt;/p&gt;

&lt;p&gt;It's a huge resource for learning all about React from simple to advanced concepts. I've really enjoyed the beta docs for some time, but you can find them now on &lt;a href="https://react.dev/"&gt;react.dev&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Julien had an interesting take on Generics with React Query options. Reading Tkdodo's recommendations made me pause for thought, we've been happily using the Generic version to allow for all options to be provided just for future proofing, but perhaps inference (and basically more zod) is the way to go.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1636740585473077250-566" src="https://platform.twitter.com/embed/Tweet.html?id=1636740585473077250"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1636740585473077250-566');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1636740585473077250&amp;amp;theme=dark"
  }



&lt;/p&gt;




&lt;h2&gt;
  
  
  This Week In React
&lt;/h2&gt;

&lt;p&gt;My top picks for &lt;a href="https://thisweekinreact.com/"&gt;TWIR&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Andrew writes about his experience &lt;a href="https://andre-landgraf.dev/blog/2023-03-11_web_standards_and_react"&gt;learning react and remix and the web APIs&lt;/a&gt;. It's a nice reminder that you don't need to stay in the same technology just because. There are web APIs available to us, even if we're mostly writing React. Same goes for some CSS and TailWind I find.&lt;/p&gt;

&lt;p&gt;A &lt;a href="https://reacttraining.com/blog/where-did-hooks-come-from"&gt;history of hooks&lt;/a&gt; by Brad is a nice little reminder of how we got to where we are today. Let's just skip over the 2016 period as the dark days 😆&lt;/p&gt;

&lt;p&gt;And that's all she wrote!&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;If you imported this line above your tailwind module.exports, it would allow for this: &lt;code&gt;/** @type {import('tailwindcss').Config} */&lt;/code&gt; ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Weekend Reading</title>
      <dc:creator>Simon Porter</dc:creator>
      <pubDate>Sat, 11 Mar 2023 00:00:00 +0000</pubDate>
      <link>https://dev.to/sporter/weekend-reading-4jk</link>
      <guid>https://dev.to/sporter/weekend-reading-4jk</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mzs5rplvt0vutslkuz.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24mzs5rplvt0vutslkuz.jpeg" alt="Image description" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Hello folks!
&lt;/h2&gt;

&lt;p&gt;It's been a week of React Server Components, so plenty of reading to go around about it!&lt;/p&gt;

&lt;p&gt;Maybe worth trying your hand with Next.js 13&lt;sup id="fnref1"&gt;1&lt;/sup&gt; to see what the fuss is about?&lt;/p&gt;




&lt;p&gt;&lt;a href="https://www.youtube.com/live/h7tur48JSaw"&gt;Kent hosted Dan and Joe&lt;/a&gt; for a 2 hour live stream to put forward his concerns. Plenty of familiar names turned up to listen in too. Don't have 2 hours spare? &lt;a href="https://simonporter.co.uk/posts/its-all-about-the-frameworks"&gt;Catch my recap&lt;/a&gt; from earlier this week.&lt;/p&gt;

&lt;p&gt;Dan was already looking for best ways to pitch RSC's. Plenty of information to skim through in this &lt;a href="https://twitter.com/dan_abramov/status/1631885118355718144"&gt;Twitter thread&lt;/a&gt;.&lt;iframe class="tweet-embed" id="tweet-1631885118355718144-456" src="https://platform.twitter.com/embed/Tweet.html?id=1631885118355718144"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1631885118355718144-456');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1631885118355718144&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Dan started playing with Remix some more (Kent's influence? 😁) and had some ideas for the Remix team on &lt;a href="https://github.com/remix-run/remix/issues/5763"&gt;implementing React transitions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And for those who have a &lt;em&gt;lot&lt;/em&gt; of free time this weekend, Ryan did a &lt;a href="https://www.youtube.com/live/QS9yAsv1czg"&gt;5 hour long in depth stream&lt;/a&gt; about server components.&lt;/p&gt;

&lt;p&gt;Matt's secret on &lt;a href="https://twitter.com/mattpocockuk/status/1633811575818579968"&gt;understanding TypeScript&lt;/a&gt; is out of the bag!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1633811575818579968-964" src="https://platform.twitter.com/embed/Tweet.html?id=1633811575818579968"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1633811575818579968-964');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1633811575818579968&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Speaking of which, Matt was also putting final touches on his &lt;a href="https://twitter.com/mattpocockuk/status/1634128647173861376"&gt;new TS library&lt;/a&gt;, 'untypeable'. When you want to type something you don't and won't control.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1634128647173861376-169" src="https://platform.twitter.com/embed/Tweet.html?id=1634128647173861376"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1634128647173861376-169');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1634128647173861376&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Zach had a great tip I've not seen before for &lt;a href="https://twitter.com/zg_dev/status/1633429660389318656"&gt;using Zod for local env type safety&lt;/a&gt;. We've had people onboard to our team before and miss required env vars to get things running, this would solve that problem for sure!&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1633429660389318656-611" src="https://platform.twitter.com/embed/Tweet.html?id=1633429660389318656"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1633429660389318656-611');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1633429660389318656&amp;amp;theme=dark"
  }



&lt;/p&gt;




&lt;h2&gt;
  
  
  This Week In React
&lt;/h2&gt;

&lt;p&gt;My top picks, make sure to &lt;a href="https://thisweekinreact.com/"&gt;subscribe&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Josh outlines some &lt;a href="https://www.joshwcomeau.com/react/common-beginner-mistakes/"&gt;common mistakes he's seen&lt;/a&gt; during his time teaching. I always enjoy Josh's writing style. How many do you remember making, or are making at the moment? 😅&lt;/p&gt;

&lt;p&gt;Alex writes about how important &lt;a href="https://alexsidorenko.com/blog/react-prop-drilling-composition/"&gt;component composition&lt;/a&gt; is to avoid prop drilling. I couldn't agree more with this, keeping components small and composable, and thinking about your component layout more than just how to get data to the component is key for good clean maintainability going forwards. This, ironically, is a good mentality to have for RSC's too!&lt;sup id="fnref2"&gt;2&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Zod, the TS first schema validator that is literally &lt;em&gt;everywhere&lt;/em&gt; right now, just &lt;a href="https://twitter.com/colinhacks/status/1632472849960280064"&gt;released a new version&lt;/a&gt;. Super neat looking &lt;code&gt;.ip()&lt;/code&gt; included which I can't wait to try out.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1632472849960280064-359" src="https://platform.twitter.com/embed/Tweet.html?id=1632472849960280064"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1632472849960280064-359');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1632472849960280064&amp;amp;theme=dark"
  }



&lt;/p&gt;




&lt;p&gt;And finally, in &lt;a href="https://css-weekly.com/"&gt;CSS Weekly&lt;/a&gt;:&lt;/p&gt;

&lt;p&gt;Šime writes an interesting article about the pros and cons of using the &lt;code&gt;::marker&lt;/code&gt; pseudo selector for &lt;a href="https://css-tricks.com/everything-you-need-to-know-about-the-gap-after-the-list-marker"&gt;custom bullet points&lt;/a&gt; in lists. It's not as simple as it first seems.&lt;/p&gt;

&lt;p&gt;Daniel writes about the &lt;a href="https://www.a11yproject.com/posts/are-you-making-these-five-mistakes-when-writing-alt-text"&gt;proper use of alt text for accessibility&lt;/a&gt;, something I'm likely failing on with my blog and will need to revisit. Do you?&lt;/p&gt;

&lt;p&gt;Here's a neat little app for &lt;a href="https://scrollbar.app/"&gt;testing custom scroll bars&lt;/a&gt;. I really like the simple design here too.&lt;/p&gt;

&lt;p&gt;Have a wonderful weekend!&lt;/p&gt;







&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;My blog is built with Next.JS 13 and RSC, and it was an interesting set up and shift in thinking. Worth giving a go. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;While you can't import server components in child components with RSC, you can pass them as props using the standard &lt;code&gt;{children}&lt;/code&gt; prop! ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>weekendreads</category>
      <category>react</category>
      <category>typescript</category>
      <category>css</category>
    </item>
    <item>
      <title>It's all about the frameworks</title>
      <dc:creator>Simon Porter</dc:creator>
      <pubDate>Fri, 10 Mar 2023 15:27:00 +0000</pubDate>
      <link>https://dev.to/sporter/its-all-about-the-frameworks-32ca</link>
      <guid>https://dev.to/sporter/its-all-about-the-frameworks-32ca</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnx4x5s0gle82rjh4l0k.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffnx4x5s0gle82rjh4l0k.jpeg" alt="This is actually be a picture of Dan who might be a robot after all" width="800" height="533"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  We've built PHP!
&lt;/h2&gt;

&lt;p&gt;This week Kent hosted &lt;a href="https://www.youtube.com/live/h7tur48JSaw"&gt;a live stream with Dan and Joe&lt;/a&gt; from the React core team to hash out what RSC's are all about. There's quite a lot of buzz &lt;em&gt;and&lt;/em&gt; confusion around this new feature.&lt;/p&gt;

&lt;p&gt;Dan has been super active on Twitter trying to answer questions and explain RSC's.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1631875392532279305-799" src="https://platform.twitter.com/embed/Tweet.html?id=1631875392532279305"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1631875392532279305-799');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1631875392532279305&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;p&gt;Briefly, RSC's allow React components to be rendered on the server, including data fetching. To be a server component though, they cannot hold state or produce side effects (e.g. &lt;code&gt;useState&lt;/code&gt; and &lt;code&gt;useEffect&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;This means less code gets sent to the client, so faster load times, and potentially faster data fetching if your server is located with your DB.&lt;/p&gt;

&lt;h2&gt;
  
  
  Confusing components
&lt;/h2&gt;

&lt;p&gt;At a high level, this makes sense. The devil's in the details! The tricky part is these RSC's are tightly bound to the frameworks right now, and so you really need Next.JS to play with this new tech&lt;sup id="fnref1"&gt;1&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Many folks in stream chat were expecting more. Docs? Examples? Repos? But it seems we're still too early for that just yet, and even Next.JS classes this as beta. That does signal things &lt;em&gt;could&lt;/em&gt; change but these calls for comments are a good way to put the feelers out and see what's what.&lt;/p&gt;

&lt;p&gt;The confusion comes over how exactly they work. Like kids in a toy store, we want things, and we want them now! RSC's bring a new mental model&lt;sup id="fnref2"&gt;2&lt;/sup&gt; to the table, and we're going to need to get on board with that before we decide if they're cutting the mustard.&lt;/p&gt;

&lt;p&gt;The best place for this right now is &lt;a href="https://twitter.com/dan_abramov"&gt;Dan's Twitter feed&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;iframe class="tweet-embed" id="tweet-1633574036767662080-130" src="https://platform.twitter.com/embed/Tweet.html?id=1633574036767662080"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1633574036767662080-130');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1633574036767662080&amp;amp;theme=dark"
  }



&lt;/p&gt;

&lt;h2&gt;
  
  
  Serverside concerns
&lt;/h2&gt;

&lt;p&gt;So what's the problem?&lt;/p&gt;

&lt;h3&gt;
  
  
  The waterfall
&lt;/h3&gt;

&lt;p&gt;Due to RSC's being nested among Client Components, it's going to be easier to end up with a server-side waterfall. As the tree gets parsed, one RSC can trigger a request, then as the tree progresses, more requests get triggered. Unlike Remix where server data is gathered at the route loader.&lt;/p&gt;

&lt;p&gt;The solution is to de-dupe requests via a new &lt;code&gt;fetch()&lt;/code&gt;. Next.js &lt;a href="https://beta.nextjs.org/docs/data-fetching/fetching#static-data-fetching"&gt;is doing this already&lt;/a&gt;, and means a query key can avoid waterfalls where possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  Patching fetch
&lt;/h3&gt;

&lt;p&gt;There was some buzz a while ago about React patching fetch. Muscling in on browser API's for React wasn't taken too kindly.&lt;/p&gt;

&lt;p&gt;They're not patching fetch, though it will be a custom fetch that the frameworks will need to provide &lt;strong&gt;if they want&lt;/strong&gt;, but it's ultimately a decision for the implementor.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cache headers and accessing req object
&lt;/h3&gt;

&lt;p&gt;Can we access the full request object with this custom fetch, and can we set custom headers?&lt;/p&gt;

&lt;p&gt;This had a bit of back and forth but ultimately it sounds like, &lt;em&gt;maybe&lt;/em&gt;. Depends on the framework 😄 The discussion was around the benefit of being able to do that in the first place and why it's needed.&lt;/p&gt;

&lt;h3&gt;
  
  
  'use client'
&lt;/h3&gt;

&lt;p&gt;In Next.JS components are RSC by default, and you need to add the &lt;code&gt;use client&lt;/code&gt; directive to function as they do today. This "opt out", rather than in, is seen as annoying and not overly clear what type of component you're dealing with from a DX perspective.&lt;/p&gt;

&lt;p&gt;Dan did acknowledge this and mentioned it was a bit of a trade off. For the given benefits, this seemed like the best option, though they did try others and liked those &lt;em&gt;worse&lt;/em&gt;. Perhaps it will improve as more and more people start to use them.&lt;/p&gt;

&lt;h2&gt;
  
  
  More than a feeling
&lt;/h2&gt;

&lt;p&gt;Overall, there was a sense of excitement. Still some trepidations from chat, and Kent didn't seem 100% won over, but he did seem more appeased.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--1l_e1fyu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://simonporter.co.uk/images/posts/its-all-about-the-frameworks.mdx/theo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--1l_e1fyu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://simonporter.co.uk/images/posts/its-all-about-the-frameworks.mdx/theo.png" alt="Message from Theo on his excitement" width="750" height="140"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2bwIH2cz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://simonporter.co.uk/images/posts/its-all-about-the-frameworks.mdx/ben.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2bwIH2cz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://simonporter.co.uk/images/posts/its-all-about-the-frameworks.mdx/ben.png" alt="Ben also looking forward to playing with RSC's outside of Next" width="750" height="120"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Many of these conversations seem to start with comparisons of frameworks though. "&lt;em&gt;Remix does it like this&lt;/em&gt;", "&lt;em&gt;Astro does it like this&lt;/em&gt;" which I think is wrong sort of questions. The real question is "&lt;em&gt;how does this improve my life as a &lt;strong&gt;React developer&lt;/strong&gt;&lt;/em&gt;", "&lt;em&gt;what are the possibilites&lt;/em&gt;"? And does it improve UX as well as DX? For me?&lt;/p&gt;

&lt;p&gt;Yes, I think it will. But it won't come overnight and not without a bit of work on your mental model.&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Shopify did attempt this with Hydrogen but abandoned it in favour of Remix. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;For most React developers certainly. Though if you use Astro or Remix, there are some comparisons here. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>react</category>
      <category>nextjs</category>
    </item>
  </channel>
</rss>
