2021 in Review

As 2021 draws to a close, I suppose it’s time for me to start babbling about what I’ve learned about in web development this year. Every year contains new surprises and new releases of libraries and packages and all sorts of other stuff, so there’s quite a bit to talk about.

(Not a very decent introduction)

Brave Browser

First of all, I became “braver” and started using Brave Browser! Safari’s privacy safeguards were not that optimal, the extensions weren’t all that available, and many Web APIs behaved in weird ways. Which is not so nice for a web developer. So I switched to Brave, which happens to be based on Chromium, arguably the browser engine that’s most up-to-date and on the cutting edge.

I still use Ghostery, though — it’s a nice complement for blocking trackers that Brave misses.

One annoying little caveat I discovered about Brave, however, is that it blocks all navigator.sendBeacon requests by default. Which makes sense from a privacy hardliner’s perspective because sendBeacon is used for logs and analytics, never for serious data exchange (that’s what it was built for, at least). However, from the perspective of a developer who’s trying to collect useful, privacy-respecting analytics, Brave is penalizing the use of modern Web APIs like sendBeacon and forcing them to use other methods such as XMLHttpRequest (Plausible) and make-believe images (Fathom). This is most certainly not an optimal situation. I hope that Brave can be more lenient towards privacy-respecting analytics and logging services.

1Password! 🎉🎉🎉

Before, I had passwords in a mess of CSV files, Chrome, Brave, and iCloud Keychain. I had to copy and paste passwords from other places when I needed them, and when I had to use passwords in apps I had to go into browser settings to copy the password.

Well, I guess I finally understood why unified password managers have a big market.

So I tried out 1Password, which seemed to be the leader in the industry. Which it was. The UI looked amazing (especially on the beta 1Password 8), the encryption was detailed in a really nice white paper, and the experience on macOS was really smooth.

I’m still in the 90-day trial right now, but there is no doubt that I will pay for 1Password once the trial ends. It’s just so good.

(I am not sponsored 🙃)

Electron

I went into Electron, because I wanted to build a better-looking and minimalistic Minecraft launcher after I’d seen many launchers which were heavyweight, made with Java, and took ages to start up. I hesitated for a long time because the multi-process model in Electron felt daunting.

Which it was. Fortunately, the Vite Electron Builder starter made the learning process much simpler for me, because I didn’t have to configure all of the npm scripts and other things to get started. It also came with Vite, which is a wonderful build tool.

The Inter-Process Communications (IPC) model was a source of confusion and consternation for me as I ran huge node scripts inside the renderer process and tried to access the DOM from the main process... But after a bit of learning from example and error traces, I got it straight. I’d like to detail the IPC model in a blog post “coming soon”, but for now this diagram would suffice:

Diagram on the Electron IPC model

I’m working on the Minecraft launcher right now with Electron and Vue, to be released sometime in 2022. ✨

TypeScript

TypeScript makes coding with JavaScript just so much easier! For those of you who don’t know what TypeScript is, it’s basically an extension of JavaScript that contains types and connects with your IDE via language servers to provide you with better autocomplete and linting.

TypeScript is a really great productivity booster. It’s incredibly useful when you don’t know how to start working with a library, because, well, you can just look at the type of its exports and the types of arguments the functions receive and get started without ever needing to even look at the docs!

TypeScript can also help you find errors in your code. For instance, this instance of JavaScript fails really quietly until you run it:

const thisIsAThing = 1;

console.log(thisIsAThng);
// ^^^^
// spelling mistake

And other more sophisticated mistakes. In contrast, TypeScript shows up with a big error message straight away and also provides useful hints:

const thisIsAThing = 1;

console.log(thisIsAThng);

/*
(error from TypeScript)
Cannot find name 'thisIsAThng'. Did you mean 'thisIsAThing'? ts(8888)
example.ts(1, 7): 'thisIsAThing' is declared here.
*/

It also helps you when you’re expecting some types and want to enforce them: for instance, if you want to have a function return a string, you can enforce it by writing

const prefix = (original: string): string => {
return '[ryanccn.dev] ' + original;
};

That way, if you lose track of what your code is doing and write something else that’s not supposed to be there, such as

const prefix = (original: string): string => {
console.log('[ryanccn.dev] ' + original);
};

The TypeScript compiler will very promptly throw an error:

A function whose declared type is neither 'void' nor 'any' must return a value. ts(8888)

So you see, that’s incredibly useful.

I’m using TypeScript in all of the projects in which I can, because it’s such a productivity booster and makes for a wonderful IDE experience.

