Welcome To My GitHub Kitchen

Andrea Giammarchi
6 min readFeb 20, 2020
Photo by Asiya Kiev on Unsplash

One of my New Year’s Eve resolutions was to stop creating libraries and focus on something more concrete in my spare time … which I did, but such thing ended up with me creating dozen libraries in the making 😅

What’s On The Menu ?

I am not going to share my longer term side project, but it’s gonna be epic, and it will require tons of modules to work “out of the box” in every machine.

While prototyping, I’ve found lack of some library for my needs, so that, as usual, I’ve filled all the gaps, and now I’m good to go with everything else.

I won’t explain how I’ll be using these modules or libraries, as each of them has a valid use case you might face at some point too. Let’s start!

The Null Class

We’ve all written Object.create(null) at least once in our JS life, and yet we can’t extend null via classes declaration. Dictionaries are common enough that having a class to create, or extend these, makes sense, and it’s also faster.

Meet the null-class package, it’s already feature complete and compatible with every JS engine.

The “shimbol”

The name plays with the concept of “shim” and JS Symbol . It’s specially handy when you want to avoid name clashes when assigning properties (i.e. to a dictionary). It’s stupidly simple, but it’s all I need 90% of the time I use symbols, so maybe you can use it too: shimbol

An Essential CLI Markdown

If you write CLI in Node.js, you likely want to show fancy text in console to help developers reading messages in relevant chunks.

The essential-md modules gives you just that:

  • headers via one or more #
  • bold, underlined, dimmed, or striked text
  • lists, quotes, and single to multi-line code
  • a .clear(N) method to clear up to N rows
  • a basic prompt functionality to ask anything

An SQLite Template Literal Tag Facade

The sqlite-tag module is a safe indirection, based on template literals, to create SQL queries. It maps automatically all interpolations into ? parameters so that it prevents automatically SQL injections.

It comes with a handy raw tag, to explicitly compose queries when needed.

// will insert into table_0, table_1, and table_2
// respective `i` values
for (let i = 0; i < 3; i++)
await query`INSERT INTO ${raw`table_${i}`} VALUES (${i})`;

It works with sql.js too, allowing exact same client/server queries through template literals, which are awesome!

P.S. this module was based on pg-tag, which is the same but for PostgreSQL

An easier scheduler

The sob module simplifies a lot scheduling of requestAnimationFrame or requestIdleCallback, throttling when same callback is re-schedule, as opposite of keep clearing and adding new timers.

Most importantly, anything scheduled runs only when the tab is visible.

A Clock Scheduler

Keeping the scheduling argument, clock-scheduler is instead based on the machine clock. The main goal is to be able to trigger callbacks only when the second, minute, hour, or even month, ticks, without using intervals or requestAnimationFrame at all. You pass minute instead of 60 * 1000, and differently from 60 * 1000 it doesn’t matter when you scheduled that, the callback will trigger whenever the next minute ticks.

Yet another LRU

Differently from every others, the basic-lru module is a drop-in replacement for any Map instance you have: it literally extends the Map class.

This makes this module smaller than average and fast as Map can be, with an optimistic, asynchronous, self-cleanup procedure that won’t be on your way.

The API is nearly 100% compatible with lru, lru-cache, quick-lru, and lru-map modules.

Some Basic Record

Focused on raw performance, the basic-record module lets you define via object literals “records”, instead of classes, for data oriented objects.

const {create, define} = require('basic-record');// define a Record class through one or more arguments
const Point2D = define({x: 0, y: 0});
// define mixins by passing records and/or literals
const Point3D = define(Point2D, {z: 0});
// create an instance via new Record or create(Record)
const p2d = create(Point2D);
// optionally pass an `init` object to assign its values
const p3d = create(Point3D, {y: 123, z: 9});

Packed Arrays

Sticking with raw performance, did you know that most common practices to create arrays result in worse performance than expected?

new Array(length); // holey, not packed
array.fill(...); // holey, not packed
Array.from(...); // holey, not packed
// ... and so on and so forth ...

That’s what packed-array solves, it gives you back the most optimized version of the array you need to loop, or change, over and over.

A better Object.assign

Did you also know that Object.assign, as well as object {...spread} loses, after accessing, properties and their descriptors?

const base = {get random() { return Math.random() }};
const spread = {...base};
spread.random === spread.random; // true 😱

With exact same API, the assign-properties module provides a way to compose or define better mixins, preserving all descriptors.

uHTML

The micro HTML module is a lighterhtml subset, and it weights 2.4K. It’s blazing fast, and the most compact library of its kind.

Wicked Elements with Hooks !

Not only wickedElements got smaller, faster, better, stronger, but it now comes with hooks too, through the hookedElements module.

import {define, useState} from 'hooked-elements';define("my-counter", element => {
const [current, update] = useState(0);
const [dec, count, inc] = $$('.dec, .count, .inc');
count.textContent = current;
dec.onclick = () => update(current - 1);
inc.onclick = () => update(current + 1);
});

And that’s all you need to have a classic counter.

The previously mentioned uHTML also plays well, if you want to keep it as small and simple as possible, and lighterhtml is always an option too.

Client Side De/Compression

Chrome 80 finally brought in Compression and Decompression Streams, which allowed me to create WebCompressor.

Imagine we can now put in the localStorage 25K items, instead of 60, isn’t that awesome? And that’s only thanks to a combination of compression, and an uint8-to-utf16 module, with an alternative uint8-to-base64 one.

Bear in mind, I’m not suggesting you should store everything in localStorage now, but you get the potentials of this spec for posting data, cookies, etc.

And Some Quick Update Too …

Well, new stuff is fun, but older stuff needs maintenance too.

Unicode 13 Emoji 😊

As the new version of Unicode is out, you might be happy to know that all their names and descriptions, in US English, have been updated in both emoji-essential, and emoji-short-names packages.

wickedElements reached v1

The smallest utility to have Custom Elements like components in every browser and without polyfills got even smaller, as in … 1.1K for the modern, ECMAScript version, with no more than 1.5K for the transpiled one to reach all browsers.

Be sure you understand the breaking changes too, if you were using it before.

Heresy SSR 🔥 got much smaller

As the canvas module has been removed from basicHTML, also updated as v2, heresy-ssr v1 now installs in seconds, and without that extra 100MB of unnecessary craft brought in by third parts.

Feel free to explicitly install npm i canvas too, if that’s something you used before, but in general, you shouldn’t notice any difference whatsoever.

What about the rest?

Well, I’ve tried to summarize the current status of my Front End related libraries in this viperHTML issue, where I hope it’s even more clear what’s going on. Sadly, viperHTML has been left behind, but since heresy is gaining more popularity, I think it’s safe to say you all have a better alternative ;-)

So thanks for coming 🙏 and I hope you’ll appreciate at least “one dish” from the menu. I’ll see you next time, have a great day 👋

--

--

Andrea Giammarchi

Web, Mobile, IoT, and all JS things since 00's. Formerly JS engineer at @nokia, @facebook, @twitter.