alifeiliu

alifeiliu

哪有什么无限进步,能进一步是一步
github
x
discord server
email
strava
bilibili

This Week's Bulletin #1

As a technical professional, especially as a senior programmer, surviving in the current terrible social environment always brings a sense of anxiety, which is caused by instability, lack of achievements, and peer pressure.

Book Review#

Recently, I have been reading the book "The Efficiency Handbook." Although I don't recommend it, as it contains personal opinions, repetitive and irrelevant content, and boasts without grounding, there are still some concepts that I find acceptable, such as honing practical skills. Indeed, investing in oneself, setting goals for one's life, breaking them down into actionable steps, and truly implementing them, just like leveling up in a game, allows oneself to continuously grow and cultivate the excellent qualities of the people around them, even surpassing them, making them one's own strengths, and thus alleviating the aforementioned anxieties.

Work#

It has been four months since I left Bilibili and joined a big company. It feels like the growth during the probation period is the most rapid. I have overcome the challenges of high OKRs, familiarizing myself with the environment, and interacting with new colleagues. After becoming a regular employee, it feels like all the pressure has disappeared. There are no new and exciting technologies to learn, and no complex projects to take on. It's frustrating!

However, I found that there are many repositories worth learning on the company's code hosting platform. After all, they are applied in production environments with a large number of UV/PV. Alright, now I have a direction. I can clone the repositories I'm interested in and learn independently. Not only can I benefit from them, but I can also learn new technologies! 😏

Slacking Off at Work#

Tailwind#

One of the business projects in the company uses Tailwind. I had heard of it before, but at that time, I thought it required memorizing a lot of class names and writing long strings of classes on elements, which was quite annoying, so I didn't delve into it. However, after joining the company, I realized that performance optimization is a common practice here (I will write a series about it later), and it is also used in business development and maintenance. Therefore, I spent a day reading the official documentation and now I have a clear understanding.

Advantages#

In my opinion, the obvious advantages of Tailwind are:

  • Optimized CSS: It is said that the CSS generated by most projects will not exceed 10KB. Traditional handcrafted CSS may contain a lot of repetitive code, while Tailwind provides better performance.
  • Semantic to Atomic: Tailwind follows a set of design specifications, allowing for fine-grained customization. Compared to inline magic values in the style attribute or inconsistent class naming conventions, Tailwind provides more constraints and better semantics.
  • No separate CSS file: You don't have to worry about deleting corresponding class names when removing elements, and there are no style conflicts.
  • Development experience: You don't have to switch back and forth between CSS and HTML/components. Just add class names to elements and you're good to go.

I fully accept its disadvantages compared to its advantages. Therefore, in the next new project or when optimizing existing projects, I might consider using Tailwind's atomic approach to further reduce CSS file size.

tailwind-merge
Solves the problem of merging class names and correctly overrides styles.

import { twMerge } from 'tailwind-merge'

twMerge('px-2 py-1 bg-red hover:bg-dark-red', 'p-3 bg-[#B91C1C]')
// → 'hover:bg-dark-red p-3 bg-[#B91C1C]'

class-variance-authority
Generates different combinations of class names based on component attributes. Can be used to create custom components with Tailwind.

// components/button.ts
import { cva } from "class-variance-authority";
 
const button = cva(["font-semibold", "border", "rounded"], {
  variants: {
    intent: {
      primary: [
        "bg-blue-500",
        "text-white",
        "border-transparent",
        "hover:bg-blue-600",
      ],
      // **or**
      // primary: "bg-blue-500 text-white border-transparent hover:bg-blue-600",
      secondary: [
        "bg-white",
        "text-gray-800",
        "border-gray-400",
        "hover:bg-gray-100",
      ],
    },
    size: {
      small: ["text-sm", "py-1", "px-2"],
      medium: ["text-base", "py-2", "px-4"],
    },
  },
  compoundVariants: [
    {
      intent: "primary",
      size: "medium",
      class: "uppercase",
      // **or** if you're a React.js user, `className` may feel more consistent:
      // className: "uppercase"
    },
  ],
  defaultVariants: {
    intent: "primary",
    size: "medium",
  },
});
 
button();
// => "font-semibold border rounded bg-blue-500 text-white border-transparent hover:bg-blue-600 text-base py-2 px-4 uppercase"
 
button({ intent: "secondary", size: "small" });
// => "font-semibold border rounded bg-white text-gray-800 border-gray-400 hover:bg-gray-100 text-sm py-1 px-2"

clsx
A CSS-in-JS library. Here is a concise official description:

A tiny (239B) utility for constructing className strings conditionally.
Also serves as a faster & smaller drop-in replacement for the classnames module.

It dynamically adds or removes CSS classes based on conditional values, for example:

import clsx from 'clsx';
// or
import { clsx } from 'clsx';

// Strings (variadic)
clsx('foo', true && 'bar', 'baz');
//=> 'foo bar baz'

// Objects
clsx({ foo:true, bar:false, baz:isTrue() });
//=> 'foo baz'

// Objects (variadic)
clsx({ foo:true }, { bar:false }, null, { '--foobar':'hello' });
//=> 'foo --foobar'

// Arrays
clsx(['foo', 0, false, 'bar']);
//=> 'foo bar'

// Arrays (variadic)
clsx(['foo'], ['', 0, false, 'bar'], [['baz', [['hello'], 'there']]]);
//=> 'foo bar baz hello there'

// Kitchen sink (with nesting)
clsx('foo', [1 && 'bar', { baz:false, bat:null }, ['hello', ['world']]], 'cya');
//=> 'foo bar hello world cya'

tailwindcss-animate and tailwindcss-animated
Tailwind animation plugins.

Preact#

While optimizing the company's applications, I found that most of the cases where the INP (Input Delay) value exceeded 200 were related to the html or html>body elements, and the INP interaction events were pointerdown/up or keydown/up.

image

This issue always occurred when simulating CPU x4 slowdown in the local browser and was independent of network speed. Based on my speculation, it is related to the application's adoption of an isomorphic + streaming rendering approach. The first chunk of the stream allows users to see part of the page content, and at this point, users may interact with the page. Client-side interactions depend on the execution of the entry JS file, and the hydration injection is required for interactions to take effect. When clicking on a blank area, INP is recorded:

image

When any key is pressed, INP is recorded:

image

I ran a performance test:

image

Especially on devices with poor performance, the download of JS files is not affected, but parsing and execution may be slightly affected, resulting in a higher probability of high Input delay. When investigating the INP issue in the company's applications, I found that the inclusion of react.production.min.js and react-dom.production.min.js blocks user interactions during the initial loading phase. Therefore, I have to consider whether there are better options for framework selection.

Fortunately, preact is said to be a drop-in replacement for react, and its production version is only 3.5KB in size. It's amazing!

image

image

image

If it can bring performance advantages, can it optimize INP? I will try it when I have the opportunity.

Interesting Things#

  • Online tool for checking package size and download time: bundlephobia
  • An interesting illustrated book called "Life Montage," which depicts small things in life, healing, and empathy. At this moment, what I think in my world must have been thought by someone else at some point.
  • Blog cover images taken from 500px
Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.