(Unfortunately, Eleventy does not support TypeScript, which is why I’m considering moving this site to Next.js — yet again. 😅)

clank

This is a project born out of my own convenience and a generally open source spirit. clank is a simple CLI made with Deno (more on that later) that compiles your C++ source file into a custom cache directory before running the executable.

The CLI experience is made with Cliffy, a very useful CLI toolkit for Deno.

Some features include:

The gist of the clank workflow when you run a C++ source file is this:

  1. It creates a hash of the source file using SHA-256 in the Deno standard library.
  2. It checks whether this same file has been built before by checking whether the executable file exists in clank’s cache.
    1. If it doesn’t exist, it compiles the source file using clang++ or g++ (depending on your OS) to a file named with the hash.
    2. If it does, it skips compilation and goes straight to execution.
  3. It executes the executable with stdin, stdout and stderr all set to 'inherit' so that the experience is just like if you were running it directly.
  4. It exits, but not before it checks if the cache size is above 1GB. If it’s above 1GB, it uses a cool algorithm based on the age of the file and the size of the file to determine which files to delete first.

This project was fun to make and easy to use — if you also do CS competitions in C++, using clank will absolutely speed up your workflow!

This is how to install if you have Deno already installed:

deno install -Af -n "clank" --import-map "https://deno.land/x/clank/import_map.json" https://deno.land/x/clank/mod.ts

Then, just run any C++ file like this:

clank hello.cpp

Deno & Deno Deploy

Deno is the cool new runtime for JavaScript and TypeScript made by Ryan Dahl, the original creator of Node.js. It’s cool, because it tries to comply completely with the Web APIs commonly used in browsers, and it’s incredibly modern, with top-level await (which is still not generally available in Node.js) and modern ES syntax built right into it.

It’s fast, because it’s made with Rust (among many other CLIs), and it includes a formatter, linter, compiler, documentation generator, and other tools in one bundle of a CLI.

It uses ES Modules, which is ever so useful, and it imports only via URLs, which relieves you of the burden of having to maintain a package.json and makes it incredibly easy to test out libraries.

Correspondingly, Deno Deploy is

a distributed system that runs JavaScript, TypeScript, and WebAssembly at the edge, worldwide.

It runs Deno scripts that you can just run with the Deno CLI on your local dev environment, with support for the built in HTTP server modules. It’s a distributed worker architecture, like Cloudflare Workers and Lambda@Edge, so it loads really fast, and it’s really easy to make because everything is based on Web APIs, like fetch and Request and Response.

For instance, this is from the source code of my link shortener at a.ryanccn.dev:

const handler = async (req: Request) => {
const fragments = new URL(req.url).pathname.split('/').filter((a) => !!a);

if (fragments.length === 0) {
// root url
return responses.redirect('https://ryanccn.dev');
}

if (fragments.length >= 2) {
// more than 1 piece of path
return responses.notFound();
}

if (req.method !== 'GET') {
return responses.notAllowed();
}

const res1 = await get(fragments[0]);

if (!res1.ok || !res1.data) {
// no redirect exists for such an id
return responses.notFound();
}

// ok
const res2 = await click(fragments[0], res1.data.clicks);
return responses.redirect(res1.data.t, res1.latency + res2.latency);
};

It looks really simple, and with the flexible ES Modules system built right into Deno, it’s easy to modularize functionality, as you can obviously see from the imports from ./db.ts (in which I connect to Supabase) and ./responses.ts (in which I have functions for creating Responses).

Deno is a promising piece of tooling for the future, and the only problem now is that the ecosystem is not yet complete, so many sophisticated setups required for building big web apps and native apps are not possible. However, building simple scripts with Deno has been a wonderful experience, and I look forward to the day when I can use Deno to build a desktop app or a mobile app or something in IoT. The future is endless! 🚀

Lines of code (tokei)

These are clips of output in each of my projects from tokei, a CLI (as always, written in Rust) that counts your code really quickly. It deserves a checking out!

redirects

===============================================================================
 Language            Files        Lines         Code     Comments       Blanks
===============================================================================
 TypeScript              5          175          134            4           37
 YAML                    1            7            7            0            0
===============================================================================
 Total                   6          182          141            4           37
===============================================================================

clank

===============================================================================
 Language            Files        Lines         Code     Comments       Blanks
===============================================================================
 C++                     3           37           26            0           11
 JSON                    1            6            6            0            0
 TypeScript             18          757          593            4          160
