Отнасяйте се правилно към потребителите си с HTTP кеш и сегментирано изобразяване

Тази статия е дълга (10–15 минути), но си заслужава! Вземете си топла напитка и се насладете на четенето.

Богатият гост и бедният клиент

Представете си как разглеждате любимото си онлайн списание. „За мен“ това би бил блог, описващ неясни скъпи музикални синтезатори, които всъщност никога няма да купя.

Изпълненията на уебсайта са невероятни. Тъй като съдържанието е публично и се споделя между всички потребители, то може да бъде кеширано някъде близо до вас, на „ръба“, и изпратено както е в HTML.

Представете си, че този уебсайт има платена секция за наистина много добри статии. Купувате абонамент и продължавате към влизане.

Изведнъж всичко започва да става по-бавно. Виждате ужасни спинери навсякъде. Вашият процесор става шумен. Изчаквате 3 секунди, за да се зареди всяка страница. Можете да изпържите яйце на вашия Ipad.

Това е така, защото напуснахте прекрасния свят на статично изобразено съдържание. Сега това е изобразяване от страна на клиента навсякъде! Изобразяване от страна на сървъра по заявка навсякъде!

Само защото вече сте уникален, специален, удостоверен потребител, който чете лично съдържание, за което сте платили.

Това е, което аз наричам проблемът с богатия гост и бедния клиент. Гостите се радват на оптимална производителност, със статично или кеширано изобразяване, докато удостоверените потребители получават най-лошото, с SSR на заявка и изобразяване от страна на клиента . Няма много смисъл!

Представяме ви изобразяване на сегменти: 1 сегмент = 1 изобразяване

Маркетингът разделя хората на хомогенни сегменти. Гостите са един сегмент, платените клиенти са друг сегмент.

Само клиентският сегмент може да види платеното съдържание, докато гостите трябва да бъдат пренасочени към страница за абонамент.

Има много други сценарии, при които можете да дефинирате сегменти, които трябва да виждат конкретно съдържание на вашия уебсайт:

  • A/B тестване: всички потребители на кофа ще видят една и съща вариация на уебсайта
  • Многонаемност: всички потребители на дадена компания ще виждат едно и също лого и цветова схема
  • Интернационализирано съдържание: всички потребители с един и същи език виждат едни и същи текстове
  • Тъмна/светла тема: всички потребители, избрали светъл режим, разрушават роговицата си

В тези примери всички потребители на даден сегмент трябва да виждат едно и също съдържание. Кеширано или статично изобразяване за всеки сегмент би било страхотно!

Нека наречем този модел „Сегментирано изобразяване“.

Нашата цел тук е да направим само едно изобразяване на сегмент. Това както ще намали разходите за работа с нашия уебсайт, така и ще подобри възприеманата производителност за крайните потребители.

За съжаление, много рамки на „Jamstack“ предполагат, че ако дадено съдържание не е публично и еднакво за всички, то не може да бъде статично изобразено. Те няма да ви позволят лесно да приложите сегментирано изобразяване.

Но нека открием 2 модела за заобикаляне на това ограничение.

Нестандартна реализация с Next.js

Вече описах пълноценно внедряване на този модел на „сегментирано изобразяване“ с Next.js. Също така доказах формално, „с някои математически изчисления“, че този модел постига минимален брой изобразявания, като основно избутва статичното изобразяване до най-крайните му граници. Изпратих и „PR на документацията на Next.js“, за да изясня условията, при които SSG действително е приложим.

Проблемът е, че този подход разчита на нестандартни функции, междинен софтуер Next.js и SSG/ISR специфики. В Remix.js можете да кеширате изобразяванията, като използвате някаква персонализирана логика в entry.server. Може да се разшири до други рамки на Jamstack с помощта на прокси сървър, но не и извън кутията.

За да обобщим, сървърът трябва да отговаря за проверката на съдържанието на заявката и пренасочването към правилния вариант на страницата.

