From e3f1fe7eb5ea920507ef3f4e6a688c793819db36 Mon Sep 17 00:00:00 2001 From: Maxim Dolgolyov Date: Tue, 2 Jun 2026 20:35:18 +0300 Subject: [PATCH] =?UTF-8?q?fix(textbooks):=20html=20=D1=83=D1=87=D0=B5?= =?UTF-8?q?=D0=B1=D0=BD=D0=B8=D0=BA=D0=B0=20=D0=B2=D1=81=D0=B5=D0=B3=D0=B4?= =?UTF-8?q?=D0=B0=20no-store=20(=D0=BD=D0=B5=20=D0=BA=D1=8D=D1=88=D0=B8?= =?UTF-8?q?=D1=80=D0=BE=D0=B2=D0=B0=D1=82=D1=8C)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Раньше no-store ставился только в dev; в prod html главы кэшировался браузером/прокси и показывал устаревшую версию страницы (с пустыми builders → заглушки «Содержание готовится»). Теперь /textbook/:slug всегда отдаётся с Cache-Control: no-store + Pragma/Expires, как и положено SPA-входу с меняющимся контентом. Co-Authored-By: Claude Opus 4.8 (1M context) --- backend/src/server.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/backend/src/server.js b/backend/src/server.js index 3cbb1bd..71e676e 100644 --- a/backend/src/server.js +++ b/backend/src/server.js @@ -437,7 +437,11 @@ app.get('/textbook/:slug', (req, res, next) => { const row = _stmtTextbookPath.get(req.params.slug); if (!row) return next(); const filePath = path.join(frontendDir, 'textbooks', row.html_path); - if (!isProd) res.setHeader('Cache-Control', 'no-store'); + // Страница-учебник — SPA-вход, контент меняется при обновлениях: не кэшируем html + // ни в dev, ни в prod (иначе браузер показывает устаревшую версию с пустыми билдерами). + res.setHeader('Cache-Control', 'no-store, no-cache, must-revalidate'); + res.setHeader('Pragma', 'no-cache'); + res.setHeader('Expires', '0'); if (req.query.embed === '1') { const html = _renderEmbed(filePath, req.params.slug); if (html == null) return next();