Запуск в продакшн
Мы написали основной функционал простенького магазина, и теперь пришло время выгрузить его на хостинг.
Админка будет сгенерирована в статичные файлы html, js и css, а вот публичный сайт мы запустим в режиме серверного рендеринга - ssr.
Серверный рендеринг нужен для того, чтобы ваш сайт могли индексировать поисковые машины. Хоть они давно и заявляют о поддержке SPA приложений, но на практике это не очень работает. Да и прочитать те же теги OpenGraph без серверного рендера никак не получится.
Конфигурации будет как для Nginx, так и для Apache2.
Настройки .env
При сборке и генерации проектов используются настройки из файла .env, и наше приложение прежде всего интересует куда ему отправлять запросы:
SITE_URL=http://vesp-shop.test/
API_URL=http://vesp-shop.test/api/
Если вы планируете собирать проект локально и выгружать на сервер - в этом файле нужно прописать правильные url конечного, а не локального, сайта.
Если же вы будете собирать проект сразу на хостинге, то там уже должен лежать .env c корректными настройками и ничего менять не нужно.
Генерация приложений
Первым делом собираем наш проект в статическом виде.
composer node:generate
В результате мы получаем две директории внутри frontend/dist: admin и site. В каждой лежат статические файлы, которые будут отдаваться пользователю веб-сервером.
Html страниц ровно одна - 200.html, больше нам и не нужно. Её задача вывести индикатор загрузки и ссылки на js и css файлы, которые отрисуют наш код.
В принципе, Nuxt может статически генерировать все маршруты, но при нашем подходе они просто не нужны. А так, да, можно статически сгенерировать небольшой сайт, например с документацией, и запустить его без ssr.
Попробуйте ради интереса закомментировать build.exclude в nuxt.config.js и посмотреть, что получится после генерации
Config.generate = {
cache: false,
dir: 'dist/admin',
// exclude: [/^\//],
}
Сборка и запуск сервера приложения
Теперь самое интересное - запуск site в режиме ssr.
Nuxt сам по себе вполне веб-сервер, который запускается из консоли и слушает определённый порт. Вы уже видели это в режиме разработки dev, а теперь нам нужно запустить тот же сервер, но уже в production режиме.
Делается это командой composer node:start, которая соберёт site, а потом запустит менеджер процессов pm2 для управления Nuxt.
Зачем нам менджер процессов? Ну как минимум для того, чтобы следить за состоянием Nuxt, логировать его сообщения и перезапускать, если он упадёт. Конфигурация pm2 находится в файле frontend/ecosystem.config.js:
// Определяем режим работы
const prod = process.argv.includes('production')
module.exports = {
apps: [
{
// Имя приложения
name: 'site',
exec_mode: 'cluster',
// Процесс для работы - наш Nuxt
script: './node_modules/nuxt/bin/nuxt.js',
// Аргументы для передачи Nuxt зависят от режима работы
// Здесь мы прописывааем порт, который будет слушать сервер
args: (prod ? 'start ' : '') + '--config-file ./src/site/nuxt.config.js -H 127.0.0.1 -p 20001',
// Количество процессов
instances: 2,
autorestart: true,
max_memory_restart: '1G',
// рабочий режим - основной
env_production: {
NODE_ENV: 'production',
// Не следить за изменением файов
watch: false,
},
// режим разработки, обычно не используется
env_development: {
NODE_ENV: 'development',
watch: true,
},
},
],
}
Все настройки можно посмотреть в документации.
В конфигурации прописан порт 20001, значит можно открывать http://127.0.0.1:20001.
Когда сервер запущен, вы можете вызывать ./frontend/node_modules/.bin/pm2 с разными командами, например проверить состояние приложений ./frontend/node_modules/.bin/pm2 status, logs выведет сообщения, а monit запустит своеобразный центр управления.
Остановка сервера производится командой composer node:stop
Деплой на сервер
Итак, у нас есть статически собранная админка, и сайт в двух вариантах: статически собранный и в режиме серверного рендера.
Теперь берём любой хостинг с NodeJS и PHP, например https://modhost.pro, главное, чтобы давали не менее 1 гигабайта свободного места, потому что javascript зависимости занимают прилично мегабайт.
У меня вот такие настройки Deployment в PhpStorm, через него я и выгружаю свой проект на хостинг:
После выгрузки заходим на сервер через SSH.
У modhost.pro в консоли по умолчанию используется php 7.0, а нам нужен минимум 7.4, так что делаем ссылку на правильную версию:
mkdir ~/bin
ln -s /usr/bin/php7.4 ~/bin/php
source ~/.profile
php -v
В результате должен быть PHP 7.4.27 (cli) (built: Dec 20 2021 21:27:56) ( NTS ) или типа того.
Теперь можно делать
composer install
composer node:install
Дальше переименовываем стандартный файл настроек и редактируем
mv .env.dist .env
nano .env
Я пишу свои настройки, вам нужно указать свои:
APP_NAME="Vesp Framework"
SITE_URL=http://s30069.h10.modhost.pro/
API_URL=http://s30069.h10.modhost.pro/api/
CORS=1
DB_DRIVER=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_PREFIX=app_
DB_DATABASE=s30069
DB_USERNAME=s30069
DB_PASSWORD=password
DB_CHARSET=utf8mb4
DB_COLLATION=utf8mb4_general_ci
DB_FOREIGN_KEYS=1
JWT_SECRET=secret
JWT_EXPIRE=2592000
JWT_MAX=3
UPLOAD_DIR=/home/s30069/upload/
CACHE_DIR=/home/s30069/tmp/
Теперь можно создать и засеять таблицы
composer db:migrate
composer db:seed
Ну и собрать приложения через composer node:generate
Финальный штрих - запуск pm2 composer node:start
Обратите внимание, что порт 20001 уже может быть занят на сервере, если кто-то другой запустил свой проект на Vesp раньше вас. Придётся указать любой другой свободный порт в frontend/ecosystem.config.js, например 20002, 20003 и т.д.
Все приложения готовы, осталось только указать веб-серверу, как с ними работать.
Настройка Nginx
Вот мой рабочий конфиг на modhost с комментариями
# Отдельная обработка PHP
location ~ \.php$ {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
# Имя обработчика зависит от вашего юзера
fastcgi_pass backend-s30069;
}
# Эти запросы улетают в API
location ~ ^/(api|__clockwork)/ {
rewrite ^/(api|__clockwork)/(.*)$ /api.php;
}
# К запросу в админку добавляем слэш на конце
location /admin {
return 301 /admin/;
}
# Файлы админки обсуживаются прямо оттуда, куда они собираются
location /admin/ {
root /home/s30069/frontend/dist/;
# Логировать запросы в админку нам не нужно
access_log off;
# Настройки кэширования статики
gzip on;
gzip_types text/css application/javascript application/x-javascript text/javascript image/svg+xml;
expires 1y;
# Указание страницы по умолчанию
try_files $uri /admin/200.html;
}
location / {
# Серверный режим
# Передаём все запросы в Nuxt
proxy_http_version 1.1;
# Тут лучше ничего не менять
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_read_timeout 240s;
# А вот и адрес нашего сервера
# Напоминаю, что порт может быть занят - и тогда вы указываете здесь другой
proxy_pass http://127.0.0.1:20001;
# Сайт так же можно запустить и в статическом режиме
# root /home/s30069/frontend/dist/site/;
# access_log off;
# gzip on;
# gzip_types text/css application/javascript application/x-javascript text/javascript image/svg+xml;
# expires 1y;
# try_files $uri /200.html;
}
В итоге всё работает как положено:
Настройка Apache2
Файл с примером правил Apache2 лежит по адресу www/.ht.access, но в нём нет настроек для работы ssr.
В отличие от Nginx, я не смог настроить чтение статических файлов из директории выше www, так что вам нужно будет перенести содержимое ~/frontend/dist/site в корень ~/www/, сохранив при этом api.php.
Вот рабочая конфигурация с одного моего проекта:
DirectoryIndex 200.html
RewriteEngine On
RewriteBase /
# Обработка запросов в API
RewriteCond %{REQUEST_URI} ^/(api|__clockwork)/ [NC]
RewriteRule ^(.*)$ api.php [L,QSA]
# Обработка запросов в админку, когда запрошенный адрес не найден
# Это для страниц сайта
RewriteCond %{REQUEST_URI} ^/admin/? [NC]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /admin/200.html [L,QSA]
# Тоже админка, но файл существует - это для скриптов и стилей
RewriteCond %{REQUEST_URI} ^/admin/? [NC]
RewriteRule ^(.*)$ $0 [L,QSA]
# А вот это передача всех оставшихся запросов на сервер Nuxt
# Флаг [P] говорит о проксировании
RewriteCond %{REQUEST_URI} ^/
RewriteRule ^(.*)$ http://127.0.0.1:20001/$1 [P]
Честно говоря, я не большой специалист по Apache2, он мне никогда не нравился, так что конфиг может быть не оптимален. Так же нет 100% уверенности, что все хостинги позволят ему проксировать запросы.
В любом случае, если на хостинге есть возможность настроить Nginx - лучше использовать именно его.
Заключение
Думаю, вы обратили внимание, что деплой рабочих проектов на хостинг не особо-то отличается от локальной разработки. Те же настройки, миграции, команды для сборки.
Единственная сложность - это режим серверного рендера, но с готовыми конфигами проблем возникнуть не должно.
На следующем занятии подводим итоги, и на этом курс окончен.
Обновлено 18 октября 2022
Перенёс рабочий сайт на свой сервер, чтобы не платить деньги за чужой хостинг. Проект работает в статическом режиме, без SSR.
Можете заходить по адресу https://vesp-shop.bezumkin.ru и в админку https://vesp-shop.bezumkin.ru/admin/ (логин и пароль user). Всё открыто только для чтения, изменить ничего нельзя.
0
👍
👎
❤️
🔥
😮
😢
😀
😡
906
07.07.2022, 14:02:29
51 комментарий
Игорь
08.07.2022, 05:49:48
Спасибо за курс! Если не сложно, напиши еще заметку о базовых настройках сайта:
- как правильно прописать head (с метатегами и каноническими ссылками)
- как редактировать названия и описания страниц сайта
- как создать карту сайта
Возможно ты сталкивался с проблемами индексирования сайта, делал все страницы сайта AMP-friendly или применял какие-то другие полезные решения типа nuxt-trailingslash-module (удаляет лишние слэши в конце адресной строки), vue-lazyload ("ленивая" загрузка фото) или cssnano (модуль для сжатия css, устранение дубликатов).
В общем, прошу поделиться своими наблюдениями ))
Василий Наумкин
08.07.2022, 10:46:40
Честно говоря, мне никогда не нравилась идея затачивать свои сайты под какие-то технологии поисковиков. Что AMP от Google, что Турбо от Яндекс. Так что здесь особо порадовать нечем.
А про всё остальное - читай заключительную заметку курса.
Ivan CR
08.07.2022, 16:18:31
Василий, а как ты решаешь вопрос автозапуска сайтов после перезагрузки сервера?
Ivan CR
08.07.2022, 18:27:44
Отвечаю сам на свой вопрос. Вот ссылка, с описанием настройки автозапуска PM2 при перезапуске сервера https://www.tecmint.com/enable-pm2-to-auto-start-node-js-app/
PM2 будет сам восстанавливать нужные процессы. Сам еще не пробовал, но обязательно попробую настроить.
Василий Наумкин
08.07.2022, 18:30:30
Так можно делать только на своём сервере.
А на публичном придётся писать скрипт для cron, который будет проверять pm2, и запускать, если не нашёл.
NightRider
10.07.2022, 17:17:02
Почему при запуске команды composer node:generate может выбивать ошибку Nuxt Fatal Error ?
Василий Наумкин
10.07.2022, 17:27:45
Хм, не знаю.
Но я бы попробовал удалить node_modules и поставить зависимости заново, возможно в системе что-то изменилось.
NightRider
10.07.2022, 18:12:19
Разобрался. На сервере была установлена древняя нода 10 версии что ли. Обновил - заработало.
Василий Наумкин
10.07.2022, 19:57:05
Отлично!
Николай Каленников
13.08.2022, 11:10:13
Коллеги, кто разбирается в настройке сервера. Есть VDS с процессором 3,3 ГГц, 1 Гб оперативки и диск 15 Гб. Поставил Ubuntu 20.04 и FastPanel, NodeJS через терминал. Исходники Vesp копируются,
срабатывает нормально. Но на
начинаются проблемы. Админка генерируется, а на генерации сайта сначала выводил composer timeout, убрал ограничение по времени, теперь то 137 ошибку выводит, то Killed. Дам полный доступ к серверу, там ничего ценного нет, напишите в телеграме @nikolokol
Василий Наумкин
13.08.2022, 11:18:21
Killed говорит, что сервер прибивает задачу, скорее всего у провайдера есть какие-то лимиты по нагрузке и их недостаточно для сборки проекта.
Такое запросто может быть на недорогих хостингах.
Александр Наумов
15.10.2022, 05:48:23
Василий добрый день!
Устанавливаю сайт на хостинг, выполняю команду composer node:generate и получаю ошибку:
Нормально выполнились, база заполнилась.
Василий Наумкин
15.10.2022, 05:52:32
А ты, случаем, composer node:install не забыл?
Александр Наумов
15.10.2022, 13:33:41
Запуск composer node:install заканчивается вот такой ошибкой:
Лог файл 2022-10-15T09_58_26_953Z-debug.log очень большой 12000 строк, скачать можно здесь http://s30805.h10.modhost.pro/2022-10-15T09_58_26_953Z-debug.log
Пару раз уже все сносил, все заново переустанавливал и каждый раз лог разный.
Василий Наумкин
15.10.2022, 13:53:15
У тебя поди свободного места на хостинге не хватает, чтобы установить все зависимости.
Александр Наумов
15.10.2022, 14:14:02
Василий, спасибо!!!
Сменил тариф с Разработки на Максимальный и вроде все установилось.
Изначально выбирал тариф Максимальный, но пояснение под тарифом Разработка меня дезориентировала:
Александр Наумов
15.10.2022, 14:45:43
Василий, подскажи, пожалуйста?
Взял из этой статьи конфиг Nginx, заменил в нем s30069 на свой s30805, сменил порт 20001 на 20086. Перехожу на сайт http://s30805.h10.modhost.pro и получаю редиректы:
Хотя по ссылке http://s30805.h10.modhost.pro/info.php сайт работает нормально.
Александр Наумов
16.10.2022, 00:42:51
Создал два сайта на Modhost на тарифе Тестовый, один на MODX другой пустой. Тот который на MODX открывается нормально, а тот который пустой делает редирект, хотя у обоих конфиг Nginx одинаковый.
Интересно, в чем может быть дело?
Василий Наумкин
16.10.2022, 10:34:06
Ты в каком режиме-то запускаешь? Если в SSR, то нужно и PM2 запустить, то есть сервер Nuxt для обработки запросов. Именно для этого режима написан конфиг.
Если в статическом, то в конфиге нужно убрать эту часть и раскомментировать другую:
Админка же у тебя в статическом режиме работает - http://s30805.h10.modhost.pro/admin/
Александр Наумов
16.10.2022, 12:50:16
Василий, спасибо!!
Запускаю в статическом, но все равно редирект происходит. ((
Василий Наумкин
17.10.2022, 06:19:09
Насколько я вижу - разобрался =)
Александр Наумов
17.10.2022, 12:35:18
Василий, спасибо!
Это у меня, что-то с двумя браузерами не лады были, почему-то они редиректили, а вот Firefox сейчас нормально все отобразил.
Александр Наумов
17.10.2022, 17:06:22
Видимо это проблема у моего провайдера, пользуюсь Мегафоном через флешку. Прикрутил домен к сайту и все равно редирект происходит на http://m.megafonpro.ru/http-errors/502, сейчас https подключу.
Александр Наумов
17.10.2022, 18:53:21
Да, с добавлением сайту https, проблема с редиректом решилась.
Василий Наумкин
17.10.2022, 18:55:26
Интересно, я с таким не сталкивался.
Александр Наумов
17.10.2022, 22:16:59
Видимо это тренды сегодняшнего времени, Мегафон, что-то химичит.
Например, зашел из хрома на 30069.h10.modhost.pro - тестовый сайт на VESP, который ты Василий делал и:
зашел из Фирефокс:
А если прорвешься, то рекламные баннеры на сайт добавят.
Хорошо, хоть с https все в порядке.
Василий Наумкин
18.10.2022, 06:57:59
А сайта на modhost уже и нет - срок вышел, надо деньги платить.
Перенёс на свой сервер, чтобы больше не беспокоиться.
Александр Наумов
19.10.2022, 00:43:25
Понятно.
Василий, не подскажешь, как поменять lang="en" в теге html?
Василий Наумкин
19.10.2022, 06:18:31
Общая документация по мета-тегам вот здесь, но конкретно по атрибутам тега html там ничего нет.
Но не проблема нагуглить. Добавляй в nuxt.config.js:
Александр Наумов
19.10.2022, 12:21:48
Спасибо, большое!!!
Александр Наумов
19.10.2022, 13:37:21
Не понятно почему, но не хочет работать ((
Александр Наумов
19.10.2022, 14:04:42
Разобрался.
У меня в vue файле в теге script прописан head и видимо его наличие там аннулирует настройки head в nuxt.config.js.
Прописал там в:
и заработало!
Василий Наумкин
19.10.2022, 14:07:10
Ура!
Вася
27.10.2022, 20:08:48
Первый курс, который я прошел до конца. Ура!
Василий Наумкин
27.10.2022, 20:24:37
Поздравляю!
Надеюсь, было не очень скучно.
Вася
28.10.2022, 15:48:06
Не скучно
но пора раздел открывать на сайте вопросы по Vesp
Вот решил многоязычность скопировать на публичный сайт, а не только чтоб в админке она была.
Ошибка Cannot set properties of undefined (setting 'getChoiceIndex')
Что нужно и где еще сделать, чтоб она завелась
Василий Наумкин
29.10.2022, 14:02:28
Vesp на сайте подключается в минимальной комплектации, так что там нет моих добавок для мультиязычности.
Попробуй включить их в конфиге:
Пока что мы общаемся в комментариях к платному курсу. Собственно, именно поэтому он и платный =)
Александр Наумов
03.11.2022, 17:14:53
Василий, а админка в статическом режиме будет работать?
Сейчас сайт в статическом режиме, пытаюсь авторизоваться выдает ошибку 500.
Василий Наумкин
03.11.2022, 17:16:17
Конечно, её вообще нет смысла запускать SSR - никто не индексирует.
Ошибка 500 - это всегда ошибка сервера, то есть бэкенд. Так что смотри логи сервера, дело не во фронтенде.
Александр Наумов
03.11.2022, 17:19:56
Спасибо большое, пошел разбираться!
Александр Наумов
03.11.2022, 18:23:47
Ошибку нашел, но не пойму как ее решить:
Файл :
Конфиг Nginx:
Откуда он берет s30805.h10.modhost.pro - не пойму?
Так и хочется почистить кэш, как в MODX))
Василий Наумкин
03.11.2022, 18:42:47
После изменения .env нужно пересобрать фронтенд - API_URL прошивается в него в момент сборки, всё статичное.
Александр Наумов
03.11.2022, 19:24:05
Спасибо!!! Все заработало!
Александр Наумов
24.01.2023, 18:13:48
Василий, добрый день!
Столкнулся с проблемой у себя на сайте, а потом ее увидел на твоем сайте, сейчас ее не наблюдаю.
Прохожу на страницу, перезагружаю F5 и вижу сообщение:
Не подскажешь, в чем причина и что нужно делать?
Ссылка на анимированную Gif https://vk.cc/cl0Sjy
Василий Наумкин
24.01.2023, 18:28:00
Ну, какая-то ошибка - смотри логи pm2
У меня такое было раньше, потом ошибку нашёл и исправил, сейчас это можно увидеть только при обновлении сайта и перезапуске pm2.
Александр Наумов
24.01.2023, 18:31:55
Понял, спасибо!
Александр Наумов
02.12.2024, 01:02:19
Василий, добрый день!
Перенес свои MODX сайты и один сайт на VESP2 на сервер от timeweb.cloud, настроил, работает неплохо.
Только вот никак не могу побороть проблему с PM2, запускаю node start - все ставится, но PM2 запускается глобальный, в ./node_modules/.bin/pm2 status - не активный.
Настроил PM2 для работы в текущей сессии:
Вроде стал работать, но говорит что ошибка.
Удалил, PM2 установленный глобально, при noda start все выполняется без ошибок и высвечивается запущенный PM2, но когда ./node_modules/.bin/pm2 status - то опять PM2 никого не обслуживает.
Подскажи, пожалуйста, как правильно сделать?
Да, настраивал сервер на основе твоей инструкции "Хостинг для MODX своими руками", где заблокировал root по ssh, а команды выполняю от user с sudo - может в этом дело?
На локальном компьютере и в Ubuntu 22.04 и в Ubuntu 20.04 - настроил этот сайт, все работает.
Василий Наумкин
02.12.2024, 07:12:36
По моему, без разницы откуда и как запускается pm2, важно только указывать ему конфиг для работы. Когда спрашиваешь про статус, тоже нужно указывать где лежит ecosystem.config.js.
Но вообще, я давно перенёс всё на Docker и pm2 больше не использую, теперь его функции выполняет systemd.
Александр Наумов
03.12.2024, 11:11:54
Василий, спасибо!
Скажи, пожалуйста, может ты помнишь или интуитивно можешь направить, куда можно посмотреть? Если при генерации возникает 404, при доступе к страницы карточка товара 404, при попытке авторизоваться ошибка 404.
Василий Наумкин
03.12.2024, 13:13:34
Генерация - это создание статичный файлов, для их работы потом pm2 не нужен, только правильная настройка web-сервера, чтобы Nginx знал, откуда читать сгенерированные файлы.
Раз ты видишь 404, значит Nginx настроен неправильно и файлы не находит. Или не хватает разрешений их прочитать.
Александр Наумов
02.12.2024, 02:35:07
Добавлял npx перед pm2 в команде start:
Не помогло, опять PM2 глобальный работает. А если PM2 глобальный удаляю, то сайт перестает работать ошибка 502, с глобальным хотя бы статику отдает, не удается по API контент подтянуть ошибка 404.
bezumkin.ru
Личный сайт Василия Наумкина
Прямой эфир
Василий Наумкин
03.12.2024, 13:13:34
Генерация - это создание статичный файлов, для их работы потом pm2 не нужен, только правильная настр...
Запуск в продакшн
51
Василий Наумкин
01.07.2024, 11:56:41
Да, верно, именно так.
А в контроллере, скорее всего, ловить данные методом post.
Василий Наумкин
26.06.2024, 09:38:15
О, точно, вылезает если не залогинен.
Спасибо, исправил!
Василий Наумкин
09.04.2024, 04:45:01
> Ошибка 500
Это не похоже на ошибку Nginx, это скорее всего ошибка PHP - надо смотреть его логи.
...
russel gal
09.03.2024, 20:17:18
> А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал...
Александр Наумов
27.01.2024, 03:06:18
Василий, спасибо!
Извини, тупанул.