Enhance SEO meta tag handling in generateHTML function by adding support for reading built index.html, updating existing tags, and implementing fallback logic for missing files.

This commit is contained in:
Torsten Schulz (local)
2025-12-05 08:03:20 +01:00
parent b6eef5100f
commit 2ee52523ff
3 changed files with 71 additions and 32 deletions

BIN
client/dist/image.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
client/dist/smileys.png vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -1,4 +1,4 @@
import { readFileSync } from 'fs'; import { readFileSync, existsSync } from 'fs';
import { join } from 'path'; import { join } from 'path';
// SEO-Meta-Daten für verschiedene Routen // SEO-Meta-Daten für verschiedene Routen
@@ -26,43 +26,62 @@ const seoData = {
}; };
// HTML-Template für Pre-Rendering // HTML-Template für Pre-Rendering
function generateHTML(route, meta) { function generateHTML(route, meta, __dirname) {
const baseHTML = `<!DOCTYPE html> // Versuche, die gebaute index.html zu lesen
<html lang="de"> const distIndexPath = join(__dirname, '../docroot/dist/index.html');
<head> let baseHTML;
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- SEO Meta Tags --> if (existsSync(distIndexPath)) {
<title>${meta.title}</title> // Verwende die gebaute index.html (mit korrekten Asset-Pfaden von Vite)
<meta name="description" content="${meta.description}"> baseHTML = readFileSync(distIndexPath, 'utf-8');
<meta name="keywords" content="${meta.keywords}">
<meta name="robots" content="index, follow">
<!-- Open Graph Tags --> // Ersetze Meta-Tags in der gebauten HTML
baseHTML = baseHTML.replace(/<title>.*?<\/title>/, `<title>${meta.title}</title>`);
// Ersetze oder füge description hinzu
if (baseHTML.includes('<meta name="description"')) {
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 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}">
<meta property="og:url" content="${meta.ogUrl}"> <meta property="og:url" content="${meta.ogUrl}">
<meta property="og:image" content="${meta.ogImage}"> <meta property="og:image" content="${meta.ogImage}">
<!-- Twitter Card -->
<meta name="twitter:card" content="summary"> <meta name="twitter:card" content="summary">
<meta name="twitter:title" content="${meta.ogTitle}"> <meta name="twitter:title" content="${meta.ogTitle}">
<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}">`;
<!-- Canonical URL --> // Entferne alte OG/Twitter/Canonical Tags falls vorhanden
<link rel="canonical" href="${meta.ogUrl}"> baseHTML = baseHTML.replace(/<meta property="og:[^>]*>/g, '');
baseHTML = baseHTML.replace(/<meta name="twitter:[^>]*>/g, '');
baseHTML = baseHTML.replace(/<link rel="canonical"[^>]*>/g, '');
<!-- Favicon --> // Füge neue Tags vor </head> ein
<link rel="icon" type="image/png" href="/static/favicon.png"> baseHTML = baseHTML.replace('</head>', `${ogTags}\n</head>`);
</head>
<body> // Füge robots meta hinzu falls nicht vorhanden
<div id="app"></div> if (!baseHTML.includes('<meta name="robots"')) {
<script type="module" src="/src/main.js"></script> baseHTML = baseHTML.replace('</head>', ` <meta name="robots" content="index, follow">\n</head>`);
</body> }
</html>`; } 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;
} }
@@ -76,15 +95,35 @@ export function setupSEORoutes(app, __dirname) {
// Pre-Rendering für Hauptseite // Pre-Rendering für Hauptseite
app.get('/', (req, res) => { app.get('/', (req, res) => {
const meta = seoData['/']; const meta = seoData['/'];
const html = generateHTML('/', meta); const html = generateHTML('/', meta, __dirname);
if (html) {
res.send(html); res.send(html);
} else {
// Fallback: Verwende die gebaute index.html direkt (ohne Meta-Tag-Anpassung)
const distIndexPath = join(__dirname, '../docroot/dist/index.html');
if (existsSync(distIndexPath)) {
res.sendFile(distIndexPath);
} else {
res.status(500).send('Gebaute index.html nicht gefunden. Bitte führe "npm run build" aus.');
}
}
}); });
// Pre-Rendering für Partners-Seite // Pre-Rendering für Partners-Seite
app.get('/partners', (req, res) => { app.get('/partners', (req, res) => {
const meta = seoData['/partners']; const meta = seoData['/partners'];
const html = generateHTML('/partners', meta); const html = generateHTML('/partners', meta, __dirname);
if (html) {
res.send(html); res.send(html);
} else {
// Fallback: Verwende die gebaute index.html direkt (ohne Meta-Tag-Anpassung)
const distIndexPath = join(__dirname, '../docroot/dist/index.html');
if (existsSync(distIndexPath)) {
res.sendFile(distIndexPath);
} else {
res.status(500).send('Gebaute index.html nicht gefunden. Bitte führe "npm run build" aus.');
}
}
}); });
} }