Bun знову виріс — тепер із вбудованим планувальником

Bun v1.3.11 вийшов 18 березня 2026, і головна фішка — Bun.cron. Це вбудований API для реєстрації cron-задач прямо на рівні операційної системи. Більше не треба вручну редагувати crontab або городити обгортки над сторонніми бібліотеками — Bun робить це за вас, причому однаково на Linux, macOS і Windows.

Крім того: бінарник став на 4 MB легшим, з’явився Bun.sliceAnsi для коректної нарізки рядків із кольоровими кодами терміналу, і підтюнили роботу з rest-синтаксисом.

Що було не так із cron у JS-екосистемі

Планування задач у Node.js-світі — це завжди компроміс:

Ідея Bun.cron інша: описуєш задачу в коді → Bun реєструє її в планувальнику ОС → задача працює навіть після того, як Bun-процес завершиться.

Bun.cron: як це працює

Реєстрація задачі

// register-jobs.ts
Bun.cron("./scripts/cleanup-logs.ts", "0 3 * * *", "cleanup-logs");

Три аргументи:

  1. Шлях до скрипта — який файл запускати.
  2. Cron-вираз — коли запускати. У прикладі 0 3 * * * означає «щодня о 3:00 ночі».
  3. Назва — ідентифікатор задачі, щоб потім її можна було знайти або видалити.

Після виконання Bun створить запис у системному планувальнику:

Валідація cron-виразів

const result = Bun.cron.parse("*/15 * * * *");
console.log(result);
// { minute: "*/15", hour: "*", dayOfMonth: "*", month: "*", dayOfWeek: "*" }

// А якщо вираз некоректний:
try {
  Bun.cron.parse("banana * * *");
} catch (e) {
  console.error("Невалідний cron-вираз:", e.message);
}

Bun.cron.parse() перевіряє вираз перед реєстрацією. Особливо корисно, якщо розклад приходить від користувачів або з конфігу — краще зловити помилку одразу, ніж дізнатися про неї о 3:00 ночі.

Видалення задачі

Bun.cron.remove("cleanup-logs");

Видаляє задачу з планувальника ОС за назвою. Чисто і передбачувано.

Приклад: реєстрація кількох задач

// setup-cron.ts — реєструємо три задачі одним скриптом
const jobs = [
  { script: "./jobs/db-backup.ts",     cron: "0 2 * * *",    name: "db-backup" },
  { script: "./jobs/send-digest.ts",   cron: "0 8 * * 1",    name: "weekly-digest" },
  { script: "./jobs/cleanup-temp.ts",  cron: "*/30 * * * *", name: "temp-cleanup" },
];

for (const job of jobs) {
  // Спочатку перевіряємо, чи коректний cron-вираз
  Bun.cron.parse(job.cron);
  // Якщо все ок — реєструємо в ОС
  Bun.cron(job.script, job.cron, job.name);
  console.log(`✅ Зареєстровано: ${job.name} (${job.cron})`);
}

У цьому прикладі: бекап бази кожну ніч о 2:00, дайджест щопонеділка о 8:00, очистка тимчасових файлів кожні 30 хвилин.

Сумісність із Cloudflare Workers

API спроєктований сумісно з Cloudflare Workers Cron Triggers. Це означає: якщо ви пишете задачу для локального Bun і потім хочете перенести її в хмару — зміни в коді будуть мінімальними. Один код, два середовища.

Бінарник на 4 MB менший

Команда Bun прибрала CMake зі свого білд-процесу. Результат: виконуваний файл Bun для Linux x64 зменшився на 4 мегабайти.

Здавалося б — 4 MB, і що? Але у контексті Docker-контейнерів і edge-серверів кожен мегабайт рахується. Менший бінарник = швидше завантаження Docker-образу, менший cold start, менший об’єм на IoT-пристроях.

Це не та фіча, заради якої ви оновите Bun. Але це показник інженерної культури: команда оптимізує не тільки runtime, а й процес збірки самого runtime.

Bun.sliceAnsi: нарізка рядків для CLI

Якщо ви будуєте CLI-інструменти, ви знаєте біль: рядок у терміналі — це не просто текст. Це суміш видимих символів, ANSI escape-послідовностей і grapheme clusters.

Стандартний String.prototype.slice() ріже по кодпоінтах і ламає і кольорові коди, і емодзі. Bun.sliceAnsi вирішує це:

import { sliceAnsi } from "bun";

const colored = "\x1b[31mHello\x1b[0m 🌍 World";

// Стандартний slice зламає кольорові коди:
console.log(colored.slice(0, 10)); // Каша з невидимих escape-кодів

// Bun.sliceAnsi враховує видиму ширину:
console.log(sliceAnsi(colored, 0, 5)); // "Hello" (червоний, з правильним закриттям ANSI)

Ідеальний варіант для:

Покращення rest-синтаксису

Bun v1.3.11 оптимізував внутрішню обробку rest-синтаксису. Це не нова фіча, а покращення продуктивності: операції з ... стали швидшими і використовують менше пам’яті.

// Ці патерни тепер працюють ефективніше:
const [first, ...rest] = largeArray;
const { id, ...metadata } = bigObject;
function log(message: string, ...args: unknown[]) { /* ... */ }

Якщо ваш код активно використовує деструктуризацію з rest — ви отримаєте безкоштовний приріст продуктивності після оновлення.

Антипатерни: чого не робити

❌ Реєструвати cron-задачі без валідації

// Погано: якщо вираз невалідний, дізнаєтеся тільки коли задача мала б запуститися
Bun.cron(script, userInput, name);

// Добре: перевіряй перед реєстрацією
Bun.cron.parse(userInput); // кине помилку, якщо вираз некоректний
Bun.cron(script, userInput, name);

❌ Дублювати назви задач

Якщо зареєструвати дві задачі з однаковою назвою — одна перезапише іншу без попередження. Використовуйте унікальні, описові назви.

❌ Плутати Bun.cron з таймерами всередині процесу

Bun.cron реєструє задачу в ОС — вона запускається як окремий процес за розкладом. Якщо вам потрібен таймер всередині тривалого процесу (наприклад, оновлення кешу кожні 30 секунд) — використовуйте setInterval або Bun.sleep, а не Bun.cron. Cron — для задач, які мають пережити зупинку вашого застосунку.

❌ Забувати про cleanup

Якщо ви перестали використовувати задачу — видаліть її через Bun.cron.remove(). Інакше вона залишиться в системному планувальнику і працюватиме навіть після видалення самого коду. Класична «задача-привид».

Що робити далі

  1. Оновити Bun: bun upgrade — перевірте, що у вас v1.3.11 або новіша.
  2. Інвентаризація задач: перегляньте, що зараз живе в crontab -l або відповідних планувальниках. Які задачі варто перенести на Bun.cron?
  3. Пілотна міграція: візьміть одну некритичну задачу, перепишіть на Bun.cron, перевірте, що вона з’явилась у системному планувальнику.
  4. CLI-інструменти: якщо у вас є CLI на Bun з кольоровим виводом — спробуйте Bun.sliceAnsi замість кастомних рішень.
  5. Перевірте продуктивність: якщо у вас є гарячі ділянки коду з активною деструктуризацією — порівняйте швидкість до й після оновлення.

Джерела: