From c6b9001f7479353d41ea917ecffad4cfaf476824 Mon Sep 17 00:00:00 2001 From: Oleg Urin Date: Sun, 12 Apr 2026 16:12:43 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D0=BB=20=D1=81=D0=BA=D1=80=D0=B8=D0=BF=D1=82=20=D0=B4=D0=BB?= =?UTF-8?q?=D1=8F=20=D0=BF=D1=80=D0=B5=D1=80=D0=B5=D0=BD=D0=B4=D0=B5=D1=80?= =?UTF-8?q?=D0=B8=D0=BD=D0=B3=D0=B0,=20=D1=81=D0=B4=D0=B5=D0=BB=D0=B0?= =?UTF-8?q?=D0=BB=20=D0=BF=D0=BE=D0=BB=D1=83=D1=87=D0=B5=D0=BD=D0=B8=D0=B5?= =?UTF-8?q?=20=D1=81=D1=82=D1=80=D0=B0=D0=BD=D0=B8=D1=86=20=D0=B4=D0=B8?= =?UTF-8?q?=D0=BD=D0=B0=D0=BC=D0=B8=D1=87=D0=B5=D1=81=D0=BA=D0=B8=D0=BC=20?= =?UTF-8?q?=D0=B4=D0=BE=D0=B1=D0=B0=D0=B2=D0=B8=D0=BB=20=D0=B3=D0=BD=D0=BD?= =?UTF-8?q?=D0=B5=D1=80=D0=B0=D1=86=D0=B8=D1=8E=20=D0=BA=D0=B0=D1=80=D1=82?= =?UTF-8?q?=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/prerender.js | 181 ++++++++++++++++++++++++++++++------------- 1 file changed, 129 insertions(+), 52 deletions(-) diff --git a/scripts/prerender.js b/scripts/prerender.js index bcc8282..316154e 100644 --- a/scripts/prerender.js +++ b/scripts/prerender.js @@ -1,69 +1,146 @@ -import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs'; -import { resolve, dirname } from 'path'; -import { fileURLToPath } from 'url'; +import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; +import { client } from "../src/api/client"; const __dirname = dirname(fileURLToPath(import.meta.url)); -// Список всех страниц -const routes = [ - '/', - '/products', - '/about', - // добавьте свои URL -]; +const products = async function getProducts() { + try { + console.log("📡 Загрузка товаров из API..."); + const response = await client.get("/productList/"); + return response.data; + } catch (error) { + console.error("❌ Ошибка загрузки из API:", error.message); + console.log("📦 Использую тестовые данные..."); + } +}; -const distPath = resolve(__dirname, '../dist'); -const indexHtmlPath = resolve(distPath, 'index.html'); +const distPath = resolve(__dirname, "../dist"); +const indexHtmlPath = resolve(distPath, "index.html"); if (!existsSync(indexHtmlPath)) { - console.error('❌ Сначала запустите npm run build'); + console.error("❌ Сначала запустите npm run build"); process.exit(1); } // Читаем исходный HTML -let baseHtml = readFileSync(indexHtmlPath, 'utf-8'); +let baseHtml = readFileSync(indexHtmlPath, "utf-8"); // Добавляем базовые мета-теги для каждой страницы -const pages = { - '/': { - title: 'Магазин труб - Главная', - description: 'Купить канализационные трубы по низким ценам' +const pages = [ + { + path: "/", + title: "Магазин труб - Главная", + description: + "Купить канализационные трубы, фитинги и комплектующие по низким ценам.", }, - '/products': { - title: 'Каталог труб для канализации', - description: 'Широкий выбор труб, фитингов и комплектующих' + { + path: "/products", + title: "Каталог труб и фитингов для канализации", + description: + "Широкий выбор канализационных труб ПВХ, фитингов, тройников, переходов, колен. Высокое качество, низкие цены.", }, - '/about': { - title: 'О магазине труб', - description: 'Информация о нашей компании' - } -}; + { + path: "/about", + title: "О магазине труб - Доставка и гарантия", + description: + "Информация о нашей компании. Как мы работаем, условия доставки, гарантия на все товары.", + }, +]; -routes.forEach(route => { - const pageInfo = pages[route] || pages['/']; - - // Заменяем мета-теги в HTML - let html = baseHtml - .replace(/.*?<\/title>/, `<title>${pageInfo.title}`) - .replace( - //, - `` +const allRoutes = [...pages]; + +// Добавляем маршруты товаров +for (const product of products) { + allRoutes.push({ + path: `/product/${product.id}`, + description: product.description, + title: product.full_name, + }); +} + +let successCount = 0; +let errorCount = 0; + +for (const route of allRoutes) { + try { + // Заменяем мета-теги + let html = baseHtml + .replace( + /.*?<\/title>/, + `<title>${escapeHtml(route.title)}`, + ) + .replace( + //, + ``, + ); + + // Добавляем Open Graph теги (для соцсетей) + html = html.replace( + "", + ` + + + +`, ); - - // Определяем путь для сохранения - let outputPath; - if (route === '/') { - outputPath = indexHtmlPath; - } else { - const routeDir = resolve(distPath, route.substring(1)); - if (!existsSync(routeDir)) { - mkdirSync(routeDir, { recursive: true }); - } - outputPath = resolve(routeDir, 'index.html'); - } - - writeFileSync(outputPath, html); - console.log(`✅ ${route} → ${outputPath}`); -}); -console.log('✨ Done!'); \ No newline at end of file + // Определяем путь для сохранения + let outputPath; + if (route.path === "/") { + outputPath = indexHtmlPath; + } else { + const routeDir = resolve(distPath, route.path.substring(1)); + if (!existsSync(routeDir)) { + mkdirSync(routeDir, { recursive: true }); + } + outputPath = resolve(routeDir, "index.html"); + } + + writeFileSync(outputPath, html); + console.log(`✅ ${route.path} → ${outputPath}`); + successCount++; + } catch (error) { + console.error(`❌ Ошибка при генерации ${route.path}:`, error.message); + errorCount++; + } +} + +const urls = allRoutes.map(route => ({ + url: route.path, + lastmod: new Date().toISOString().split('T')[0], + priority: route.path === '/' ? 1.0 : route.path.startsWith('/product') ? 0.8 : 0.7 + })); + + const sitemapContent = generateSitemap(urls, 'https://pvh.projects.rustprogersteam.ru'); // замените на ваш домен + const sitemapPath = resolve(distPath, 'sitemap.xml'); + writeFileSync(sitemapPath, sitemapContent); + console.log(`\n🗺️ Sitemap создан: ${sitemapPath}`); + + +// ============================================ +// ВСПОМОГАТЕЛЬНЫЕ ФУНКЦИИ +// ============================================ + +function escapeHtml(text) { + return text + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +function generateSitemap(urls, baseUrl) { + return ` + +${urls.map(item => ` + ${baseUrl}${item.url} + ${item.lastmod} + ${item.priority} + `).join('\n')} +`; +} + +console.log("✨ Done!");