静态站使用 Vite + EJS 实现 HTML 模板复用与变量注入
目录
在开发多页面静态站点(如公司官网、产品文档或活动页)时,直接使用原生 HTML 常常会遇到重复劳动的问题:页眉、页脚、导航栏等公共部分需要在每个页面重复书写,如果要修改,就必须手动同步到多个文件,既费时又容易出错。
嗨,我是芦苇Z。今天说说使用 Vite 和 EJS 模板引擎,为静态 HTML 项目引入模块化和集中管理的开发方式。
完成后,你将掌握:
- 如何把公共 HTML 抽离为独立模板。
- 如何集中管理页面元数据和多语言文案。
- 如何在 Vite 中集成 EJS 并自动化配置多页面入口。
- 如何处理 CSS、JavaScript 和图片等静态资源。
- 如何启动开发服务器和构建生产版本。
第 0 步:准备环境
确保你已安装:
- Node.js(推荐 18+)
- 包管理器(npm / pnpm / yarn)
第 1 步:初始化项目
创建 Vite 项目:
npm create vite@latest my-static-site -- --template vanilla cd my-static-site安装依赖:
npm install安装 EJS 插件:
npm install ejs vite-plugin-ejs -D
第 2 步:优化项目结构
我们将 页面、模板片段、数据 和 静态资源 分开存放,使结构更清晰:
my-static-site/
├── src/
│ ├── assets/ # CSS / JS / 图片等资源
│ │ └── main.css
│ ├── data/ # 全站数据
│ │ └── siteData.js
│ ├── pages/ # 页面 HTML
│ │ ├── index.html
│ │ └── zh.html
│ └── partials/ # 可复用模板片段
│ ├── head.html
│ ├── footer.html
│ └── language-selector.html
├── vite.config.js
├── package.json
└── ...
第 3 步:配置 Vite(自动化增强)
在 vite.config.js 中,我们不仅要添加 EJS 插件,还要 自动扫描 src/pages 目录下的所有 HTML 文件作为多页面入口。
import { defineConfig } from 'vite';
import { ViteEjsPlugin } from 'vite-plugin-ejs';
import { resolve } from 'path';
import fs from 'fs';
import siteData from './src/data/siteData.js';
// 自动扫描 src/pages 下的所有 HTML 文件
const pagesDir = resolve(__dirname, 'src/pages');
const entryPoints = fs.readdirSync(pagesDir)
.filter(file => file.endsWith('.html'))
.reduce((acc, file) => {
const name = file.replace(/\.html$/, '');
acc[name] = resolve(pagesDir, file);
return acc;
}, {});
export default defineConfig({
root: pagesDir,
plugins: [
ViteEjsPlugin(siteData, {
root: resolve(__dirname, 'src/partials'),
}),
],
build: {
outDir: '../../dist',
emptyOutDir: true,
rollupOptions: {
input: entryPoints,
},
},
base: './',
});说明
root: 'src/pages':Vite 的根目录,开发时直接访问http://localhost:5173/对应index.html,http://localhost:5173/zh.html对应zh.html。- 使用
fs动态生成rollupOptions.input,避免手动维护入口。base: './'确保构建后资源路径为相对路径,可部署在任意目录下。
第 4 步:集中管理数据
在 src/data/siteData.js 中定义全站和页面数据,适合管理 SEO 元信息 和 多语言文案:
export default {
global: {
siteName: "My Example Site",
author: "芦苇Z",
},
pages: {
index: {
lang: 'en',
title: 'Home',
description: 'Welcome to our amazing static site built with Vite and EJS!',
keywords: 'vite, ejs, static site, homepage',
greeting: 'Welcome',
},
zh: {
lang: 'zh-CN',
title: '首页',
description: '欢迎来到我们用 Vite 和 EJS 构建的静态网站!',
keywords: 'Vite, EJS, 静态站点, 首页',
greeting: '欢迎',
},
},
};第 5 步:编写模板片段与静态资源
head.html
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="<%= page.description %>">
<meta name="keywords" content="<%= page.keywords %>">
<title><%= page.title %> | <%= global.siteName %></title>
<link rel="stylesheet" href="../assets/main.css">footer.html
<footer>
<p>版权所有 © 2025 - <%= global.author %></p>
</footer>language-selector.html
<div class="language-selector">
<label for="language-select">Language:</label>
<select id="language-select" onchange="location = this.value;">
<option value="./index.html" <%= page.lang === 'en' ? 'selected' : '' %>>English</option>
<option value="./zh.html" <%= page.lang === 'zh-CN' ? 'selected' : '' %>>简体中文</option>
</select>
</div>main.css
body {
font-family: sans-serif;
text-align: center;
background-color: #f0f0f0;
}
footer {
margin-top: 2rem;
font-size: 0.9em;
color: #666;
}第 6 步:组装页面
index.html
<!DOCTYPE html>
<html lang="<%= pages.index.lang %>">
<head>
<%- include('head', { global, page: pages.index }) %>
</head>
<body>
<h1><%= pages.index.greeting %></h1>
<%- include('language-selector', { page: pages.index }) %>
<%- include('footer', { global }) %>
</body>
</html>zh.html
<!DOCTYPE html>
<html lang="<%= pages.zh.lang %>">
<head>
<%- include('head', { global, page: pages.zh }) %>
</head>
<body>
<h1><%= pages.zh.greeting %></h1>
<%- include('language-selector', { page: pages.zh }) %>
<%- include('footer', { global }) %>
</body>
</html>语法提示
<%- ... %>:不转义输出,适合引入模板。<%= ... %>:转义输出文本,更安全。
第 7 步:启动与构建
开发模式:
npm run dev访问:
http://localhost:5173/→index.htmlhttp://localhost:5173/zh.html→zh.html
构建生产环境:
npm run build产物会生成在 dist/ 文件夹,可直接部署到任意静态托管平台。
进阶:扩展场景
动态导航菜单
在siteData.js定义菜单数组,在模板中循环渲染,并根据当前页面高亮。主题变量注入
在数据文件中定义颜色,在<style>标签里输出为--primary-color等 CSS 自定义属性,实现换肤。更多静态资源管理
- 图片:直接用
<img>引入,Vite 会自动优化。 - JS:用
<script type="module" src="../assets/main.js"></script>引入即可。
- 图片:直接用
总结
通过 Vite + EJS,我们实现了高效的静态站点开发流程:
- 组件化:公共 UI 片段抽离,避免重复修改。
- 数据驱动:内容与结构分离,便于维护与多语言支持。
- 工程化:享受 Vite 的热更新与资源优化。
- 自动化:新增页面无需修改配置。
适合的应用场景:
- 多语言企业官网
- 营销落地页
- 小型文档站点
如需更复杂的交互,可考虑 Astro / Vue / React。但对中小型静态项目,Vite + EJS 是轻量、高效、易维护的最佳选择。