swr compared to @tanstack/react-query

August 30, 2024
2 comments JavaScript

I have a single-page-app built with React and Vite. It fetches data entirely on the client-side after it has started up. So there's no server at play other than the server that hosts the static assets.
Until yesterday, the app was use swr to fetch data, now it's using @tanstack/react-query instead. Why? Because I'm curious. This blog post attempts to jot down some of the difference and contrasts.

If you want to jump straight to the port diff, look at this commit: https://github.com/peterbe/analytics-peterbecom/pull/47/commits/eac4f873303bfb493320b0b4aa0f5f6ba133001a

Bundle phobia

When @tanstack/react-query first came out, back in the day when it was called React Query, I looked into it and immediately got scared how large it was. I think they've done some great work to remedy that because it's now not much larger than swr. Perhaps it's because swr, since wayback when, has grown too.

When I run npm run build it spits this out:

Truncated! Read the rest by clicking the link below.

Wouter + Vite is the new create-react-app, and I love it

August 16, 2024
0 comments React, Node, Bun

If you've done React for a while, you most likely remember Create React App. It was/is a prepared config that combines React with webpack, and eslint. Essentially, you get immediate access to making apps with React in a local dev server and it produces a complete build artefact that you can upload to a web server and host your SPA (Single Page App). I loved it and blogged much about it in distant past.

The create-react-app project died, and what came onto the scene was tools that solved React rendering configs with SSR (Server Side Rendering). In particular, we now have great frameworks like Gatsby, Next.js, Remix, and Astro. They're great, especially if you want to use server-side rendering with code-splitting by route and that sweet TypeScript integration between your server (fs, databases, secrets) and your rendering components.

However, I still think there is a place for a super light and simple SPA tool that only adds routing, hot module reloading, and build artefacts. For that, I love Vite + Wouter. At least for now :)
What's so great about it? Speed

Truncated! Read the rest by clicking the link below.

Default environment variables in Bash

August 12, 2024
0 comments Bash

So many of you, this is so basic that it's embarrassing. Any maybe to me too. But the truth is, I often forget the syntax. By mentioning it here, hopefully, I'll memorize it better.

To set a default environment variables, consider this example Bash program:


#!/bin/bash

: "${PORT:=8000}"

echo "Port number: $PORT"

When you run it, it defaults to the value 8000 (a string)


❯ bash dummy.sh
HOSTNAME:8000

And if you override the default:

Truncated! Read the rest by clicking the link below.

Comparing Deno vs Node vs Bun

August 5, 2024
0 comments Bun, JavaScript

This is an unscientific comparison update from previous blog posts that compared Node and Bun, but didn't compare with Deno.

Temperature conversion

From Converting Celsius to Fahrenheit round-up it compared a super simple script that just prints a couple of lines of text after some basic computation. If you include Deno on that run you get:


❯ hyperfine --shell=none --warmup 3 "bun run conversion.js" "node conversion.js" "deno run conversion.js"
Benchmark 1: bun run conversion.js
  Time (mean ± σ):      22.2 ms ±   2.1 ms    [User: 12.4 ms, System: 8.6 ms]
  Range (min … max):    20.6 ms …  36.0 ms    136 runs

  Warning: Statistical outliers were detected. Consider re-running this benchmark on a quiet system without any interferences from other programs. It might help to use the '--warmup' or '--prepare' options.

...

Summary
  bun run conversion.js ran
    1.97 ± 0.35 times faster than deno run conversion.js
    2.41 ± 0.39 times faster than node conversion.js

Truncated! Read the rest by clicking the link below.

Trying out (and liking!) MeetingBar for macOS

July 25, 2024
0 comments macOS

My GitHub colleague @joelhawksley recommended a macOS app called MeetingBar.
You installed it and granted it access to your Google Calendar (or Apple Calendar). Now, it can show, in your menu bar, a preview of your next (upcoming) meeting.

I installed it today and it looks like this:

Screenshot from macOS menu bar

If you click on it, it shows another view of other (next) upcoming events and other all-day events going on.

Converting Celsius to Fahrenheit round-up

July 22, 2024
0 comments Go, Node, Python, Bun, Ruby, Rust, JavaScript

