Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Деплой Nuxt приложений
nuxt_deployment

Деплой Nuxt приложений

SSR, SSG и гибридный деплой: Vercel, Netlify, Railway, Docker, Nginx, PM2 и CI/CD pipeline с GitHub Actions

Деплой Nuxt приложений

Деплой Nuxt — это выбор правильного режима рендеринга и платформы под ваши требования. SSR требует Node.js сервера, SSG работает на любом статическом хостинге, а гибридный режим через routeRules даёт максимальную гибкость.

#Режимы деплоя: SSR, SSG, Hybrid

SSR (Server-Side Rendering) — каждый запрос обрабатывается сервером. Нужен: Node.js или совместимая среда. Подходит для: динамического контента, аутентифицированных страниц, персонализации.

SSG (Static Site Generation) — все страницы генерируются при сборке. Нужен: любой статический хостинг (S3, Netlify, Vercel). Подходит для: блогов, документации, маркетинговых сайтов.

Hybrid — комбинация через routeRules. Часть страниц статическая, часть SSR, часть ISR. Максимальная гибкость при правильно настроенной платформе.

#nuxt build и nuxt generate

# SSR сборка — создаёт .output/ с сервером и клиентским кодом npx nuxt build # Запуск SSR сервера node .output/server/index.mjs # Сервер слушает на PORT (по умолчанию 3000) # SSG — генерирует статический HTML npx nuxt generate # Статические файлы в .output/public/ # Можно деплоить как обычные HTML/JS/CSS файлы

Структура .output/:

.output/
├── public/          # Статические файлы (CSS, JS, изображения)
│   ├── _nuxt/      # Клиентские JS чанки
│   └── index.html  # (только для SSG)
└── server/
    ├── index.mjs   # Точка входа Nitro сервера
    ├── chunks/     # Серверные чанки
    └── ...

#Переменные окружения: runtimeConfig

runtimeConfig разделяет переменные на серверные (секреты) и публичные:

// nuxt.config.ts export default defineNuxtConfig({ runtimeConfig: { // Только на сервере — НЕ попадают в клиентский бандл databaseUrl: process.env.DATABASE_URL, jwtSecret: process.env.JWT_SECRET, stripeSecretKey: process.env.STRIPE_SECRET_KEY, // Доступны везде — попадают в клиентский бандл public: { apiBase: process.env.NUXT_PUBLIC_API_BASE || '/api', siteUrl: process.env.NUXT_PUBLIC_SITE_URL || 'http://localhost:3000', stripePublicKey: process.env.STRIPE_PUBLIC_KEY } } })

Использование в коде:

// В server routes — доступны серверные переменные export default defineEventHandler((event) => { const config = useRuntimeConfig() const db = new Database(config.databaseUrl) return db.query() })
<script setup lang="ts"> // В компонентах — только public переменные const config = useRuntimeConfig() const apiBase = config.public.apiBase </script>

Для локальной разработки создайте .env:

DATABASE_URL=postgresql://user:pass@localhost:5432/mydb JWT_SECRET=your-super-secret-key-min-32-chars NUXT_PUBLIC_API_BASE=http://localhost:3000/api NUXT_PUBLIC_SITE_URL=http://localhost:3000

#Деплой на Vercel

Vercel автоматически определяет Nuxt проект и настраивает деплой. Дополнительный конфиг не нужен:

npm install -g vercel vercel # Первый деплой — интерактивная настройка vercel --prod # Деплой в production

Переменные окружения в Vercel UI: Settings → Environment Variables. Устанавливайте отдельно для Production, Preview и Development.

Для оптимального деплоя на Vercel добавьте preset:

// nuxt.config.ts export default defineNuxtConfig({ nitro: { preset: 'vercel-edge' // Edge Functions — быстрее чем Serverless // или 'vercel' для обычных Serverless Functions } })

Edge Functions работают глобально (CDN узлы), Serverless Functions — в одном регионе. Для ISR и динамического контента Edge Functions предпочтительнее.

Vercel Preview Deployments — каждый pull request получает свой URL. Это позволяет тестировать изменения до мержа в main.

#Деплой на Netlify

npm install @nuxtjs/netlify-edge
// nuxt.config.ts export default defineNuxtConfig({ modules: ['@nuxtjs/netlify-edge'], nitro: { preset: 'netlify-edge' } })

Конфигурация netlify.toml:

[build] command = "npm run build" publish = ".output/public" [build.environment] NODE_VERSION = "20" # Перенаправление для SPA (если нужно) [[redirects]] from = "/*" to = "/.netlify/functions/server" status = 200

Netlify Edge Functions используют Deno runtime — убедитесь что ваши зависимости совместимы.

#Деплой на Railway

Railway поддерживает деплой через Dockerfile или авто-определение через Nixpacks:

Без Dockerfile Railway автоматически:

  1. Определяет Node.js проект
  2. Запускает npm install && npm run build
  3. Запускает node .output/server/index.mjs

Укажите PORT переменную — Railway динамически назначает порт:

# В переменных Railway (Settings → Variables) PORT=3000 NODE_ENV=production DATABASE_URL=postgresql://...

С PORT Nuxt/Nitro автоматически слушает на правильном порту.

Health check endpoint для Railway:

// server/api/health.get.ts export default defineEventHandler(async (event) => { try { // Проверяем что БД доступна await db.$queryRaw`SELECT 1` return { status: 'ok', timestamp: new Date().toISOString() } } catch (error) { setResponseStatus(event, 503) return { status: 'error', message: 'Database unavailable' } } })

В настройках Railway укажите /api/health как health check path.

#Docker: многоэтапная сборка

Многоэтапный Dockerfile минимизирует размер финального образа:

# Stage 1: Сборка FROM node:20-alpine AS builder WORKDIR /app # Копируем манифесты зависимостей COPY package*.json ./ RUN npm ci # Копируем исходный код COPY . . # Сборка Nuxt RUN npm run build # Stage 2: Production образ FROM node:20-alpine AS runner WORKDIR /app # Только production зависимости (если .output содержит node_modules) # В большинстве случаев Nitro bundling не требует node_modules в production COPY --from=builder /app/.output /app/.output # Переменные окружения ENV NODE_ENV=production ENV PORT=3000 EXPOSE 3000 # Запуск Nitro сервера CMD ["node", "/app/.output/server/index.mjs"]

Сборка и запуск:

docker build -t my-nuxt-app . docker run -p 3000:3000 \ -e DATABASE_URL=postgresql://... \ -e JWT_SECRET=... \ my-nuxt-app

#docker-compose для локальной разработки

# docker-compose.yml version: '3.8' services: app: build: . ports: - "3000:3000" environment: - DATABASE_URL=postgresql://postgres:password@db:5432/mydb - REDIS_URL=redis://redis:6379 depends_on: db: condition: service_healthy redis: condition: service_started restart: unless-stopped db: image: postgres:16-alpine environment: POSTGRES_DB: mydb POSTGRES_USER: postgres POSTGRES_PASSWORD: password volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 redis: image: redis:7-alpine command: redis-server --appendonly yes volumes: - redis_data:/data volumes: postgres_data: redis_data:

#Nginx как reverse proxy

Nginx проксирует запросы к Nuxt, обрабатывает SSL, отдаёт статику напрямую:

# /etc/nginx/sites-available/myapp server { listen 80; server_name myapp.com www.myapp.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; server_name myapp.com www.myapp.com; ssl_certificate /etc/letsencrypt/live/myapp.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/myapp.com/privkey.pem; # Gzip сжатие gzip on; gzip_types text/plain text/css application/json application/javascript; gzip_min_length 1000; # Статические файлы из .output/public отдаём напрямую location /_nuxt/ { root /app/.output/public; expires 1y; add_header Cache-Control "public, immutable"; } # Всё остальное — проксируем к Nuxt location / { proxy_pass http://localhost:3000; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_cache_bypass $http_upgrade; } }

#PM2: управление процессом Node.js

PM2 перезапускает приложение при краше, поддерживает cluster mode:

npm install -g pm2
// ecosystem.config.js module.exports = { apps: [{ name: 'nuxt-app', script: '.output/server/index.mjs', instances: 'max', // Кластер: по числу CPU ядер exec_mode: 'cluster', // Балансировка нагрузки между инстансами env: { NODE_ENV: 'production', PORT: 3000 }, // Автоматический перезапуск при утечке памяти max_memory_restart: '512M', // Логирование log_file: '/var/log/myapp/combined.log', error_file: '/var/log/myapp/error.log', out_file: '/var/log/myapp/out.log' }] }
pm2 start ecosystem.config.js pm2 save # Сохраняем конфигурацию pm2 startup # Автозапуск при перезагрузке системы

#CI/CD: GitHub Actions pipeline

Полный pipeline: тесты → сборка → деплой:

# .github/workflows/deploy.yml name: Deploy to Production on: push: branches: [main] jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm' - run: npm ci - run: npm run test:run deploy: needs: test runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Build Docker image run: docker build -t myapp:${{ github.sha }} . - name: Push to registry run: | docker tag myapp:${{ github.sha }} registry.example.com/myapp:latest docker push registry.example.com/myapp:latest - name: Deploy to server uses: appleboy/ssh-action@v1 with: host: ${{ secrets.SERVER_HOST }} username: ${{ secrets.SERVER_USER }} key: ${{ secrets.SERVER_SSH_KEY }} script: | docker pull registry.example.com/myapp:latest docker stop myapp || true docker rm myapp || true docker run -d \ --name myapp \ --restart unless-stopped \ -p 3000:3000 \ --env-file /app/.env \ registry.example.com/myapp:latest

#Стратегии rollback

Blue-Green deployment: поддерживаете два окружения (blue — активное, green — новое). Переключаете трафик через Nginx upstream:

upstream nuxt_app { server 127.0.0.1:3000; # blue # server 127.0.0.1:3001; # green (активируем при переключении) }

Версионирование Docker образов: каждый деплой тегируется hash коммита. Откат — это просто запуск предыдущего образа.

Канарейные релизы: новая версия получает 10% трафика. При отсутствии ошибок постепенно увеличиваем до 100%:

split_clients "${remote_addr}" $upstream { 10% 127.0.0.1:3001; # canary (10% трафика) * 127.0.0.1:3000; # stable }

Хорошая практика: всегда держите последние 3 успешных Docker образа и имейте runbook (документ с пошаговыми инструкциями) для отката.