Skip to content

Instantly share code, notes, and snippets.

@guest271314
Last active November 8, 2024 18:30
Show Gist options
  • Save guest271314/da04334bb0dce19fcd970415bb003b02 to your computer and use it in GitHub Desktop.
Save guest271314/da04334bb0dce19fcd970415bb003b02 to your computer and use it in GitHub Desktop.
Why I use node, deno, bun, qjs, tjs at the same time

Why I use node, deno, bun, qjs, tjs at the same time.

Winds up being a (not the) rather comprehensive JavaScript toolbox. The idea being for the modern JavaScript programmer can use all of the tools available for a given requirement, task or job, without preference for any. No external bundlers or compilers are needed. No frameworks are needed. I can use qjs or tjs for systems with minimal RAM and disk space; and when I want to use Web API's deno makes an effort to provide those interfaces. In some cases I can run the exact same code in bun, deno, and node, which provides a means to perform 1:1 testing as to performance.

There's probably a few things I am unintentionally omitting below. These are just a brief synposis. I'll update accordingly.

node (v22 100 MB executable)

  • Reasonable stability
  • Full-duplex streaming supported for WHATWG fetch()
  • CommonJS supported by default
  • Capability to create single executable application from CommonJS source code

deno (v1.41.3 135 MB executable)

  • fmt to format .js and .json files
  • vendor with --vendor=true to fetch NPM modules and reate node_modules folder
  • Import maps supported
  • file: protocol supported for WHATWG fetch()
  • Full-duplex streaming supported for fetch()
  • WHATWG Fetch and Streams supported in servers
  • Built-in WebSocket server
  • Network imports supported by default
  • Capability to bundle dependencies to a single file with bundle (until 2.0)
  • Capability to compile dependencies to a standalone executable with compile - since recently using denort executables are approximately half the size of deno executable at around 78 MB.
  • TypeScript support
  • Web API implementations
  • Ecmascript modules supported by default
  • No extraneous files and folders included with the runtime - just the runtime
  • No package.json file expected or necessary
  • deno upgrade built in
  • No external package manager

bun (v1.0.35 90 MB executable)

  • Built-in package manager, including writing GitHub repositories - bun install creates node_modules folder
  • Faster than node and deno for reading STDIN and writing to STDOUT
  • Capability to bundle CommonJS and/or Ecmascript dependencies to a single file with build
  • Capability to compile dependencies to a standalone executable with build
  • TypeScript support
  • CommonJS and Ecmascript module support - in the same file if necessary
  • Simple to delete cached dependencies with pm cache rm
  • file: protocol supported for WHATWG fetch()
  • Ecmascript modules supported by default
  • No extraneous files and folders included with the runtime - just the runtime
  • No package.json necessary
  • bun upgrade built in
  • No external package manager
  • bun build --minify to minify files

tjs (v23.12.0 5.7 MB executable)

  • Embeddable
  • Supports TCP and Unix sockets
  • Capability to import C shared library as Ecmascript module
  • libuv
  • WebAssembly support

qjs (v0.4.1 1.2 MB executable (QuickJS-ng ))

  • Embeddable
  • Faster than node, deno, bun, tjs for reading STDIN, writing to STDOUT
  • Capable of reading 1 MB from STDIN in one read
  • Capability to import C shared library as Ecmascript module
  • Compilable to WASM

Caveats

node

  • Ecmascript modules not supported by default; requires --experimental-deafult-type=module or --experimental-detect-module
  • Does not support file: protocol for Undici's WHATWG fetch() implementation
  • Import maps not supported - have to use loader/hooks interface to intercept specifiers/imports
  • API's primarily callback-based
  • No built-in WebSocket server
  • Internal node:crypto implementation can't be polyfilled, is incompatible with Web Cruptography API that we can get to at import { webcrypto } from node:crypto
  • Extraneous folders and files (e.g., node_modules, npm, npx) included in the archive besides just the runtime executable node
  • Generally expects a package.json file and node_modules folder on the system
  • Flag necessary for network imports
  • Capability to create single executable application from only CommonJS source code

deno

  • Dynamic import("./exports".js) is not dynamic when bare string specifiers are used; trying to import("./exports.js") a script created in the script will throw - unless something like "" + "./exports" or const exports = "./exports.js"; import(exports) is used
  • Won't automatically write GitHub repository dependencies to created node_modules folder
  • No built-in way to delete cached dependencies
  • fmt can panic and freeze the entire system depending on the file size
  • vendor can panic when fetching raw file from GitHub and trying to output to a node_modules folder

bun

  • Full-duplex streaming not supported in fetch() implementation
  • HTTP/2 not supported
  • Import maps not supported - have to use plugin interface to intercept specifiers/imports

tjs

  • WHATWG Streams implementation is not full-duplex; a polyfill is currently used
  • No built-in HTTP(S) server
  • Full-duplex streaming not supported in fetch() implementation

qjs

  • Web API's generally not supported
  • No WHATWG Streams
  • No WHATWG Fetch
  • No built-in HTTP(S) server
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment