Робота з включеннями крайніх сторін

Дата оновлення перекладу 2024-05-29

Робота з включеннями крайніх сторін

Шлюзові кеші - це чудовий спосіб підвищити продуктивність вашого веб-сайту. Але вони мають одне обмеження: вони можуть кешувати лише сторінку цілком. Якщо ваші сторінки містять динамічні секції, такі як імʼя користувача або корзину покупок, то вам не пощастило. На щастя, Symfony надає вирішення для таких випадків, засноване на технології під назвою ESI, або Включення крайніх сторін. Акамаї написав цю специфікацію у 2001 році, і вона дозволяє певним частинам сторінки мати інші
стратегії кешування, ніж головна сторінка.

Специфікація ESI описує теги, які ви можете вбудовувати у ваші сторінки, щоб комунікувати зі шлюзовим кешем. Лише один тег реалізовано в Symfony, include, так як він єдиний корисний поза контекстом Акамаї:

1
2
3
4
5
6
7
8
9
10
11
<!DOCTYPE html>
<html>
    <body>
        <!-- ... деякий зміст -->

        <!-- Вбудувати зміст іншої сторінки тут -->
        <esi:include src="http://..." />

        <!-- ... більше змісту -->
    </body>
</html>

Note

Відмітьте у прикладі, що кожний тег ESI вимагає повністю кваліфікованого URL. ESI-тег представляє фрагмент сторінки, який можна отримати через заданий URL.

Коли обробляється запит, кешуючий щлюз викликає цілу сторінку з кешу або запитує її з додатку вихідного буферу. Якщо відповідь містить один або більше ESI-тегів, то вони обробляються таким же чином. Іншоими словами, кешуючий шлю або вилучає включений фрагмент сторінки з його кешу, або запитує фрагмент сторінки з додатку вихідного буферу знову. Коли будуть розвʼязані всі ESI-теги, кешуючий шлюз обʼєднує кожний з них з головною сторінкою та відправляє кінцевий зміст клієнту.

Все це відбувається прозоро на рівні кешуючого шлюзу (тобто, поза вашим додаток). Як ви побачите, якщо ви вирішите скористатися перевагами ESI-тегів, Symfony зробить процес їх включення майже безтурботним.

Використання ESI в Symfony

Для початку, щоб використовувати ESI, включіть їх у конфігурації вашого додатку:

1
2
3
4
# config/packages/framework.yaml
framework:
    # ...
    esi: true

Тепер, уявіть, що у вас є сторінка, яка відносно статична, окрім рухомого новинного рядку знизу змісту. З ESI ви можете кешувати цей рухомий рядок незалежно від решти сторінки:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// src/Controller/DefaultController.php
namespace App\Controller;

// ...
class DefaultController extends AbstractController
{
    public function about(): Response
    {
        $response = $this->render('static/about.html.twig');
        $response->setPublic();
        $response->setMaxAge(600);

        return $response;
    }
}

У цьому прикладі, відповідь відмічена як публічна, щоб зробити всю сторінку кешованою для всіх запитів, з життєвим циклом у десять хвилин. Далі, додайте новинний тікер у шаблон, вбудувавши дію. Це робиться через помічника render() (щоб дізнатися більше, прочитайте, як вбудовувати контролери у шаблони ).

Так як вбудований зміст поступає з іншої сторінки (або контролера, якщо на це пішло), Symfony використовує стандартного помічника render, щоб сконфігурувати ESI-теги:

1
2
3
4
5
6
7
{# templates/static/about.html.twig #}

{# ви можете використати посилання на контролер #}
{{ render_esi(controller('App\Controller\NewsController::latest', { 'maxPerPage': 5 })) }}

{# ... або на URL #}
{{ render_esi(url('latest_news', { 'maxPerPage': 5 })) }}

Використовуючи відображувач esi (через функцію Twig render_esi()), ви повідомляєте Symfony, що дія має бути відображена як ESI-тег. Ви можете не розуміти, чому вам може захотітися використовувати помічника замість того, щоб просто написати ESI-тег самостійно. Це тому, що використання помічника змушує ваш додаток працювати рівно, навіть якщо не встановлено кешуючий шлюз.

Tip

Як ви побачите нижче, зміння maxPerPage, яку ви передаєте, доступна в якості аргументу вашого контролера (тобто, $maxPerPage). Змінні, передані через render_esi також стають частиною ключа кешу, щоб у вас були унікальні кеші для кожної комбінації змінних та значень.

При використанні функції render() за замовчуванням (або установці відображувача як inline), Symfony обʼєдную включений зміст сторінки з головною сторінкою до відправки відповіді клієнту. Але якщо ви використовуєте відображувач esi (тобто, викликаєте render_esi()) та якщо Symfony визначає, що вона має справу зі шлюзовим кешем, що підтримує ESI, вона згенерує тег включення ESI. Але якщо шлюзового кешу немає, або він не підтримує ESI, то Symfony просто обʼєднає включений зміст сторінки з головною, так само, як було б, якщо б ви використали render().

Note

Symfony ввадає, що кеш шлюзу підтримує ESI, якщо його запит включає у себе HTTP-заголовок Surrogate-Capability, і значення цього заголовку містить рядок ESI/1.0 будь-де.

Вбудована дія тепер може вказати свої власні правила кешування, повністю незалежні від головної сторінки:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// src/Controller/NewsController.php
namespace App\Controller;

use Symfony\Component\HttpKernel\Attribute\Cache;
// ...

class NewsController extends AbstractController
{
    #[Cache(smaxage: 60)]
    public function latest(int $maxPerPage): Response
    {
        // ...
    }
}

У цьому прикладі, вбудована дія теж кешується публічно, так як зміст однаковий для всіх запитів. Однак, в інших випадках, вам може знадобитися зробити цю відповідь непублічною і навіть некешошваною, в заллежності від ваших потреб.

Склавши весь вищенаписаний код, з ESI, кеш всієї сторінки буде валідним протягом 600 секунд, але кеш компонента новин триватиме лише 60 секунд.

При використанні посилання на контролер, ESI-тег повинен посилатися на вбудовану дію, як доступний URL, щоб кешуючий шлю міг виллучити її незалежно від решти сторінки. Symfony турбується про те, щоб згенерувати унікальний URL для будь-якого посилання контролера, може правильно прокласти маршрути, завдяки FragmentListener, який повинен бути додано у вашу конфігурацію:

1
2
3
4
# config/packages/framework.yaml
framework:
    # ...
    fragments: { path: /_fragment }

Однією чудовою перевагою ESI-відображувача є те, що ви можете зробити ваші додатки настільки динамічними, наскільки це потрібно, і водночас з цим, звертатися до додатку настільки рідко, наскільки це можливо.

Caution

Слухач фрагментів відповідає лише на підписані запити. Запити підписуються лише при використанні відображувача фрагменту та функції Twig render_esi.

Помічнику render_esi підтримує дві інші корисні опції:

alt
Використовується як атрибут alt в ESI-тегу, який дозволяє вам вказувати альтернативний URL для використання, якщо неможливо знайти src.
ignore_errors
Якщо встановлена як "true", до ESI буде додано атрибут onerror зі значенням continue, яке означає, що у разі невдачі, кешуючий шлюз просто тихо видалить ESI-тег.
absolute_uri
Якшо встановлена як "true", буде згенеровано абсолютний URI. За замовчуванням: false