In the last couple of days, I've created variations of a simple algorithm to demonstrate how Celcius and Fahrenheit seem to relate to each other if you "mirror the number".
It wasn't supposed to be about the programming language. Still, I used Python in the first one and I noticed that since the code is simple, it could be fun to write variants of it in other languages.

  1. Converting Celsius to Fahrenheit with Python
  2. Converting Celsius to Fahrenheit with TypeScript
  3. Converting Celsius to Fahrenheit with Go
  4. Converting Celsius to Fahrenheit with Ruby
  5. Converting Celsius to Fahrenheit with Crystal
  6. Converting Celsius to Fahrenheit with Rust

It was a fun exercise.

Truncated! Read the rest by clicking the link below.

Node watch mode and TypeScript

July 21, 2024
0 comments Node, JavaScript

You might have heard that Node now has watch mode. It watches the files you're saving and re-runs the node command automatically. Example:


// example.js

function c2f(c) {
  return (c * 9) / 5 + 32;
}
console.log(c2f(0));

Now, run it like this:

❯ node --watch example.js
32
Completed running 'example.js'

Edit that example.js and the terminal will look like this:

Restarting 'example.js'
32
Completed running 'example.js'

(even if the file didn't change. I.e. you just hit Cmd-S to save)

Truncated! Read the rest by clicking the link below.

Converting Celsius to Fahrenheit with Rust

July 20, 2024
0 comments Rust

Previously in this series:

  1. Converting Celsius to Fahrenheit with Python
  2. TypeScript
  3. Go
  4. Ruby
  5. Crystal

This time, in Rust:


fn c2f(c: i8) -> f32 {
    let c = c as f32;
    c * 9.0 / 5.0 + 32.0
}

fn is_mirror(a: i8, b: i8) -> bool {
    let a = massage(a);
    let b = reverse_string(massage(b));
    a == b
}

fn massage(n: i8) -> String {
    if n < 10 {
        return format!("0{}", n);
    } else if n >= 100 {
        return massage(n - 100);
    } else {
        return format!("{}", n);
    }
}

fn reverse_string(s: String) -> String {
    s.chars().rev().collect()
}

fn print_conversion(c: i8, f: i8) {
    println!("{}°C ~= {}°F", c, f);
}

fn main() {
    let mut c = 4;
    while c < 100 {
        let f = c2f(c);
        if is_mirror(c, f.ceil() as i8) {
            print_conversion(c, f.ceil() as i8)
        } else if is_mirror(c, f.floor() as i8) {
            print_conversion(c, f.floor() as i8)
        } else {
            break;
        }
        c += 12;
    }
}

Run it like this:


rustc -o conversion-rs conversion.rs && ./conversion-rs

and the output becomes:

4°C ~= 40°F
16°C ~= 61°F
28°C ~= 82°F
40°C ~= 104°F
52°C ~= 125°F

Converting Celsius to Fahrenheit with Crystal

July 19, 2024
0 comments Ruby

Previously in this series:

  1. Converting Celsius to Fahrenheit with Python
  2. TypeScript
  3. Go
  4. Ruby

Crystal?

Crystal is a general-purpose, object-oriented programming language. With syntax inspired by Ruby, it's a compiled language with static type-checking.


def c2f(c)
    c * 9.0 / 5 + 32;
end

def is_mirror(a, b)
    massage(a).reverse == massage(b)
end

def massage(n)
    if n < 10
        "0#{n}"
    elsif n >= 100
        massage(n - 100)
    else
        n.to_s
    end
end

def print_conv(c, f)
    puts "#{c}°C ~= #{f}°F"
end

(4...100).step(12).each do |c|
    f = c2f(c)
    if is_mirror(c, f.ceil.to_i)
        print_conv(c, f.ceil.to_i)
    elsif is_mirror(c, f.floor.to_i)
        print_conv(c, f.floor.to_i)
    else
        break
    end
end

And this is its diff with the Ruby version:


<     if is_mirror(c, f.ceil)
<         print_conv(c, f.ceil)
<     elsif is_mirror(c, f.floor)
<         print_conv(c, f.floor)
---
>     if is_mirror(c, f.ceil.to_i)
>         print_conv(c, f.ceil.to_i)
>     elsif is_mirror(c, f.floor.to_i)
>         print_conv(c, f.floor.to_i)

Run it like this:


crystal conversion.cr

or build and run:


crystal build -o conversion-cr conversion.cr
./conversion-cr

and the output becomes:

4°C ~= 40°F
16°C ~= 61°F
28°C ~= 82°F
40°C ~= 104°F
52°C ~= 125°F