Вы когда-нибудь оказывались в ситуации, когда вам нужно сделать огромное приложение React.js SEO-дружественным, но у вас нет времени на перенос приложения на фреймворк вроде Next.js или Gatsby.js, поддерживающий серверный сайд-рендеринг?
Это решение, которое я собираюсь обсудить сегодня, действительно может помочь вам выполнить серверный рендеринг вашего приложения react всего за несколько минут, используя такой инструмент, как Selenium и веб-сервер.
ПРИМЕЧАНИЕ: В интернете часто встречается дезинформация о том, что библиотека React-Helmet является SEO-решением для React. Но это не так, по крайней мере, не только для нее одной. Важно понимать, что React Helmet использует javascript для вставки тегов <meta>
в DOM. Однако, когда боты google или facebook приходят на ваш сайт, они не выполняют javascript. Поэтому страница, которую видят боты, приходя на ваш сайт, не содержит тегов <meta>
, и боты не могут узнать много нового о вашем сайте. Другая библиотека, которая работает так же, как React-Helmet, — это React-Meta-Tags. Нам все еще нужна подобная библиотека, но она будет работать только после того, как мы реализуем идеи, обсуждаемые далее в этом посте.
В моем случае REST API, который потреблял React front end, был построен с использованием python. Поэтому я буду использовать пакет Selenium для python. Но вы можете использовать эту идею независимо от того, какую технологию бэкенда использует ваш проект. Еще одна вещь, о которой я хочу упомянуть, это то, что мое приложение React обслуживалось веб-сервером Nginx. Но, опять же, вы сможете применить эту идею, которая, по сути, просто требует обновления конфигурации любого используемого вами веб-сервера.
Решение
Шаг 1: Обновите конфигурацию веб-сервера приложения React App
Как упоминалось ранее, приложение React, над которым я работал, обслуживалось через Nginx. Вот что я изменил в существующей конфигурации Nginx,
location / {
set $server_side_render 0;
set $server_side_render_host_path api.mydomain.com/v1/ssr/;
if ($http_user_agent ~* "googlebot|bingbot|yandex|baiduspider|twitterbot|facebookexternalhit|rogerbot|linkedinbot|embedly|quora link preview|showyoubot|outbrain|pinterest/0.|pinterestbot|slackbot|vkShare|W3C_Validator|whatsapp") {
set $server_side_render 1;
}
if ($uri !~ "^(.*)/(product|category|other_endpoints_i_want_to_be_seo_friendly)(.*)"){
set $server_side_render 0;
}
if ($server_side_render = 1) {
proxy_pass https://$server_side_render_host_path$request_uri;
}
try_files $uri $uri/ /index.html;
}
Идея изменения заключается в том, что мы хотим проверять, когда один из ботов популярных сайтов, таких как Facebook или Google, заходит на наш сайт, а затем делегировать эти запросы определенной конечной точке нашего бэкенд API. Мы называем эту конечную точку api.mydomain.com/v1/ssr/
. Вы можете задаться вопросом, почему мы отправляем ботов только на эту конечную точку? Почему бы не отправить всех? Я бы не рекомендовал этого делать, потому что, очевидно, для реального пользователя вашего сайта будет очень медленно проходить через все это, чтобы получить ответ от вашего сайта. К счастью, бот google и другие боты имеют достаточно длительный тайм-аут, так что это все еще достаточно быстро для ботов, но не так быстро для реальных пользователей. Если вы хотите предоставлять всем своим пользователям html с рендерингом на стороне сервера, вам следует подумать о переходе на фреймворк, например Next.js или Gatsby.js. Но это тоже займет немало времени, если ваше приложение на React достаточно большое, и именно поэтому я считаю, что подход, который я обсуждаю в этом посте, актуален.
Шаг 2: Добавьте конечную точку API бэкенда /ssr/
Теперь, когда мы отправили ботов на эту конечную точку, нам нужно предоставить им файлы html с поддержкой javascript для их request_uri. Здесь на помощь приходит Selenium, который мы можем использовать просто для рендеринга html на бэкенде. Вот как это работает,
def render_html(request, path):
if request.method != 'GET':
return HttpResponse(status=405)
# start after 3 letters (s-s-r)
idx = request.get_full_path().find('ssr/')
url = f"https://www.mydomain.com{request.get_full_path()[idx + 3:]}"
chrome_options = Options()
chrome_options.add_argument("--disable-extensions")
chrome_options.add_argument("--enable-javascript")
chrome_options.add_argument("--headless")
chrome_options.add_argument("--no-sandbox")
chrome_options.add_argument("--disable-dev-shm-usage")
chrome_options.add_argument('--ignore-ssl-errors=yes')
chrome_options.add_argument('--ignore-certificate-errors')
chrome_options.add_argument('--disable-web-security')
chrome_options.add_argument('--enable-logging=stderr --v=1')
# chrome_options.add_experimental_option('w3c', False)
chrome_options.add_argument('user-agent=Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/94.0.4606.81 Safari/537.36')
d = DesiredCapabilities.CHROME
d['goog:loggingPrefs'] = {'browser': 'ALL'}
driver = webdriver.Chrome(chrome_options=chrome_options, desired_capabilities=d)
driver.get(url)
soup = BeautifulSoup(driver.page_source, 'html.parser')
for entry in driver.get_log('browser'):
print('Selenium-Log:', entry)
meta = soup.html.findAll('meta')
for item in meta:
print(item)
driver.quit()
return HttpResponse(soup.html, content_type="text/html")
Мы используем chrome webdriver и используем опцию --enable-javascript
, чтобы найти html-строку сайта с поддержкой javascript. Эта html-строка будет содержать соответствующие теги<meta>
, добавляемые библиотеками типа React-Helmet
. Таким образом, мы посылаем ботам, приходящим на наш сайт, html, отрендеренный на стороне сервера.
Шаг 3: Добавьте соответствующие теги на страницы react
Теперь мы можем использовать такие библиотеки, как React-Helmet или React-Meta-Tags, чтобы внедрить теги для каждой страницы.
Шаг 4: Тестирование
Мы можем проверить, работает ли разработанная нами система, используя такой инструмент, как Facebook-Sharing-Debugger, чтобы проверить, что видит бот facebook, когда он обращается к одной из конечных точек нашего сайта с поддержкой SSR.
Вуаля! Мы успешно обманули ботов, заставив их увидеть серверный рендеринг html нашего сайта, который содержит соответствующие теги <meta>
, используемые для SEO и SMO.
BTW, подумайте о кэшировании этих серверных html, чтобы сделать ботов 🤖 🤖 🤖 🤖 еще более счастливыми xD