Improve SEO handling in generateHTML function by adding detailed logging, enhancing error handling for missing index.html, and ensuring proper path resolution for production environments.

This commit is contained in:
Torsten Schulz (local)
2025-12-05 08:56:29 +01:00
parent 2ee52523ff
commit 99097cf213

View File

@@ -1,5 +1,5 @@
import { readFileSync, existsSync } from 'fs'; import { readFileSync, existsSync } from 'fs';
import { join } from 'path'; import { join, resolve } from 'path';
// SEO-Meta-Daten für verschiedene Routen // SEO-Meta-Daten für verschiedene Routen
const seoData = { const seoData = {
@@ -29,31 +29,39 @@ const seoData = {
function generateHTML(route, meta, __dirname) { function generateHTML(route, meta, __dirname) {
// Versuche, die gebaute index.html zu lesen // Versuche, die gebaute index.html zu lesen
const distIndexPath = join(__dirname, '../docroot/dist/index.html'); const distIndexPath = join(__dirname, '../docroot/dist/index.html');
let baseHTML;
if (existsSync(distIndexPath)) { console.log('[SEO] Prüfe gebaute index.html:', distIndexPath);
// Verwende die gebaute index.html (mit korrekten Asset-Pfaden von Vite) console.log('[SEO] Datei existiert:', existsSync(distIndexPath));
baseHTML = readFileSync(distIndexPath, 'utf-8');
if (!existsSync(distIndexPath)) {
// Ersetze Meta-Tags in der gebauten HTML // Fallback: Gebaute index.html nicht gefunden
baseHTML = baseHTML.replace(/<title>.*?<\/title>/, `<title>${meta.title}</title>`); console.error('WARNUNG: Gebaute index.html nicht gefunden:', distIndexPath);
return null;
// Ersetze oder füge description hinzu }
if (baseHTML.includes('<meta name="description"')) {
baseHTML = baseHTML.replace(/<meta name="description"[^>]*>/, `<meta name="description" content="${meta.description}">`); // Verwende die gebaute index.html (mit korrekten Asset-Pfaden von Vite)
} else { let baseHTML = readFileSync(distIndexPath, 'utf-8');
baseHTML = baseHTML.replace('</head>', ` <meta name="description" content="${meta.description}">\n</head>`); console.log('[SEO] Gebaute HTML geladen, Länge:', baseHTML.length);
}
// Ersetze Meta-Tags in der gebauten HTML
// Ersetze oder füge keywords hinzu baseHTML = baseHTML.replace(/<title>.*?<\/title>/, `<title>${meta.title}</title>`);
if (baseHTML.includes('<meta name="keywords"')) {
baseHTML = baseHTML.replace(/<meta name="keywords"[^>]*>/, `<meta name="keywords" content="${meta.keywords}">`); // Ersetze oder füge description hinzu
} else { if (baseHTML.includes('<meta name="description"')) {
baseHTML = baseHTML.replace('</head>', ` <meta name="keywords" content="${meta.keywords}">\n</head>`); baseHTML = baseHTML.replace(/<meta name="description"[^>]*>/, `<meta name="description" content="${meta.description}">`);
} } else {
baseHTML = baseHTML.replace('</head>', ` <meta name="description" content="${meta.description}">\n</head>`);
// Ersetze oder füge Open Graph Tags hinzu }
const ogTags = `
// Ersetze oder füge keywords hinzu
if (baseHTML.includes('<meta name="keywords"')) {
baseHTML = baseHTML.replace(/<meta name="keywords"[^>]*>/, `<meta name="keywords" content="${meta.keywords}">`);
} else {
baseHTML = baseHTML.replace('</head>', ` <meta name="keywords" content="${meta.keywords}">\n</head>`);
}
// Ersetze oder füge Open Graph Tags hinzu
const ogTags = `
<meta property="og:title" content="${meta.ogTitle}"> <meta property="og:title" content="${meta.ogTitle}">
<meta property="og:description" content="${meta.ogDescription}"> <meta property="og:description" content="${meta.ogDescription}">
<meta property="og:type" content="${meta.ogType}"> <meta property="og:type" content="${meta.ogType}">
@@ -64,23 +72,18 @@ function generateHTML(route, meta, __dirname) {
<meta name="twitter:description" content="${meta.ogDescription}"> <meta name="twitter:description" content="${meta.ogDescription}">
<meta name="twitter:image" content="${meta.ogImage}"> <meta name="twitter:image" content="${meta.ogImage}">
<link rel="canonical" href="${meta.ogUrl}">`; <link rel="canonical" href="${meta.ogUrl}">`;
// Entferne alte OG/Twitter/Canonical Tags falls vorhanden // Entferne alte OG/Twitter/Canonical Tags falls vorhanden
baseHTML = baseHTML.replace(/<meta property="og:[^>]*>/g, ''); baseHTML = baseHTML.replace(/<meta property="og:[^>]*>/g, '');
baseHTML = baseHTML.replace(/<meta name="twitter:[^>]*>/g, ''); baseHTML = baseHTML.replace(/<meta name="twitter:[^>]*>/g, '');
baseHTML = baseHTML.replace(/<link rel="canonical"[^>]*>/g, ''); baseHTML = baseHTML.replace(/<link rel="canonical"[^>]*>/g, '');
// Füge neue Tags vor </head> ein // Füge neue Tags vor </head> ein
baseHTML = baseHTML.replace('</head>', `${ogTags}\n</head>`); baseHTML = baseHTML.replace('</head>', `${ogTags}\n</head>`);
// Füge robots meta hinzu falls nicht vorhanden // Füge robots meta hinzu falls nicht vorhanden
if (!baseHTML.includes('<meta name="robots"')) { if (!baseHTML.includes('<meta name="robots"')) {
baseHTML = baseHTML.replace('</head>', ` <meta name="robots" content="index, follow">\n</head>`); baseHTML = baseHTML.replace('</head>', ` <meta name="robots" content="index, follow">\n</head>`);
}
} else {
// Fallback: Gebaute index.html nicht gefunden - verwende SPA-Fallback
console.error('WARNUNG: Gebaute index.html nicht gefunden:', distIndexPath);
return null;
} }
return baseHTML; return baseHTML;
@@ -92,6 +95,8 @@ export function setupSEORoutes(app, __dirname) {
const IS_PRODUCTION = process.env.NODE_ENV === 'production'; const IS_PRODUCTION = process.env.NODE_ENV === 'production';
if (IS_PRODUCTION) { if (IS_PRODUCTION) {
const distIndexPath = resolve(__dirname, '../docroot/dist/index.html');
// Pre-Rendering für Hauptseite // Pre-Rendering für Hauptseite
app.get('/', (req, res) => { app.get('/', (req, res) => {
const meta = seoData['/']; const meta = seoData['/'];
@@ -100,10 +105,10 @@ export function setupSEORoutes(app, __dirname) {
res.send(html); res.send(html);
} else { } else {
// Fallback: Verwende die gebaute index.html direkt (ohne Meta-Tag-Anpassung) // Fallback: Verwende die gebaute index.html direkt (ohne Meta-Tag-Anpassung)
const distIndexPath = join(__dirname, '../docroot/dist/index.html');
if (existsSync(distIndexPath)) { if (existsSync(distIndexPath)) {
res.sendFile(distIndexPath); res.sendFile(distIndexPath);
} else { } else {
console.error('FEHLER: Gebaute index.html nicht gefunden:', distIndexPath);
res.status(500).send('Gebaute index.html nicht gefunden. Bitte führe "npm run build" aus.'); res.status(500).send('Gebaute index.html nicht gefunden. Bitte führe "npm run build" aus.');
} }
} }
@@ -117,10 +122,10 @@ export function setupSEORoutes(app, __dirname) {
res.send(html); res.send(html);
} else { } else {
// Fallback: Verwende die gebaute index.html direkt (ohne Meta-Tag-Anpassung) // Fallback: Verwende die gebaute index.html direkt (ohne Meta-Tag-Anpassung)
const distIndexPath = join(__dirname, '../docroot/dist/index.html');
if (existsSync(distIndexPath)) { if (existsSync(distIndexPath)) {
res.sendFile(distIndexPath); res.sendFile(distIndexPath);
} else { } else {
console.error('FEHLER: Gebaute index.html nicht gefunden:', distIndexPath);
res.status(500).send('Gebaute index.html nicht gefunden. Bitte führe "npm run build" aus.'); res.status(500).send('Gebaute index.html nicht gefunden. Bitte führe "npm run build" aus.');
} }
} }