HTML tĩnh (static HTML) không hỗ trợ include/import file khác. Để tách Header, Footer, Content thành các file riêng và tái sử dụng, có các giải pháp:
1. Server-Side Includes (SSI) - Apache/Nginx
<!-- index.html (cần rename .shtml hoặc config server parse .html) --> <!--#include virtual="/includes/header.html" --> <main>Nội dung trang</main> <!--#include virtual="/includes/footer.html" -->
Cấu hình Nginx: ssi on; trong location block.
2. PHP Include (Phổ biến nhất cho shared hosting)
<!-- header.php --> <header><nav>...</nav></header> <!-- footer.php --> <footer>Copyright 2024</footer> <!-- index.php --> <?php include 'header.php'; ?> <main>Nội dung trang</main> <?php include 'footer.php'; ?>
3. JavaScript Client-side Load (AJAX/Fetch) - Không cần backend
<div id="header-container"></div>
<main>Nội dung trang</main>
<div id="footer-container"></div>
<script>
async function loadPartial(selector, url) {
try {
const response = await fetch(url);
const html = await response.text();
document.querySelector(selector).innerHTML = html;
// Khởi tạo lại script/component trong partial nếu cần
} catch (e) {
console.error('Load partial failed:', url, e);
}
}
loadPartial('#header-container', '/includes/header.html');
loadPartial('#footer-container', '/includes/footer.html');
4. ES6 Modules / Web Components (Modern)
<!-- header-component.js -->
class HeaderComponent extends HTMLElement {
connectedCallback() {
this.innerHTML = `<header>...</header>`;
}
}
customElements.define('app-header', HeaderComponent);
// index.html
<script type="module" src="header-component.js"></script>
<app-header></app-header>
5. Build Tools / Static Site Generators (Khuyên dùng Production)
| Tool | Loại | Include syntax |
|---|---|---|
| Vite | Bundler | import './header.html' (plugin), hoặc vite-plugin-handlebars |
| Astro | SSG | <Header /> (component) |
| 11ty (Eleventy) | SSG | {% include 'header.njk' %} |
| Hugo | SSG | {{ partial "header.html" }} |
| Next.js | React Framework | import Header from '@/components/Header' |
| Gulp/Grunt | Task Runner | fileinclude plugin |
So sánh & Khuyến nghị
| Phương pháp | SEO | Performance | Độ phức tạp | Phù hợp |
|---|---|---|---|---|
| SSI / PHP | ✅ Tốt | ✅ Nhanh (server render) | Thấp | Shared hosting, legacy |
| JS Fetch (Client) | ❌ Kém (crawler không chạy JS tốt) | ⚠️ Chậm (waterfall request) | Thấp | Prototype, dashboard nội bộ |
| Web Components | ⚠️ Trung bình | ⚠️ Cần polyfill cũ | Trung bình | Design system, micro-frontend |
| SSG (Astro, 11ty, Hugo) | ✅ Tốt nhất | ✅ Nhanh nhất (static files) | Trung bình | Production website |
| Framework (Next, Nuxt) | ✅ Tốt (SSR/SSG) | ✅ Tốt | Cao | Web App phức tạp |
Lưu ý CORS cho JS Fetch
Nếu load partial từ domain khác: Server phải trả Access-Control-Allow-Origin: * hoặc domain cụ thể.