Если тебя когда-нибудь раздражало, что простое десктопное приложение на JS тянет за собой полноценный Electron с гигабайтом зависимостей — Blue предлагает радикально другой путь.
Как это работает
Blue использует два режима выполнения кода, которые могут сосуществовать в одном бинарнике.
AOT-компиляция
Твой JS-файл прогоняется через Babel, понижается до AST, транслируется в C++ и компилируется в нативный исполняемый файл — без интерпретатора в рантайме. Поддерживаются классы, замыкания, прототипное наследование, деструктуризация, шаблонные строки, полный набор методов массивов, строк и объектов.
АОТ-режим — для нативных окон, файловой системы, бизнес-логики и горячих циклов.
// src/main.js — компилируется в C++
var notes = require("fs").readdirSync("./notes");
var file = Blue.Dialog.showOpenDialog("Open", "*.md", false);
Blue.Window.setTitle("Notes - " + notes.length + " files");
window.open("<h1>My App</h1>", "Notes", 900, 600);
QuickJS island
Опциональный встроенный движок QuickJS добавляет поддержку ES2020+, async/await и npm-пакетов (через esbuild) — всё это упаковывается в тот же бинарник. Два контекста общаются через лёгкий мост: Blue.callAot() и Blue.callIsland().
Остров удобен для HTTP-серверов, динамической логики и npm-пакетов.
// src/island.js — работает во встроенном QuickJS
const http = require("http");
const server = http.createServer((req, res) => {
var note = Blue.callAot("getNote", req.url.slice(1));
res.writeHead(200, { "content-type": "text/html" });
res.end(note);
});
server.listen(3000);
Нативные API
Blue предоставляет несколько встроенных пространств имён:
Blue.Window—setTitle(),setSize(),center(),minimize()/maximize(),setFrameless(),close()Blue.Dialog—showOpenDialog(),showSaveDialog(),showMessageBox()Blue.Clipboard—readText(),writeText()Blue.Process—exec(cmd)→{ code, stdout, stderr }
Что работает в острове
- Чистые JS-утилиты и UI-фреймворки (для генерации бандла)
- Базовые HTTP-роутеры,
async/await, ES2020+ - Node built-ins:
fs,path,os,http
Что не работает
- Нативные аддоны (
.node-файлы) worker_threads,child_process- Пакеты, завязанные на Node.js internals
crypto.subtle, WebSockets — частичная поддержкаeval/new Function(str)в рантайме
Остров запускает QuickJS, а не Node.js. Совместимость с npm варьируется — тестируй свои пакеты до релиза.
Для отладки AOT-кода: blue --print-c file.js выведет сгенерированный C++.
Бенчмарки против Node.js
| Метрика | Blue | Node.js v18 |
|---|---|---|
| Время старта | ~1 мс | ~108 мс |
| Пик RSS (hello world) | 3.8 МБ | 48.5 МБ |
| Размер бинарника (hello world) | 60 КБ | — |
| Runtime-зависимости | 0 | есть |
Сам сайт bluejs.dev раздаётся Blue-бинарником весом 2.2 МБ — HTML и HTTP в одном исполняемом файле 🦆
Быстрый старт
curl -fsSL install.sh | bash
Самый простой пример — GTK-окно из одной строки:
echo 'window.open("<h1>Hello from Blue</h1>", "My App", 800, 500);' > hello.js
blue -compile hello.js -o hello
./hello
Для полноценного гибридного проекта (AOT + QuickJS island + встроенный HTML-фронтенд):
blue -init myapp
cd myapp
blue -build myapp -o myapp
./myapp
Примеры — на github.com/bluejs-team/Bluejs: от минималистичного hello-webview до React-фронтенда, встроенного в бинарник через esbuild.

