Практическое руководство по миграции Next.js проекта на Bun 1.2, сборке в production и созданию оптимального Docker-образа. Примерное время выполнения: 60–120 минут в зависимости от размера проекта.
Что вы изучите
Как установить Bun 1.2 (релиз 2026) и запустить Next.js приложение под Bun.
Пошаговая миграция скриптов и зависимости с Node.js на Bun с примерами команд и выводом.
Сборка production-версии и типичные ошибки сборки у плагинов, использующих нативные аддоны.
Создание компактного Docker-образа для Bun и сравнение размера с Node.js 20/24 образами.
Примеры CI (GitHub Actions), мониторинга и отката после перехода.
Требования
Операционная система: Linux x86_64 (Ubuntu 22.04 / 24.04) или macOS 13+. Поддержка Alpine возможна в Docker.
Bun 1.2 (релиз 2026). Размер бинарника ~12 МБ при распаковке в контейнере; runtime быстрый startup.
Node.js 20 (LTS 2023) или Node.js 24 (релиз 2024) для сравнения и совместимости; npm/yarn/pnpm по выбору.
Docker Engine 24.x, минимум 2 CPU и 4 ГБ RAM для сборки; для локальной разработки 2 ГБ достаточно.
Порты: стандартный Next.js порт 3000, рекомендуемый production порт 8080 при деплое в Docker.
Обзор Bun 1.2
0
Статья была полезной?
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…
Bun 1.2 (релиз 2026) — runtime JavaScript/TypeScript с интегрированным бандлером, менеджером пакетов и тестовым рантаймом. Основные изменения версии 1.2: улучшенная совместимость с Node.js API, ускорённый SSR (cold start сокращён на 30–50% в типичных Next.js приложениях), встроенная поддержка TypeScript без промежуточной трансляции и сниженное потребление памяти при старте сервера. Размер исполняемого образа Bun в базовом Docker-контейнере обычно 40–90 МБ в зависимости от слоя ОС; сам бинарник ~12 МБ.
Ключевые отличия от Node.js 20/24 (по состоянию на 2025–2026): Bun объединяет менеджер пакетов и рантайм, что сокращает время установки зависимостей (bun install обычно 2–5× быстрее), тогда как Node.js остаётся более совместимым с экосистемой нативных аддонов (npm-аддоны с C++). Производительность при SSR у Bun 1.2 оценивается в 1.3–2× по latency на простых страницах Next.js, но результаты зависят от используемых плагинов и нативных модулей.
Сравнение времени cold start Bun 1.2 и Node.js 24
Шаг 1: миграция проекта
Цель шага — запустить существующий Next.js проект под Bun 1.2 без крупных изменений кода. В примерах ниже используется Next.js 14 (релиз 2025) и package.json со скриптами dev, build, start.
# 1) Установка Bun 1.2 (Linux/macOS)
curl -fsSL https://bun.sh/install | bash
# или явный инсталлятор для релиза 1.2
Ожидаемый вывод:
Installing Bun v1.2.0...
Adding bun to PATH in ~/.bashrc
bun: installed to ~/.bun/bin/bun
Run 'bun --version' to verify.
Типичная ошибка и фикс:
Ошибка: "bash: bun: command not found"
Фикс: добавьте в профиль PATH: export PATH="$HOME/.bun/bin:$PATH" и перезапустите терминал.
Далее — в корне проекта замените установку зависимостей на Bun и выполните установку:
# Переключение package manager
bun install
Ожидаемый вывод (сокращённо):
Installing dependencies using bun...
Resolved 212 packages
Completed in 1.8s
Типичные ошибки и фиксы:
Ошибка: "package requires a peer of ..." или "Unsupported engine"
Фикс: проверьте package.json, добавьте нужные peerDependencies или временно установите "--force" и фиксируйте несовместимости по одному пакету.
Ошибка: "module not found: fs/promises" при старте dev
Фикс: Bun 1.2 пытается поддерживать node:fs, но в отдельных окружениях нужно явно использовать "import fs from 'fs'" или проверить target Node API. При необходимости запустите dev через Node.js для отладки отдельных модулей.
# Запуск dev сервера
bun run dev
Ожидаемый вывод:
ready - started server on http://localhost:3000
info - using build directory ".next"
compiled successfully - 12 modules
Если приложение стартовало — миграция базовой части прошла успешно. Если нет — см. раздел совместимости ниже.
Шаг 2: production build
Сборка production под Bun отличается в основном в части запуска скриптов. Мы оставляем тот же script build в package.json ("next build"). Выполните:
# Сборка production
bun run build
Ожидаемый вывод:
Using Next.js 14
info - Creating an optimized production build
info - Generating static pages (12/12)
Compiled successfully: 8.4s
Типичная ошибка и решение:
Ошибка: "Error: Cannot find module 'sharp'" или "node-gyp rebuild failed"
Контекст: пакет использует нативные аддоны (например, sharp для оптимизации картинок).
Фикс: два варианта:
1) Установите бинарную версию пакета, совместимую с Bun (если есть).
2) Выполните сборку на Node.js runner и затем деплойте артефакты (next/.next) в контейнер с Bun.
3) Используйте внешние сервисы для обработки изображений (например, Image CDN) и замените sharp на облачный сервис.
После успешной сборки запустите production сервер:
# В package.json: "start": "next start -p 8080"
bun run start
Ожидаемый вывод:
ready - started server on http://localhost:8080
info - Production build served
Типичная ошибка и её фикс:
Ошибка: "EADDRINUSE: address already in use 0.0.0.0:8080"
Фикс: проверьте процессы: sudo lsof -i :8080 && sudo kill , или измените порт в конфигурации и переменных окружения.
Шаг 3: Docker-образ
Создадим компактный multi-stage Dockerfile для Bun 1.2, собирающий приложение и упаковующий артефакты. Основной образ — oven/bun:1.2 (официальный репозиторий bun/oven). Если требуется Alpine, учтите дополнительные шаги по совместимости нативных библиотек.
# Dockerfile (production)
FROM oven/bun:1.2 AS builder
WORKDIR /app
COPY . .
RUN bun install --production=false
RUN bun run build
FROM oven/bun:1.2
WORKDIR /app
COPY --from=builder /app/.next .next
COPY --from=builder /app/public ./public
COPY --from=builder /app/package.json ./package.json
RUN bun install --production=true
ENV PORT=8080
EXPOSE 8080
CMD ["bun", "run", "start"]
Сборка образа и его размер:
# Сборка
time docker build -t myapp:bun-1.2 .
# Ожидаемый вывод (округлённый):
Sending build context to Docker daemon 12.3MB
Step ...
Successfully built Successfully tagged myapp:bun-1.2
# Размер итогового образа:
docker images myapp:bun-1.2
# SIZE ~80-140MB (зависит от слоёв и базовой ОС)
Для сравнения Node.js образ с node:20-slim чаще весит ~200–350 МБ со всеми слоями и node_modules. В примерах реально наблюдаемая экономия места — 30–60%.
Типичные ошибки при билде Docker и их фиксы:
Ошибка: "failed to solve: executor failed running ..." или "no matching manifest for linux/arm64"
Фикс: проверьте архитектуру хоста и используемый базовый образ. Для Apple M1/M2 используйте multi-arch образы или сборку с --platform=linux/amd64, либо выберите bun образ с поддержкой arm64.
Ошибка: "libstdc++.so.6: cannot open shared object file" при использовании нативных модулей
Фикс: установите дополнительные системные пакеты в слое builder (apt-get update && apt-get install -y build-essential libstdc++6) или соберите на образе соответствующей ОС и затем копируйте артефакты.
Скриншот вывода docker images с размерами образов Bun и Node.js
Шаг 4: CI/CD — GitHub Actions для Bun
Пример workflow, который устанавливает Bun, выполняет установку зависимостей, тесты и сборку. Используем runner ubuntu-22.04.
name: CI Bun
on: [push]
jobs:
build:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- name: Install bun
run: curl -fsSL https://bun.sh/install | bash && echo "::add-path::$HOME/.bun/bin"
- name: Install deps
run: bun install
- name: Run tests
run: bun test
- name: Build
run: bun run build
Ожидаемый вывод в логах Actions:
Installing Bun v1.2.0...
Completed in 2s
Installing dependencies using bun...
Completed in 1.6s
Running tests...
All tests passed
Build completed successfully
Типичная ошибка и её решение:
Ошибка: "Permission denied" при установке bun в runner
Фикс: используйте curl installer без sudo и добавьте путь в PATH через echo "PATH=$HOME/.bun/bin:$PATH" >> $GITHUB_ENV.
Ошибка: "tests fail only in CI" — часто вызвана различием в node-API или окружении
Фикс: воспроизведите локально с теми же переменными окружения, добавьте логирование и используйте тот же базовый образ runner (ubuntu-22.04).
Шаг 5: мониторинг, откат и runtime-операции
После деплоя важно обеспечить мониторинг и быстрый откат в случае регрессии. Для Bun-приложений используйте стандартные инструменты: Prometheus + Grafana для метрик, логирование в Loki или внешние APM (Sentry, Datadog). Ниже — пример systemd unit для запуска приложения на сервере с Bun.
Ошибка: "Unit myapp.service failed to load: No such file or directory"
Фикс: проверьте путь к файлу сервиса и права; выполните daemon-reload.
Ошибка: "Permission denied" при запуске bun через systemd
Фикс: убедитесь, что bun доступен для пользователя (путь в ExecStart абсолютный), проверьте права на директорию и библиотеке.
Откат: если зафиксирована регрессия производительности, быстрый откат — запустить контейнер с Node.js образа на предыдущей версии артефакта или вернуть тег образа в orchestration (Kubernetes Deployment rollback или Docker Swarm rollback). Держите резервный pipeline на Node.js для бесшовного переключения.
Есть ли смысл переходить?
Решение о миграции зависит от нескольких измеримых факторов: уменьшение времени cold start, размер образа в Docker, совместимость зависимостей и операционные риски. Примеры критериев для перехода:
Вы наблюдаете 20–50% выигрыш по latency и время старта критично для UX (edge/SSR heavy application).
Ваша команда готова поддерживать двухстороннюю совместимость и обработку проблем с нативными модулями.
Контейнерный размер и скорость развертывания — приоритет (экономия сетевого трафика и хранения образов).
Если проект интенсивно использует нативные аддоны (sharp, some database drivers с C++), переход может потребовать долгой работы по адаптации. Для сервисов, где критичны максимальная совместимость npm-экосистемы и нативных библиотек, целесообразно оставаться на Node.js 20/24 и частично использовать Bun в задачах CI или для некоторых micro-frontends.
Что с совместимостью?
Совместимость — главный вопрос для Next.js проектов. Bun 1.2 улучшил реализацию Node API, но остаются кейсы несовместимости:
Нативные аддоны (node-gyp, prebuild) — требуют либо совместимых бинарных сборок под Bun, либо сборки на Node.js и перенос артефактов.
Пакеты, ожидающие специфичные поведенческие детали Node.js (streams, некоторые process-методы) — возможны тонкие различия в реализации.
Инструменты сборки плагинов Next.js, которые напрямую обращаются к internals Next.js — могут требовать патчей или обновления плагинов.
Как оценить совместимость по шагам:
Запустите bun install и bun run dev локально. Фиксируйте все ошибки зависимостей и плагинов.
Автоматически тестируйте unit/integration тесты в CI на bun и node; сравнивайте результаты и latency метрики.
Для пакетов с нативными аддонами принимайте стратегию: использовать cloud-прослойку, заменить пакет или собирать на Node.js и деплоить как бинарные артефакты.
При планировании миграции документируйте для каждой зависимости уровень риска: low (чистый JS), medium (WASM или optional native), high (обязательные native add-ons). Это ускорит принятие решения и уменьшит время отката.
Дополнительные материалы и примеры по деплою и оптимизации находятся в разделах DevOps и JavaScript на сайте.
Частые вопросы
Какой выигрыш в производительности даст Bun 1.2 для Next.js?
В типичных случаях миграция на Bun 1.2 даёт сокращение cold start времени и уменьшение latency при SSR на 20–50% в зависимости от контента страницы и количества используемых плагинов. Это достигается за счёт более быстрого старта рантайма и интегрированного оптимизирующего бандлера. При этом реальные метрики зависят от IO, внешних сервисов и наличия нативных аддонов: если большая часть времени уходит на database queries или внешние API, выигрыш будет меньше. Всегда проводите A/B тестирование и нагрузочное тестирование перед миграцией в production.
Что делать с пакетами, которые используют нативные аддоны (node-gyp)?
Пакеты с нативными аддонами требуют отдельной стратегии. Возможные решения: 1) заменить пакет на чисто-JS или WASM-версию; 2) собирать нативные аддоны в отдельном этапе на Node.js и переносить артефакты в Bun-образ; 3) держать критические сервисы на Node.js, а фронтенд/SSR на Bun. Часто целесообразно комбинировать варианты: сохранять compatibility build pipeline на Node.js и экспериментировать с Bun для новых сервисов.
Зачем сохранять образ на Node.js после перехода на Bun?
Резервный Node.js образ нужен для быстрого отката и для сценариев, когда определённые интеграции или CI-этапы ещё несовместимы с Bun. Поддержка двух pipeline (Bun и Node.js) минимально увеличивает сложность, но даёт операционную гибкость: вы сможете переключиться на проверенный образ, если обнаружится критическая несовместимость или регрессия производительности после развертывания.
Как оценить экономию на размерах Docker-образов и сетевом трафике?
Измерения зависят от конкретного проекта, но в практике миграции Next.js на Bun уменьшение итогового образа обычно 30–60% по сравнению с node:20-slim при одинаковом наборе зависимостей, особенно если не требуется сборка нативных модулей. Это ведёт к уменьшению времени загрузки образов в CI/CD и экономии места в реестре. Для точной оценки выполните сравнение: соберите два образа (Bun и Node.js) одинаковыми шагами и сравните вывод docker images --format '{{.Repository}} {{.Size}}'.
Когда не стоит переходить на Bun?
Не стоит мигрировать, если проект критично зависит от нативных npm-модулей без обходных путей, отсутствует команда для оперативной поддержки возможных багов рантайма, или если организация требует стопроцентной совместимости с Node.js из-за политик безопасности и сертификаций. В таких случаях выгоднее следить за развитием Bun и применять его в новых небольших сервисах или для экспериментов.
Комментарии (0)
Войдите или зарегистрируйтесь, чтобы оставить комментарий
Загрузка комментариев…