-------------------------------------------------------------------------------
 Markdown                1           44            0           30           14
 |- BASH                 1           34           14           11            9
 (Total)                             78           14           41           23
===============================================================================
 Total                  23          844          625           34          185
===============================================================================

redirects

===============================================================================
 Language            Files        Lines         Code     Comments       Blanks
===============================================================================
 TypeScript              5          175          134            4           37
 YAML                    1            7            7            0            0
===============================================================================
 Total                   6          182          141            4           37
===============================================================================

ryanccn.dev

===============================================================================
 Language            Files        Lines         Code     Comments       Blanks
===============================================================================
 CSS                     2          213          169           11           33
 JavaScript             26         1096          899           57          140
 JSON                    2           94           94            0            0
 TypeScript              3          218          169            7           42
-------------------------------------------------------------------------------
 HTML                    1           19           19            0            0
 |- CSS                  1           38           34            0            4
 (Total)                             57           53            0            4
-------------------------------------------------------------------------------
 Markdown               12         1173            0          696          477
 |- BASH                 2            5            5            0            0
 |- HTML                 2          102          100            0            2
 |- JSON                 3           91           84            0            7
 |- JSX                  6          502          387           47           68
 |- Markdown             1            0            0            0            0
 (Total)                           1873          576          743          554
===============================================================================
 Total                  46         2813         1350          771          692
===============================================================================

Untitled Minecraft launcher (WIP)

===============================================================================
 Language            Files        Lines         Code     Comments       Blanks
===============================================================================
 CSS                     1            1            1            0            0
 HTML                    2           35           34            0            1
 JavaScript              9          310          236           38           36
 JSON                    5          100           99            0            1
 TypeScript             11          518          355           89           74
-------------------------------------------------------------------------------
 Vue                     1            5            4            0            1
 |- HTML                 1           19           19            0            0
 |- JavaScript           1           53           42            0           11
 (Total)                             77           65            0           12
===============================================================================
 Total                  29          969          729          127          113
===============================================================================

C++

===============================================================================
 Language            Files        Lines         Code     Comments       Blanks
===============================================================================
 C++                   383        17177        12736          401         4040
===============================================================================
 Total                 383        17177        12736          401         4040
===============================================================================

[private project]

===============================================================================
 Language            Files        Lines         Code     Comments       Blanks
===============================================================================
 CSS                     1           27           23            0            4
 GraphQL                 1           35           30            1            4
 JavaScript              4           80           72            3            5
 JSON                    4           70           70            0            0
 TSX                     9          393          331            0           62
 TypeScript              6          246          130           76           40
-------------------------------------------------------------------------------
 Markdown                1           31            0           17           14
 |- BASH                 1            3            2            1            0
 (Total)                             34            2           18           14
===============================================================================
 Total                  26          882          656           97          129
===============================================================================

Total

(this might not be an accurate sum of the previous snippets, but whatever, it’s okay)

But 22,797 lines of code is pretty impressive to me though!

===============================================================================
 Language            Files        Lines         Code     Comments       Blanks
===============================================================================
 C++                   386        17214        12762          401         4051
 CSS                     4          241          193           11           37
 GraphQL                 1           35           30            1            4
 JavaScript             37         1420         1154           97          169
 JSON                   11          266          265            0            1
 TSX                     9          393          331            0           62
 TypeScript             43         1914         1381          180          353
 YAML                    1            7            7            0            0
-------------------------------------------------------------------------------
 HTML                    3           54           53            0            1
 |- CSS                  1           38           34            0            4
 (Total)                             92           87            0            5
-------------------------------------------------------------------------------
 Markdown               14         1248            0          743          505
 |- BASH                 4           42           21           12            9
 |- HTML                 2          102          100            0            2
 |- JSON                 3           91           84            0            7
 |- JSX                  6          502          387           47           68
 |- Markdown             1            0            0            0            0
 (Total)                           1985          592          802          591
-------------------------------------------------------------------------------
 Vue                     1            5            4            0            1
 |- HTML                 1           19           19            0            0
 |- JavaScript           1           53           42            0           11
 (Total)                             77           65            0           12
===============================================================================
 Total                 510        22797        16180         1433         5184
===============================================================================

Thanks a lot for reading this article to the end! If you have any thoughts or just anything to talk about, you can DM me on Twitter @RyanCaoDev. Or take a look at my projects on GitHub!

It’s 23:59:59 right now, and with that, wish you all a very happy New Year! 🌈🦄🌈

If you have something to say...

You can also fire me a Twitter DM!

Click to open my Twitter: @RyanCaoDev.