Нека се опитаме да постигнем сегментирано изобразяване, използвайки само една стандартна технология: HTTP кеша.

Малка техническа забележка: Склонен съм да използвам „статични“ и „кеширани“ взаимозаменяемо в тази статия. Това е така, защото статичното изобразяване е приблизително еквивалентно на кеширане на някои сървърни изобразявания по време на изграждане или дори при първа заявка. Поставянето на добре конфигуриран кеш пред всяка рамка, която може да прави изобразяване от страна на сървъра на заявка, я превръща в статична рамка.

Стандартна реализация с HTTP кеш

Стълбът на философията на рамката на Remix е „работа с основите на уеб браузъра““. HTTP протоколът наистина идва с мощна кеш система. «Документацията на Mozilla е чудесно място да започнете, ако искате да научите повече за нея. Нека използваме този кеш, за да реализираме сегментирано изобразяване.

1. Активирайте изобразяване от страна на сървъра при заявка

Имаме нужда от начин да рендираме HTML за всеки вариант на вашата страница, в зависимост от заявката на потребителя. Например, една версия на език.

Първата стъпка е да настроите приложението си, за да активирате SSR по време на заявка:

  • В Next.js чрез getServerSideProps; в Гетсби през getServerData; в Remix това е поведението по подразбиране.

2. Идентифицирайте сегменти чрез HTTP заявката

При заявка на потребител трябва да познаем неговия сегмент. Например техния предпочитан език.

Втората стъпка е изясняване на сегментите на вашето приложение:

  • Идентифицирайте сегменти чрез елементи от входящата заявка: обикновено бисквитки, URL параметри и понякога специфични заглавки като „Accept-Language“

3. Настройте заглавката Vary на HTTP отговора

Сега всъщност трябва да конфигурираме кеша, така че да съхраняваме/извличаме една версия на страницата на сегмент. Например, когато за първи път френски потребител посети нашия уебсайт, ние изобразяваме френската версия и я кешираме. Вторият френски потребител ще получи незабавно кешираната версия.

Третата стъпка е да кажете на HTTP кеша как да разграничава вашите сегменти:

Пример: Vary: Cookie, Accept-Language

Последна стъпка: настройте заглавката Cache-Control на HTTP отговора

  • настройте кеша, чрез заглавката Cache-Control, така че ново изобразяване на сървъра да се случи само след определен период от време.

Пример: Cache-Control: public, s-maxage=604800

“Maxage” е за секунди. Бъдете внимателни, за да настроите тази продължителност според живота на вашето съдържание. Например скорошна статия може да бъде редактирана, след като е била публикувана, така че я дръжте ниска и след това я увеличете за по-старо съдържание, което почти не се движи вече. Хранилището трябва да е „публично“: смисълът на сегментираното изобразяване е да се споделя едно и също изобразяване между множество потребители.

Вие сте готови!

Чрез използването на този прост подход рендирането от страна на сървъра ще се случи само веднъж на сегмент!

Това не е „статично“ изобразяване в традиционното значение, защото изобразяването не се случва по време на изграждане, а при първо изобразяване. Това всъщност е по-близо до Next.js „ISR“. Но броят на изобразяванията всъщност е точно същият като статичния: 1 за всеки сегмент.

Получавате повечето от възможностите за персонализиране на SSR на заявка, с характеристиките на генерирането на статичен сайт по време на изграждане!

Бонус: ETags за версия на всяка вариация

Заглавката „ETags“ ви позволява да присвоите конкретна версия на някои съдържания. Тук ETags трябва да съдържат уникален идентификатор за сегмента. Не забравяйте също така да добавите уникален идентификатор на версията, например последния Git комит на вашето хранилище.

Пример: ETag: bucket-b-theme-light-commit-1234

Този хедър ще се обработва само от браузъра. Полезно е, ако потребителят е склонен да променя много своя сегмент, например когато опитва различни теми в настройките си.

