Node.js Express中无需模板引擎添加通用页眉页脚的方法
Nice one! Since you’re avoiding template engines entirely, you can handle this by reading your header, main content, and footer files directly, concatenating their content, and sending the combined HTML as a single response. Here’s a step-by-step breakdown with code examples:
Step 1: Set up dependencies and file paths
First, you’ll need Node’s fs.promises for async file reading (to avoid callback hell) and path to safely handle file paths. Make sure your HTMLLOCATION points to the correct directory containing your HTML files.
const fs = require('fs').promises; const path = require('path'); const HTMLLOCATION = './path/to/your/html/directory'; // Replace with your actual path
Step 2: Modify your route handler to concatenate files
Replace your existing sendDashboardHtml function with an async version that reads all three files, combines them, and sends the result. We’ll add error handling to catch any file-reading issues:
exports.sendDashboardHtml = async function(req, res, next) { try { // Read each HTML file's content as UTF-8 strings const header = await fs.readFile(path.join(HTMLLOCATION, 'header.html'), 'utf8'); const dashboard = await fs.readFile(path.join(HTMLLOCATION, 'dashboard.html'), 'utf8'); const footer = await fs.readFile(path.join(HTMLLOCATION, 'footer.html'), 'utf8'); // Combine the parts into a single HTML string const fullPage = header + dashboard + footer; // Set the correct content type and send the response res.setHeader('Content-Type', 'text/html'); res.send(fullPage); } catch (err) { // Log the error and pass it to Express's error-handling middleware console.error('Failed to load HTML parts:', err); next(err); } };
Step 3: Optimize with caching (optional but recommended)
If your header and footer don’t change often, you can preload them into memory when your app starts instead of reading them on every request. This reduces disk I/O and improves performance:
// Preload header and footer once at app startup let cachedHeader, cachedFooter; (async function loadStaticParts() { try { cachedHeader = await fs.readFile(path.join(HTMLLOCATION, 'header.html'), 'utf8'); cachedFooter = await fs.readFile(path.join(HTMLLOCATION, 'footer.html'), 'utf8'); console.log('Header and footer cached successfully'); } catch (err) { console.error('Critical error loading static HTML parts:', err); process.exit(1); // Exit if we can't load essential parts } })(); exports.sendDashboardHtml = async function(req, res, next) { try { // Only read the dynamic dashboard content on each request const dashboard = await fs.readFile(path.join(HTMLLOCATION, 'dashboard.html'), 'utf8'); const fullPage = cachedHeader + dashboard + cachedFooter; res.setHeader('Content-Type', 'text/html'); res.send(fullPage); } catch (err) { console.error('Failed to load dashboard content:', err); next(err); } };
Key Notes:
- Always use
path.join()to construct file paths instead of string concatenation—it avoids issues with trailing slashes and cross-platform compatibility. - Specify
'utf8'when reading files to get string content instead of raw Buffer data, which prevents garbled output. - Error handling is crucial here—if any file is missing or unreadable, passing the error to
next()lets Express handle it gracefully (e.g., returning a 500 status code).
内容的提问来源于stack exchange,提问作者sunny jindal

