Перенаправление на CloudFront с помощью Lambda @ Edge

Amazon CloudFront вместе с S3 - одно из самых простых и быстрых решений для публикации нового веб-сайта в наши дни. В Доме Радона мы часто используем комбинацию CloudFront + S3 с сайтами, которые мы выпускаем. В основном мы используем React для разработки этих веб-сайтов как одностраничных приложений.

Одна из основных проблем, которые у нас были в течение некоторого времени, заключалась в том, чтобы делиться определенными страницами с определенными метаданными в социальных сетях. Некоторыми хорошо известными решениями этой проблемы в экосистеме SPA являются рендеринг на стороне сервера или предварительный рендеринг страниц перед публикацией в файлы HTML для каждого маршрута, который у вас есть в приложении.

Затем вы можете иметь папки с предварительно обработанными файлами index.html в них и обслуживать их, когда клиент достигает определенной конечной точки. Например, если у вас есть маршрут в / home / my-page, вы можете создать папку home и еще одну под ней с именем my-page который содержит index.html с определенными метаданными и теми же ссылками js, что и ваш SPA. Такой вывод можно создать с помощью таких библиотек, как react-snap или response-snapshot.

Проблема

Это не было проблемой, пока мы не решили использовать частные корзины S3 и обслуживать их через CloudFront с источником S3. S3 имеет функцию автоматического обслуживания файлов index.html в папках, если вы не указали это специально. Например, если вы попытаетесь достичь маршрута в / home / page, он может автоматически обслужить /home/page/index.html. Однако CloudFront не имеет этой функции, за исключением основной папки. Он может обслуживать /index.html, когда вы нажимаете /, но не может обслуживать /home/page/index.html, когда вы нажимаете / home / page.

Такое поведение не мешает нам обслуживать SPA через CloudFront. В любом случае наш SPA будет перенаправлять внутренне на правильную страницу. Проблема заключается в совместном использовании и поисковой оптимизации (SEO), в частности, с метаданными. Мы все еще использовали инструменты моментальных снимков для создания структуры папок и файлов index.html, а также конкретных метаданных с помощью React Helmet, но мы не могли обслуживать эти файлы .

Решение: Lambda @ Edge

Lambda @ Edge - это особая версия Lambda, в которой вы можете прикреплять функции к своим дистрибутивам CloudFront. Эти функции повторяются во всех краевых точках и выполняются на краю. Он ограничен Node.js и имеет некоторые дополнительные ограничения по сравнению с исходной Lambda. Вы можете найти эти ограничения здесь.

С помощью Lambda @ Edge вы можете перехватить запрос CloudFront в 4 разных этапа. Эти этапы хорошо объяснены на следующей диаграмме.

Мы решили перехватить запрос источника, когда CloudFront запрашивает объект с исходного сервера, которым в нашем случае является S3. Это помогает нам перехватить только один раз, когда CloudFront необходимо кэшировать, поэтому мы не накладываем никаких накладных расходов на наши реальные пользовательские запросы (запросы зрителей). Поскольку мы аннулируем кеш только в том случае, если у нас есть обновление для веб-сайта, это будет происходить только для каждой версии на странице.

Логика здесь проста. Мы используем библиотеку path, чтобы проверить, имеет ли URI запроса расширение или нет. Все запросы с определенными расширениями будут статическими активами, поэтому мы не изменяем запрос и позволяем CloudFront выполнять свою работу. Для всех остальных запросов мы создаем новый uri, добавляя index.html в конец uri. Затем CloudFront знает, что ему необходимо получить этот конкретный файл для запроса и кэшировать его для всех следующих запросов, пока он не станет недействительным.

Так просто перехватывать и изменять запросы CloudFront. Вы можете проверить Примеры Lambda @ Edge, чтобы увидеть множество других вариантов использования, которые могут оказаться полезными, от A / B-тестирования до локализации веб-сайтов. У нас также есть другой пример, когда нам нужно было внедрить метаданные в одностраничное приложение с динамическим контентом. Нам удалось реализовать функцию Lambda для создания динамических HTML-страниц для нашего SPA без использования какой-либо серверной визуализации. Это немного сложнее, но все же приятно видеть возможности Lambda @ Edge.

Если вы хотите работать над важными, сложными, веселыми, скучными и сложными проектами с использованием AWS, React, Clojure и многих других передовых технологий, не стесняйтесь связаться с нами!