исправил скрипт для пререндеринга, сделал получение страниц динамическим добавил гннерацию карты
This commit is contained in:
1 parent
b7027d1183
commit
c6b9001f74
1 file changed
+124
-47
+124
-47
@@ -1,69 +1,146 @@
|
|||||||
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
|
import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
|
||||||
import { resolve, dirname } from 'path';
|
import { resolve, dirname } from "path";
|
||||||
import { fileURLToPath } from 'url';
|
import { fileURLToPath } from "url";
|
||||||
|
import { client } from "../src/api/client";
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||||
|
|
||||||
// Список всех страниц
|
const products = async function getProducts() {
|
||||||
const routes = [
|
try {
|
||||||
'/',
|
console.log("📡 Загрузка товаров из API...");
|
||||||
'/products',
|
const response = await client.get("/productList/");
|
||||||
'/about',
|
return response.data;
|
||||||
// добавьте свои URL
|
} catch (error) {
|
||||||
];
|
console.error("❌ Ошибка загрузки из API:", error.message);
|
||||||
|
console.log("📦 Использую тестовые данные...");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const distPath = resolve(__dirname, '../dist');
|
const distPath = resolve(__dirname, "../dist");
|
||||||
const indexHtmlPath = resolve(distPath, 'index.html');
|
const indexHtmlPath = resolve(distPath, "index.html");
|
||||||
|
|
||||||
if (!existsSync(indexHtmlPath)) {
|
if (!existsSync(indexHtmlPath)) {
|
||||||
console.error('❌ Сначала запустите npm run build');
|
console.error("❌ Сначала запустите npm run build");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Читаем исходный HTML
|
// Читаем исходный HTML
|
||||||
let baseHtml = readFileSync(indexHtmlPath, 'utf-8');
|
let baseHtml = readFileSync(indexHtmlPath, "utf-8");
|
||||||
|
|
||||||
// Добавляем базовые мета-теги для каждой страницы
|
// Добавляем базовые мета-теги для каждой страницы
|
||||||
const pages = {
|
const pages = [
|
||||||
'/': {
|
{
|
||||||
title: 'Магазин труб - Главная',
|
path: "/",
|
||||||
description: 'Купить канализационные трубы по низким ценам'
|
title: "Магазин труб - Главная",
|
||||||
|
description:
|
||||||
|
"Купить канализационные трубы, фитинги и комплектующие по низким ценам.",
|
||||||
},
|
},
|
||||||
'/products': {
|
{
|
||||||
title: 'Каталог труб для канализации',
|
path: "/products",
|
||||||
description: 'Широкий выбор труб, фитингов и комплектующих'
|
title: "Каталог труб и фитингов для канализации",
|
||||||
|
description:
|
||||||
|
"Широкий выбор канализационных труб ПВХ, фитингов, тройников, переходов, колен. Высокое качество, низкие цены.",
|
||||||
},
|
},
|
||||||
'/about': {
|
{
|
||||||
title: 'О магазине труб',
|
path: "/about",
|
||||||
description: 'Информация о нашей компании'
|
title: "О магазине труб - Доставка и гарантия",
|
||||||
}
|
description:
|
||||||
};
|
"Информация о нашей компании. Как мы работаем, условия доставки, гарантия на все товары.",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
routes.forEach(route => {
|
const allRoutes = [...pages];
|
||||||
const pageInfo = pages[route] || pages['/'];
|
|
||||||
|
|
||||||
// Заменяем мета-теги в HTML
|
// Добавляем маршруты товаров
|
||||||
let html = baseHtml
|
for (const product of products) {
|
||||||
.replace(/<title>.*?<\/title>/, `<title>${pageInfo.title}</title>`)
|
allRoutes.push({
|
||||||
.replace(
|
path: `/product/${product.id}`,
|
||||||
/<meta name="description".*?>/,
|
description: product.description,
|
||||||
`<meta name="description" content="${pageInfo.description}">`
|
title: product.full_name,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
let successCount = 0;
|
||||||
|
let errorCount = 0;
|
||||||
|
|
||||||
|
for (const route of allRoutes) {
|
||||||
|
try {
|
||||||
|
// Заменяем мета-теги
|
||||||
|
let html = baseHtml
|
||||||
|
.replace(
|
||||||
|
/<title>.*?<\/title>/,
|
||||||
|
`<title>${escapeHtml(route.title)}</title>`,
|
||||||
|
)
|
||||||
|
.replace(
|
||||||
|
/<meta name="description".*?>/,
|
||||||
|
`<meta name="description" content="${escapeHtml(route.description)}">`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Добавляем Open Graph теги (для соцсетей)
|
||||||
|
html = html.replace(
|
||||||
|
"</head>",
|
||||||
|
` <meta property="og:title" content="${escapeHtml(route.title)}">
|
||||||
|
<meta property="og:description" content="${escapeHtml(route.description)}">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta name="robots" content="index, follow">
|
||||||
|
</head>`,
|
||||||
);
|
);
|
||||||
|
|
||||||
// Определяем путь для сохранения
|
// Определяем путь для сохранения
|
||||||
let outputPath;
|
let outputPath;
|
||||||
if (route === '/') {
|
if (route.path === "/") {
|
||||||
outputPath = indexHtmlPath;
|
outputPath = indexHtmlPath;
|
||||||
} else {
|
} else {
|
||||||
const routeDir = resolve(distPath, route.substring(1));
|
const routeDir = resolve(distPath, route.path.substring(1));
|
||||||
if (!existsSync(routeDir)) {
|
if (!existsSync(routeDir)) {
|
||||||
mkdirSync(routeDir, { recursive: true });
|
mkdirSync(routeDir, { recursive: true });
|
||||||
|
}
|
||||||
|
outputPath = resolve(routeDir, "index.html");
|
||||||
}
|
}
|
||||||
outputPath = resolve(routeDir, 'index.html');
|
|
||||||
|
writeFileSync(outputPath, html);
|
||||||
|
console.log(`✅ ${route.path} → ${outputPath}`);
|
||||||
|
successCount++;
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`❌ Ошибка при генерации ${route.path}:`, error.message);
|
||||||
|
errorCount++;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
writeFileSync(outputPath, html);
|
const urls = allRoutes.map(route => ({
|
||||||
console.log(`✅ ${route} → ${outputPath}`);
|
url: route.path,
|
||||||
});
|
lastmod: new Date().toISOString().split('T')[0],
|
||||||
|
priority: route.path === '/' ? 1.0 : route.path.startsWith('/product') ? 0.8 : 0.7
|
||||||
|
}));
|
||||||
|
|
||||||
console.log('✨ Done!');
|
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, '"')
|
||||||
|
.replace(/'/g, ''');
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateSitemap(urls, baseUrl) {
|
||||||
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||||
|
${urls.map(item => ` <url>
|
||||||
|
<loc>${baseUrl}${item.url}</loc>
|
||||||
|
<lastmod>${item.lastmod}</lastmod>
|
||||||
|
<priority>${item.priority}</priority>
|
||||||
|
</url>`).join('\n')}
|
||||||
|
</urlset>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("✨ Done!");
|
||||||
Reference in new issue
Block a user