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:
BIN
client/dist/image.png
vendored
Normal file
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
BIN
client/dist/smileys.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.2 KiB |
@@ -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">
|
// Ersetze Meta-Tags in der gebauten HTML
|
||||||
|
baseHTML = baseHTML.replace(/<title>.*?<\/title>/, `<title>${meta.title}</title>`);
|
||||||
<!-- Open Graph Tags -->
|
|
||||||
|
// 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 -->
|
|
||||||
<link rel="canonical" href="${meta.ogUrl}">
|
// Entferne alte OG/Twitter/Canonical Tags falls vorhanden
|
||||||
|
baseHTML = baseHTML.replace(/<meta property="og:[^>]*>/g, '');
|
||||||
<!-- Favicon -->
|
baseHTML = baseHTML.replace(/<meta name="twitter:[^>]*>/g, '');
|
||||||
<link rel="icon" type="image/png" href="/static/favicon.png">
|
baseHTML = baseHTML.replace(/<link rel="canonical"[^>]*>/g, '');
|
||||||
</head>
|
|
||||||
<body>
|
// Füge neue Tags vor </head> ein
|
||||||
<div id="app"></div>
|
baseHTML = baseHTML.replace('</head>', `${ogTags}\n</head>`);
|
||||||
<script type="module" src="/src/main.js"></script>
|
|
||||||
</body>
|
// Füge robots meta hinzu falls nicht vorhanden
|
||||||
</html>`;
|
if (!baseHTML.includes('<meta name="robots"')) {
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
@@ -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);
|
||||||
res.send(html);
|
if (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);
|
||||||
res.send(html);
|
if (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.');
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user