Ограничения на HTTP кеша за сегментирано изобразяване

За съжаление, този стандартен модел с HTTP кеша всъщност е по-нисък от нашето „нестандартно“ внедряване, базирано на Next.js. Ето защо.

Ограничения на ниво приложение и на ниво CDN

HTTP кешът се обработва от мрежата за доставка на съдържание. Можете да настроите своя собствена CDN или да разчитате на CDN, предоставена предварително от вашия хостинг доставчик. Ако сте били внимателни в последния раздел, може да сте забелязали множество ограничения:

  • Ако вашата рамка не активира SSR на заявка, няма да можете да използвате HTTP кеша за сегментирано изобразяване. съжалявам Въпреки това персонализираното внедряване все още ще работи, стига да можете да поставите сървър за пренасочване пред приложението си. „Вижте моята статия за решение, което работи навсякъде.“
  • Внимавайте, че заглавката Vary в момента (05/2022) не се поддържа от някои големи CDN, включително Vercel. Съжалявам. Ако не можете да използвате CDN, който поддържа тази заглавка, върнете се към нестандартната реализация.
  • Всеки CDN може да има някои допълнителни правила за сигурност и поверителност. Например Vercel няма да запълни кеша, ако заявката съдържа заглавката за оторизация, от съображения за поверителност. Сегментираното изобразяване може да не работи, ако влезете например чрез основно удостоверяване, дори за публично съдържание. Извинявай отново.
  • Не можете да изберете ключа за бисквитка. Тази стара статия описва предложението за допълнителен ключов хедър, който изглежда не е прилаган оттогава. Наистина съжелявам!

Какво ще кажете за платеното и частното съдържание?

HTTP кеширането има 2 режима:

  • публично, кеширано изобразяване се съхранява в CDN, достъпно за всеки
  • частно, кеширано изобразяване се съхранява в браузъра на потребителя

Няма такова нещо като частно изобразяване на CDN, защото обикновено не можете да правите изчисления в CDN. Не можете да проверите удостоверяването, не можете да проверите дали потребителят има платен абонамент или принадлежи към правилния наемател или A/B тестове.

Сегментираното изобразяване с HTTP кеш няма да работи за нашия блог с платена секция. Няма друга опция освен прилагането на кеш от страна на сървъра. Този подход ви дава повече контрол върху разрешенията за достъп и работи за частно/платено/сигурно съдържание.

Персонализираният сървърен кеш винаги е по-гъвкав от HTTP кеш

Казано накратко, при определени условия HTTP кешът ви позволява да отидете по-далеч от традиционното статично изобразяване. Можете да имате няколко варианта на една и съща страница. Прилага се за случаи на използване като интернационализирано съдържание, някои прости A/B тестове, тематизиране, публични страници на всеки наемател. Особено ако вариантът е избран чрез URL параметър. Вече е много!

Но ако искате повече, единственото решение е да поставите прокси сървър пред вашето приложение и да разчитате на някакъв вид кеширане от страна на сървъра. Може да бъде или статично изобразяване, или SSR с кеш в паметта, или каквото измислите. Статията, която вече споделих по-горе, ви показва как да направите това с Next.js, вижте я, ако искате да научите повече за сегментираното изобразяване.

Вече трябва да можете да направите клиентите си отново богати, а гостите си... още по-богати!

Много благодаря на Sergio Xalambrí (sergiodxa) за споделянето на невероятни познания за HTTP кеширането с мен. Ако ви е харесала тази статия, със сигурност ще се насладите на неговия блог:https://sergiodxa.com/

Благодаря, че прочетохте тази статия! Ако ви е харесало, моля, отделете малко време, за да откриете нашата рамка Next.js и GraphQL, VulcanNext.

Абонирайте се за блога на Vulcan за повече истории като тази или ме последвайте в Twitter: @ericbureltech