A few failed attempts at speeding up the Ink.js start-time.

I wanted to try something that combined [react-table], [ink] & maybe notion or airtable. Ink is pretty cool, it's used by a bunch of open source JS tools & it lets you write JSX in command line tools. A simple example like this:

import React from 'react';

import Table from 'ink-table'
import { render, Text } from 'ink'

const data = [
  {
    name: 'Cool',
    age: 30,
  },
  {
    name: 'Dean',
    age: 80,
  },
]

console.log("data", data)

render(<Text>hmmm</Text>)

const Basic = () => <Table data={data} />

render(<Basic />)

will output:

yarn node dist/index.js
data [ { name: 'Cool', age: 30 }, { name: 'Dean', age: 80 } ]
┌──────┬─────┐
│ name │ age │
├──────┼─────┤
│ Cool │ 30  │
├──────┼─────┤
│ Dean │ 80  │
└──────┴─────┘
✨  Done in 0.58s.

That Done in 0.58s is a little rough though, it's noticeable on something as small as this. There's a noticeable delay between the boot and the output.

It could be that this is just better for tools that are going to take longer than a second to run - it's very popular with code generators & test runners & dev servers, and in all of those you expect a tiny bit of warmup before the process starts in earnest.

I ended up getting sidetracked by this.

I tried to see if yarn was causing it time node dist/index.js was generally a bit faster, more like ~0.45. (The production builds are about ~0.40) That's better but it still feels noticable. And for a baseline - simply logging data was about 0.10s, which is more like what I'd like to see.

I tried a few things to get a faster execution time. They did not work, for reasons that are mildly interesting.

Deno

First, I tried deno. Maybe it can stitch things together better then node can?

I used skypack.dev - which is like unpkg, - it serves ESModules, but it's a little easier to use (because they're trying to make it a business & can spend more time developing it)

The code is basically the same, except instead of importing from local modules, we import from skypack (and Deno downloads what it needs and caches things locally):

import React from 'https://cdn.skypack.dev/react';
import Table from 'https://cdn.skypack.dev/ink-table';
import { render, Text } from 'https://cdn.skypack.dev/ink';

this fails here:

deno run --unstable deno-ink-table.tsx
Download https://cdn.skypack.dev/yoga-layout-prebuilt
Check file:///Users/dan/code/js/deno-ink-trial/what.tsx
This browser doesn't support requestAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills
This browser doesn't support cancelAnimationFrame. Make sure that you load a polyfill in older browsers. https://reactjs.org/link/react-polyfills
error: Uncaught ReferenceError: _a is not defined
    at https://cdn.skypack.dev/-/yoga-layout-prebuilt@v1.10.0-mJ9p46YRzJqOsUifqeTZ/dist=es2019,mode=imports/optimized/yoga-layout-prebuilt.js:4396:10
    at https://cdn.skypack.dev/-/yoga-layout-prebuilt@v1.10.0-mJ9p46YRzJqOsUifqeTZ/dist=es2019,mode=imports/optimized/yoga-layout-prebuilt.js:5373:7
    at https://cdn.skypack.dev/-/yoga-layout-prebuilt@v1.10.0-mJ9p46YRzJqOsUifqeTZ/dist=es2019,mode=imports/optimized/yoga-layout-prebuilt.js:29620:1

So that package is 1) maintained by the maintainer of Ink[https://www.npmjs.com/package/yoga-layout-prebuilt]. 2) is a core dependency of Ink, used to and 3) wraps a compiled version of this very complicated looking cross-platform implementation of Flexbox. 4) it has an open ticket capturing the error but that ticket points to the upstream codebase and 5) It hasn't been updated in a year .. so it's possible that there's a fix already, or it's possible that there's a workaround.

I was feeling pretty stuck here, so I gave up for the moment. (Or forever!)

WASM???

Then, as a real longshot, I thought - "hey why not try compiling it to WASM? That might .. just .. make it fast ...... magically?" Well, that did not work.

I went through the steps to set up assemblyscript here. The default converts whatever you put in the assembly dir into wasm & writes it to build.

And I used wasmer which lets you run wasm in from the cli.

This is how you'd invoke a wasm script:

wasmer build/untouched.wasm

However I did one of those "try it out without reading the article":

Closures are not yet implemented. This is a feature they’re pretty much interested in having but considering it’s still not yet implemented, you have to be sure to not use any type of closures in your code.

So what have we learned from all this? It's hard to say. "Don't Rush", maybe?

I'd say:

  1. skypack is nice. I'm sure other things will come along, but it is well designed.
  2. Deno ... this is the second time I've tried to do something that loaded 3rd party packages & the second time I've had a hard time getting them to work. If it takes off, that might get easier as people start to accomodate it it, but I'm probably using it wrong & should try to write something that just uses Deno tools or just uses my own code.
  3. WASM .... I should try more of a walk don't run approach to learning about it.