txiki.js

Activity, over time

Daily observations from the public event archive.

Attention

Daily stars & forks

Loading attention chart

Star accumulation

Cumulative stars

Loading star accumulation chart

Pull requests

Daily opens & merges

Loading pull requests chart

Conversations

Daily issues & comments

Loading conversations chart

Community

Daily accounts & reviews

Loading community chart

Releases

Daily releases

Loading releases chart

Mentions

1post · 30d
Nov 30 posts
  1. Why I built a 6MB JavaScript runtime for embedded and IoT devices --- title: "Why I built a 6MB JavaScript runtime for embedded and IoT devices" published: true description: "xuan is a lightweight JavaScript runtime built on QuickJS, aimed at IoT and edge devices where Node.js is too heavy. Here's why it exists, how it works, and how to try it." tags: javascript, node, iot, embedded cover_image: raw.githubusercontent.com --- I love Node.js. It's why I can ship a backend in an afternoon. But I also write firmware and deal with edge hardware — OpenWrt routers, MIPS boards, small ARM gateways. And on that class of device, Node.js is often just too much: a 100 MB+ runtime, high memory use, and a cold start you can feel. So I built xuan (玄) — a lightweight JavaScript runtime for IoT and embedded devices. It's built on QuickJS and forked from tjs / txiki.js. It's MIT licensed and on GitHub here: **topelinux/xuan**. This post is about why it exists, how it's put together, and how to try it. The problem with "just use Node" On a server, none of Node's costs matter. On a $10 board with 64 MB of RAM, they all do: - Binary size — you don't want a 100 MB runtime on a device with a small flash partition. - Memory — resident memory is at a premium. - Startup — if your program runs occasionally (a cron-like sensor task, a request handler on a gateway), cold start dominates. I wanted to run JavaScript — and ideally a good chunk of the npm ecosystem — in that environment, with a runtime measured in single-digit megabytes. What xuan is xuan embeds QuickJS (a small, fast ES2020+ engine by Fabrice Bellard) and adds the pieces a real application needs: - a Node.js-compatible API layer (so many existing npm packages run with little or no change) - built-in IoT modules: MQTT, serial port, and FFI - standalone compilation: turn a script into a single self-contained binary - cross-compilation to x86, ARM, MIPS and RISC-V It's a fork of txiki.js, which already had an excellent QuickJS + Node-compat foundation. My focus is the IoT/embedded angle and the built-in device modules. Built-in modules, not npm-installed ones On constrained devices, pulling native modules at runtime is painful. So the ones you actually need are built in: - MQTT — publish/subscribe, the lingua franca of IoT - SerialPort — talk to MCUs and modems - FFI — call into C libraries directly, so you can reuse existing code - GPIO / I2C / SPI — in progress A minimal MQTT client looks like normal Node code: const mqtt = require('mqtt'); const client = mqtt.connect('mqtt://broker.emqx.io'); client.on('message', (topic, msg) => { console.log(topic, msg.toString()); }); client.on('connect', () => { client.subscribe('iot/device/001/#', { qos: 1 }); setInterval(() => { client.publish('iot/device/001/status', 'online', { qos: 1 }); }, 5000); }); And FFI lets you reach for C when you need to: import FFI from 'tjs:ffi'; const libc = new FFI.Lib(FFI.Lib.LIBC_NAME); const atoi = new FFI.CFunction(libc.symbol('atoi'), FFI.types.sint, [FFI.types.string]); console.log(atoi.call('123')); // 123 Standalone binaries with xuan compile You can also embed your app into the runtime and ship one file: ./build/xuan compile app.js myapp ./myapp # no Node.js, no runtime install required That's the deployment story I wanted for devices: build once on your machine, copy one binary onto the target. Rough numbers On a MacBook Air M1 (executable size and cold start only — this is not a resident-memory benchmark): | Runtime | Cold start (mean) | Binary size | |---------|-------------------|-------------| | xuan | 5.37 ms | 6.2 MB | | bun | 8.82 ms | 58 MB | | Node.js | 20.29 ms | 112 MB | *220 runs each, randomly interleaved, -e "0", wall-clock from process start to exit. Treat it as a rough data point, not a victory lap.* Those numbers are on a fast desktop CPU; the interesting part for embedded folks is the shape — a single-digit-megabyte runtime with millisecond startup. How it's put together ┌─────────────────────────────────────┐ │ xuan Runtime │ ├─────────────────────────────────────┤ │ Node.js Compatible API Layer │ ├─────────────────────────────────────┤ │ IoT Native Modules (MQTT/Serial/FFI)│ ├─────────────────────────────────────┤ │ QuickJS Engine │ ├─────────────────────────────────────┤ │ Embedded System (Linux/RTOS) │ └─────────────────────────────────────┘ JavaScript sources are bundled (esbuild) and compiled into C, then embedded into the binary. Local changes to the bundled dependencies (libwebsockets, QuickJS, libuv, mimalloc) are kept as patches and applied at build time, so a clean clone builds reproducibly. Build and run git clone https://github.com/topelinux/xuan.git cd xuan git submodule update --init --recursive --force npm install # esbuild etc. — needed before make make # -> ./build/xuan ./build/xuan run app.js What works, and what's next Working today: the Node-compat layer, MQTT, serial port, FFI, xuan compile, and cross-compilation. Next up: GPIO, I2C and SPI, plus widening Node API coverage. It's early, and I'd genuinely value feedback — especially from people shipping on constrained hardware. Which boards, which Node APIs, which device modules would you need first? - Repo: topelinux/xuan - License: MIT Credit where it's due: the foundation is txiki.js by Saúl Ibarra Corretgé, and the engine is QuickJS by Fabrice Bellard.

    2 reactions · 1 comment

Latest stargazers

The last 10 distinct accounts we observed this year.

Most active participants

PR, issue, comment & review events in the past year.

Packages

1
PackageVersionDownloads · 30dTrend · 30d
v26.6.0
≥368

README badges

Embed a badge in your README or website.

Live mentions · last 30 days
saghul/txiki.js mentions in the last 30 days