From 8889c6bee79d612eba146abd36458169bd2be374 Mon Sep 17 00:00:00 2001 From: Oleg Urin Date: Tue, 14 Apr 2026 20:24:40 +0300 Subject: [PATCH] =?UTF-8?q?=D0=B8=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=B5=D0=BD=D0=BD=D1=8B=D0=B9=20=D0=BF=D1=80=D1=80=D0=B5=D0=BD?= =?UTF-8?q?=D0=B4=D1=80=D0=B8=D0=BD=D0=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- scripts/prerender.js | 209 +++++++++++++++++++++++++++++-------------- 1 file changed, 143 insertions(+), 66 deletions(-) diff --git a/scripts/prerender.js b/scripts/prerender.js index 316154e..bd094f2 100644 --- a/scripts/prerender.js +++ b/scripts/prerender.js @@ -1,20 +1,27 @@ 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 products = async function getProducts() { +async function getProducts() { try { - console.log("📡 Загрузка товаров из API..."); - const response = await client.get("/productList/"); - return response.data; + const response = await fetch('https://pvh.projects.rustprogersteam.ru/api/productList'); + const data = await response.json(); + + if (Array.isArray(data)) { + console.log(`✅ Загружено ${data.length} товаров`); + return data; + } + return []; } catch (error) { - console.error("❌ Ошибка загрузки из API:", error.message); - console.log("📦 Использую тестовые данные..."); + console.error('Ошибка:', error.message); + return []; } -}; +} + +// Получаем товары +const products = await getProducts(); const distPath = resolve(__dirname, "../dist"); const indexHtmlPath = resolve(distPath, "index.html"); @@ -27,65 +34,149 @@ if (!existsSync(indexHtmlPath)) { // Читаем исходный HTML let baseHtml = readFileSync(indexHtmlPath, "utf-8"); -// Добавляем базовые мета-теги для каждой страницы -const pages = [ +// ============================================ +// ФУНКЦИИ ДЛЯ ГЕНЕРАЦИИ КОНТЕНТА +// ============================================ + +function escapeHtml(text) { + if (!text) return ''; + return String(text) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +// Генерация страницы товара +function generateProductPage(product) { + return ` +
+

${escapeHtml(product.full_name)}

+
+

${escapeHtml(product.description || 'Описание отсутствует')}

+
+
+

Артикул: ${product.id}

+
+
`; +} + +// Генерация главной страницы +function generateHomePage(products) { + const topProducts = products.slice(0, 6).map(product => ` +
+

${escapeHtml(product.full_name || `Товар ${product.id}`)}

+ Подробнее +
`).join(''); + + return ` +
+

Добро пожаловать в магазин труб!

+

Широкий выбор канализационных труб, фитингов и комплектующих.

+

Популярные товары

+
+ ${topProducts} +
+ Перейти в каталог +
`; +} + +// Генерация страницы каталога +function generateCatalogPage(products) { + const allProducts = products.map(product => ` +
+

${escapeHtml(product.full_name || `Товар ${product.id}`)}

+

${escapeHtml((product.description || '').slice(0, 150))}...

+ Подробнее +
`).join(''); + + return ` +
+

Каталог товаров

+
+ ${allProducts} +
+
`; +} + +// Генерация страницы "О нас" +function generateAboutPage() { + return ` +
+

О магазине

+

Мы занимаемся продажей качественных труб и фитингов для канализации.

+

Наши преимущества:

+ +
`; +} + +const routes = [ { path: "/", title: "Магазин труб - Главная", - description: - "Купить канализационные трубы, фитинги и комплектующие по низким ценам.", + description: "Купить канализационные трубы, фитинги и комплектующие по низким ценам.", + getContent: () => generateHomePage(products) }, { path: "/products", title: "Каталог труб и фитингов для канализации", - description: - "Широкий выбор канализационных труб ПВХ, фитингов, тройников, переходов, колен. Высокое качество, низкие цены.", + description: "Широкий выбор канализационных труб ПВХ, фитингов, тройников, переходов, колен.", + getContent: () => generateCatalogPage(products) }, { path: "/about", title: "О магазине труб - Доставка и гарантия", - description: - "Информация о нашей компании. Как мы работаем, условия доставки, гарантия на все товары.", - }, + description: "Информация о нашей компании. Как мы работаем, условия доставки.", + getContent: () => generateAboutPage() + } ]; -const allRoutes = [...pages]; - -// Добавляем маршруты товаров +// Добавляем страницы товаров for (const product of products) { - allRoutes.push({ + routes.push({ path: `/product/${product.id}`, - description: product.description, title: product.full_name, + description: (product.description || ''), + getContent: () => generateProductPage(product) }); } +console.log(`\n📄 Всего страниц для генерации: ${routes.length}\n`); + let successCount = 0; -let errorCount = 0; -for (const route of allRoutes) { +for (const route of routes) { try { - // Заменяем мета-теги - let html = baseHtml - .replace( - /.*?<\/title>/, - `<title>${escapeHtml(route.title)}`, - ) - .replace( - //, - ``, - ); - - // Добавляем Open Graph теги (для соцсетей) + // Генерируем контент для этой страницы + const pageContent = route.getContent(); + + // Вставляем контент в #root + let html = baseHtml; + + // Меняем title + html = html.replace(/.*?<\/title>/, `<title>${escapeHtml(route.title)}`); + + // Меняем meta description + html = html.replace(//, ``); + + // Вставляем контент в #root (ВАЖНО!) + html = html.replace('
', `
${pageContent}
`); + + // Добавляем Open Graph теги html = html.replace( "", ` -`, +` ); - + // Определяем путь для сохранения let outputPath; if (route.path === "/") { @@ -97,40 +188,21 @@ for (const route of allRoutes) { } outputPath = resolve(routeDir, "index.html"); } - + writeFileSync(outputPath, html); - console.log(`✅ ${route.path} → ${outputPath}`); + console.log(`✅ ${route.path}`); 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, '''); -} +const urls = routes.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 +})); function generateSitemap(urls, baseUrl) { return ` @@ -143,4 +215,9 @@ ${urls.map(item => ` `; } -console.log("✨ Done!"); +const sitemapContent = generateSitemap(urls, 'https://pvh.projects.rustprogersteam.ru'); +const sitemapPath = resolve(distPath, 'sitemap.xml'); +writeFileSync(sitemapPath, sitemapContent); + +console.log(`\n✨ Готово! Сгенерировано ${successCount} страниц.`); +console.log(`🗺️ Sitemap: ${sitemapPath}`);