2020 in Review

I have learned a lot of things during 2020. Since I just got into frontend web development last summer, I learned lots and still have lots to learn. A couple of things that I have learnt:

React + Next.js

React, although it might be unwieldy and messy, is still one of my favorite JavaScript frameworks because of its authoring experience, which is very “Just JavaScript” and feels great when you also have JSX.

When I use React, I almost always use Next.js as the framework, because of its hybrid capabilities, serverless architecture, filesystem routing, and many other stuff that I really like. It really speeds up my workflow compared to Gatsby, which I do agree is a great framework but sometimes really is overkill, both on developer experience, client-side JavaScript and my MacBook Pro memory.

As to React and React DOM’s hulking size, I chose to use preact/compat in order to shorten the size down to 3KB with the same API that works everywhere. With Next.js’s Webpack custom config, this was easily done by adding module aliases:

module.exports = {
  webpack: (config, { dev, isServer }) => {
    // Replace React with Preact only in client production build
    if (!dev && !isServer) {
      Object.assign(config.resolve.alias, {
        react: 'preact/compat',
        'react-dom/test-utils': 'preact/test-utils',
        'react-dom': 'preact/compat',

    return config;

Shoutout to Lee Robinson for first mentioning this approach on his blog post 😉

Tailwind CSS + twin.macro

Surprise here - I never actually learned CSS systematically! My first styling was done using bits and pieces of CSS copied from the forever-mighty Stack Overflow slapped with !important onto Bootstrap. After I learned about Tailwind CSS, however, it made my life much easier as a developer. It allowed me to rapidly build modern websites without ever leaving your HTML. And in addition, it makes it easy to be consistent with color choices, spacing, typography, shadows, and everything else that makes up a well-engineered design system.

As Adam Wathan predicted, my first reaction to Tailwind CSS was “Ugh! Why would you do that? That’s disgusting!” Even though I never wrote a medium-to-large-sized CSS file before, I was much more accustomed to seeing classes such as article-title or navbar-item-primary. Certainly not bg-red-400! Then, after I tried it out for once, I totally fell in love with it.

However, there was one problem. My development builds were taking ages to compile because Tailwind generates thousands of classes in development without purging in order to not have to rebuild every time you edit the HTML file. This annoyed me even more than the 3-second Webpack compilation, and I wondered if there was a way to speed it up.

There was. Twin blends the magic of Tailwind with the flexibility of CSS-in-JS (emotion, styled-components and goober) at build time (i.e. without any runtime). It generates CSS style objects according to the CSS-in-JS spec on-demand when it detects the tw keyword being used in markup and inserts it onto the styles prop (Emotion) of the element. And in production, each set of styles has its own class name (e.g. css-3yn28ej-link)** and the styles are injected by Next.js’s SSR automatically into the <head>.

This drastically sped up builds and also gave me much more flexibility, as I didn’t have to write @layer utilities anymore in a custom CSS file and wait for 10 seconds. I could just use the styles prop and concatenate the styles that Twin generated with custom styles I wrote using the css export of Emotion. This avoided the “bailwind” dilemma that was constantly a problem for Tailwind CSS users.

Snowpack & ESM

As a frontend developer, it is my “duty” to learn about new technologies and perhaps use them a little bit in production. (Always use them in development.) One of the most cutting-edge technologies I have encountered this year is Snowpack + Skypack by the amazing Pika** team. These awesome tools allow for no bundling in development and only use ES Modules, which modern browsers support.

Unbundled development has several advantages over the traditional bundled development approach:

  • Single-file builds are fast.
  • Single-file builds are deterministic.
  • Single-file builds are easier to debug.
  • Project size doesn’t affect dev speed.
  • Individual files cache better.

You should be able to use a bundler because you want to, and not because you need to. That was the original concept that Snowpack was designed to address. Snowpack treats bundling as an optional production optimization, which means you’re free to skip over the extra complexity of bundling until you need it. (Snowpack docs)


After immersing myself in all that client-side JavaScript, I started to explore some alternative static site generators that didn’t output any client-side bundles by default.

  • Hugo was incredibly fast but I didn’t want to learn all of the Go syntax and also I wanted to be able to write code myself that could augment the SSG in addition to plugins.
  • Charge was a very interesting one that used React as a templating language, but it was highly opinionated and the creator, Brendan Weiss**, had started using Gatsby for his site, so I didn’t see why I would use it for something serious.
  • I had tried Hexo on my site about 17 versions before, and it was a mess. Did not like.

Then I came into contact with Eleventy, and I instantly liked it. The majority of the custom logic could be implemented in the .eleventy.js file, which is like how you would use gatsby-node.js, and tons of things were customizable, such as permalink, collections, etc.

Although it didn’t have as much users as other SSGs, it was quickly growing in popularity and is now closing in on v1. Development has been very rapid, with Zach Leatherman, Philipp Rudloff, and lots of other great guys contributing to the repo with as much as 6,000 additions a week!


I started caring more about my privacy online. Reading articles by WIRED, DuckDuckGo, and Mozilla told me about lots of violations on my privacy that was enabled without proper defense mechanisms. I deleted Google Chrome from my Mac, because guess what? Google is the biggest advertiser on the planet, and they have a browser that knows everything you do on the Internet. I’m sure everything’s going to be fine.

So I started using Safari, which now I know to be very beautifully designed (especially in the new Big Sur release) and also incredibly fast compared to Chrome, which is a memory hog. For more advanced web platform features, I use Firefox Developer Edition, which has a wonderful DevTools and supports most modern Web Platform features. I also have Ghostery complementing Safari’s built-in tracker blocking features.


I learned lots during 2020 that I could possibly never forget.

Comment below if you have any thoughts 🧐