Настройка Prerender с nginx и кэшем в Redis
Предисловие
В современной веб разработке большая часть веб-страниц рендерится на стороне браузера. Это означает, что в исходом HTML-документе, который принят от сервера, нет тех данных, которые видит пользователь. Они, как правило, загружаются с помощью API уже в процессе работы со страницей. Такой подход помогает строить отзывчивые веб-приложения при удобном разделении ответственности между командами фронтенд и бэкенд разработки.
При этом возникает ряд проблем, одна из которых связана со спецификой работы поисковых роботов, которые индексируют веб-страницы. Они не исполняют JavaScript или делают это очень редко.
Чтобы поисковый бот корректно проиндексировал страницу и сайт в целом, исходный HTML-документ должен быть наполнен контентом и ссылками на другие страницы сайта. В таком случае на помощь приходит Server-Side Rendering. Но что делать, если вы не обладаете необходимыми навыками для его настройки или не имеете возможности сделать это в конкретном проекте?
Можно настроить Prerender. Это NodeJS-приложение, которое умеет рендерить любые веб-страницы через headless браузер и выдавать в ответ статический HTML. Решение не зависит от конкретного языка или проекта, так как является самостоятельным приложением и в связке с nginx никак не влияет на существующий исходный код.
Перед установкой
Инструкция подразумевает, что у вас уже есть облачный сервер с установленной Ubuntu 16+, доступом по SSH под не-root пользователем с sudo правами и рабочим JavaScript-приложением, которое раздается с помощью nginx.
Инструкция
Установка зависимостей
Подключитесь к серверу по SSH. Если у вас не установлен NodeJS, выполните команды в терминале для его установки:
curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -sudo apt-get install -y nodejs
Установите Google Chrome, выполнив команды в терминале:
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.debsudo apt install ./google-chrome-stable_current_amd64.debrm google-chrome-stable_current_amd64.deb
Во время работы Prerender будет рендерить ваши веб-страницы в headless версии браузера Google Chrome.
Установка Prerender
На сервере перейдите в папку, куда хотите установить Prerender. Я устанавливаю её в домашнюю директорию пользователя:
cd ~
Необходимо склонировать исходники из git репозитория:
git clone https://github.com/prerender/prerender.git
Перейдите в созданную папку и установите зависимости:
cd prerendernpm install
Проверьте, что установка прошла успешно, запустив сервер Prerender:
node server.js
Чтобы выключить Prerender, выполните:
Ctrl+C
Настройка systemd скрипта
Чтобы Prerender автоматически запускался при старте системы, нужно создать systemd скрипт. Перед этим выполните несколько подготовительных действий.
Prerender по умолчанию запускается на 3000 порту, но я предпочитаю изменять его на случайный порт.
Создайте случайное значение порта из допустимого диапазона:
shuf -i 49152-65535 -n 1
На всякий случай проверьте, не занят ли полученный порт этой командой (Пустая выдача означает, что порт свободен):
sudo lsof -i :PORT
Создайте файл “/lib/systemd/system/prerender.service” через sudo со следующим содержанием:
Вместо <PORT> укажите значение порта, полученное на предыдущем шаге.
Вместо <OS_USER> укажите имя пользователя, под которым происходит установка Prerender.
Если вы установили Prerender не в домашнюю директорию, укажите актуальный путь к файлу server.js в значении переменной ExecStart.
Активируйте сервис:
sudo systemctl daemon-reloadsudo systemctl start prerender.service
Убедитесь, что он запустился, выполнив команду:
sudo systemctl status prerender.service
Среди выдачи вы должны увидеть “Active: active (running)”:
● prerender.service - prerender.js - SEO Wizard
Loaded: loaded (/lib/systemd/system/prerender.service; disabled; vendor preset: enabled)
Active: active (running) since Fri 2020-06-19 05:38:35 UTC; 2h 27min ago
Для проверки работоспособности Prerender-а выполните команду, заменив <PORT> на актуальный:
curl http://localhost:<PORT>/https://www.google.com
Вы должны увидеть выдачу статического HTML.
Конфигурация nginx
Чтобы отдавать поисковым ботам статический HTML, нужно научить nginx перенаправлять запросы в Prerender.
Отредактируйте файл “/etc/nginx/sites-available/default”. В нём необходимо:
- Добавить новый “upstream” для Prerender. Не забудьте указать актуальный порт.
- Заменить “proxy_pass” на динамическое определение “upstream” в зависимости от User-Agent и параметров запроса. В случае ботов запросы будут перенаправлены на Prerender.
Пример, как должно получиться:
Проверьте, что нет ошибок в синтаксисе:
sudo nginx -t
Перезапустите nginx:
sudo systemctl restart nginx
Откройте в браузере ваш сайт, добавив в URL строку параметр “_escaped_fragment_” с пустым значением:
https://your.domain.com/?_escaped_fragment_=
Вам должна отобразиться полная статическая страница без скриптов. Именно так боты будут видеть ваш сайт.
Дополнительно
Кэширование через Redis
Чтобы Prerender не поднимал Google Chrome каждый раз, можно настроить кэширование страниц. Это позволит ускорить время выдачи страниц поисковым ботам и уменьшить расход оперативной памяти.
Если у вас не установлен Redis, выполните это по инструкции:
Перейдите в папку с Prerender и установите зависимость:
npm install prerender-redis-cache --save
Отредактируйте файл “server.js”, добавив в него строчку:
server.use(require('prerender-redis-cache'));
Отредактируйте файл “/lib/systemd/system/prerender.service”, добавив в него необходимые переменные окружения:
Environment=PAGE_TTL=3600
Environment=REDIS_URL=redis://:<REDIS_PASSWORD>@localhost:6379/1
PAGE_TTL — время жизни кэша страниц в секундах.
REDIS_URL — строка подключения к Redis. Замените <REDIS_PASSWORD> на актуальный.
Перезагрузите systemd скрипты и сервис:
sudo systemctl daemon-reloadsudo systemctl restart prerender.service
Теперь при повторном запросе страницы результат должен выдаваться намного быстрее.
Перезапуск Prerender в случае падения Google Chrome
В моей практике происходили случаи, когда Google Chrome падает при отрисовке страницы. При этом процесс Prerender ломается, но статус systemd скрипта остается активным.
Чтобы обойти эту проблему, можно настроить периодическую проверку работоспособности Prerender с автоматическим перезапуском.
Перейдите в домашнюю папку. Создайте файл “prerender_ping.sh” со следующим содержанием:
Замените https://your.domain.com на ссылку на ваш сайт.
Сделайте файл исполняемым:
chmod +x prerender_ping.sh
Остановите сервис Prerender:
sudo systemctl stop prerender.service
Проверьте, что сервис неактивен:
sudo systemctl status prerender.service
Запустите скрипт:
./prerender_ping.sh
Вы должны увидеть вывод “not responding”. Это значит, что Prerender неактивен и сейчас перезапустится. Еще раз проверьте статус сервиса, он должен стать активен:
sudo systemctl status prerender.service
Чтобы не забивать логи системы, можете закомментировать все “echo” в скрипте.
Разрешите выполнять перезапуск сервиса Prerender от имени sudo без запроса пароля. Добавьте в файл “/etc/sudoers” следующие строки, заменив <OS_USER> на имя пользователя, от имени которого вы установили Prerender:
Cmnd_Alias PRERENDER_SERVICE_CMNDS = /bin/systemctl restart prerender.service
<OS_USER> ALL=(ALL) NOPASSWD: PRERENDER_SERVICE_CMNDS
Откройте редактирование cron операций:
crontab -e
Добавьте в конец файла следующую строку, заменив <OS_USER> на имя пользователя, от имени которого вы установили Prerender:
*/5 * * * * /bin/bash -l -c '/home/<OS_USER>/prerender_ping.sh'
Теперь каждые 5 минут сервер будет проверять работоспособность Prerender и перезапускать его, если он не работает.