Задать вопрос
@dimuska139
Backend developer

Как программно инвалидировать SSR кеш в NextJS?

Не понимаю, как в проекте с NextJS инвалидировать кеш SSR. Во всех примерах (например) кеш хранится не в Memcache или, скажем, в Redis, а прямо в приложении и инвалидируется по ttl. Соответственно если у меня блог, а я отредактировал статью, чтобы пользователь увидел изменения на сайте, проходит определенное время. Если ttl, допустим, 2 часа, то максимум можно ждать обновления кеша 2 часа, соответственно. Можно ли как-то инвалидировать программно кеш конкретной страницы? Подружить NextJS с express-redis-cache не удалось.
  • Вопрос задан
  • 593 просмотра
Подписаться 3 Простой 8 комментариев
Решения вопроса 1
@dimuska139 Автор вопроса
Backend developer
В общем, сам решил вопрос. У cacheable-response можно в параметре cache указать свой экземпляр Keyv, передав в конструктор класса нужный store. Соответственно, если передать туда @keyv/redis, то кеш будет храниться в Redis. При желании можно просто из Redis удалять нужный ключ и все - вот и инвалидация.
Может немного неправильно объяснил, так что вот код моего server.js:
const express = require('express');
const next = require('next');
const redirects = require("./redirects");
const cacheableResponse = require('cacheable-response');
const port = parseInt(process.env.PORT, 10) || 3001;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const KeyvRedis = require('@keyv/redis');
const Keyv = require('keyv');

const handle = app.getRequestHandler();

const keyvRedis = new KeyvRedis('redis://127.0.0.1:6399'); // TODO: Get from dotenv

const ssrCache = cacheableResponse({
    ttl: 1000 * 60 * 120, // 2 hours
    get: async ({ req, res, pagePath, queryParams }) => ({
        data: await app.renderToHTML(req, res, pagePath, queryParams)
    }),
    cache: new Keyv({ store: keyvRedis }),
    send: ({ data, res }) => res.send(data)
});


app.prepare().then(() => {
    const server = express();

    redirects.forEach(({ from, to, type = 301, method = 'get' }) => {
        server[method](from, (req, res) => {
            res.redirect(type, to)
        })
    });

    server.use((req, res, next) => {
        res.append('Set-Cookie', "HttpOnly;Secure;SameSite=Strict");
        next();
    });

    server.get('/posts/:slug', (req, res) => {
        const queryParams = { slug: req.params.slug };
        const pagePath = '/post';
        return ssrCache({
            req,
            res,
            pagePath,
            queryParams
        });
    });

    server.get('/', (req, res) => {
        const pagePath = '/';
        return ssrCache({
            req,
            res,
            pagePath
        });
    });

    server.all('*', (req, res) => {
        //console.dir(req.url);
        return handle(req, res)
    });

    server.listen(port, err => {
        if (err) throw err;
        console.log(`> Ready on http://localhost:${port}`)
    })
});
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы