Nginx-SSI:在返回静态 HTML 之前,先在服务端把 HTML 里的特定指令替换成动态内容

Nginx SSI(Server Side Includes)

一句话总结: SSI 让 Nginx 在返回静态 HTML 之前,先在服务端把 HTML 里的特定指令替换成动态内容,类似"简易版 PHP include"。

核心原理

用户请求 → Nginx 读取 .html 文件 → 遇到 SSI 指令 → 执行替换 → 返回最终 HTML``

它不是完整的编程语言,只是一组 HTML 注释形式的指令,Nginx 识别后做简单处理。

常用指令

指令 作用 示例
include 包含另一个文件 <!--#include file="header.html" -->
echo 输出变量(日期、环境变量等) <!--#echo var="DATE_LOCAL" -->
set 设置自定义变量 <!--#set var="name" value="World" -->
if/elif/else/endif 条件判断 <!--#if expr="$name = World" -->Hi<!--#endif -->
exec 执行系统命令 <!--#exec cmd="date" -->
config 配置时间格式等 <!--#config timefmt="%Y-%m-%d" -->
flastmod 输出文件最后修改时间 <!--#flastmod file="index.html" -->
printenv 输出环境变量 <!--#printenv var="REMOTE_ADDR" -->

配置方式

复制代码
# nginx

location / {
    ssi on;                              # 开启 SSI
    ssi_silent_errors on;                # 出错时静默(不返回 500)
    ssi_types text/html;                 # 指定哪些 MIME 类型解析 SSI
    ssi_value_length 256;                # 变量值最大长度
}

实际使用示例

典型使用场景

场景 说明
公共页头/页脚 多个静态页面共用 header、footer,不用手动复制
显示动态时间/IP 纯静态站点也能显示"最后更新时间"
简单条件内容 根据变量显示不同内容(但逻辑很弱)

局限性(很重要)

问题 说明
性能差 每个请求都要解析 SSI 指令,高并发下明显拖累
功能弱 没有循环、没有数组、没有真正的逻辑,复杂需求做不了
已过时 现在基本被 SSI 模板引擎(如 Liquid)、后端渲染(PHP/Node)替代
仅限 HTML 只对指定 MIME 类型生效,CSS/JS 里的 SSI 不会被解析

什么时候该用?

✅ 纯静态站点,只需要嵌入公共片段、显示时间

❌ 需要复杂逻辑 → 用后端语言

❌ 高流量站点 → 用缓存或构建时生成(SSG)

简单说:SSI 是 Nginx 给纯静态网站留的一个"小后门",够用但别依赖。

SSI 的 include 确实能实现"把组件拆出来、按需引入"的效果:

React/Vue 的 <Header /> ≈ SSI 的 <!--#include file="header.html" -->

是的,但只是最原始的版本。

对比一下就清楚了

能力 SSI include 现代组件(React/Vue)
拆分公共部分 ✅ 可以 ✅ 可以
多页面复用 ✅ 可以 ✅ 可以
传参(props) ❌ 不行 ✅ 可以
条件渲染 ⚠️ 极弱(if/else) ✅ 完全支持
循环列表 ❌ 不行 ✅ 可以
状态管理 ❌ 没有 ✅ 有
交互响应 ❌ 没有(纯服务端) ✅ 有
缓存友好 ⚠️ 每次请求都解析 ✅ 虚拟DOM diff

所以本质上

SSI = 服务端的字符串拼接,每次请求把碎片拼成完整 HTML 返给浏览器。

它能做到的"组件化":

复制代码
<!-- header.html -->
<nav>...</nav>

<!-- footer.html -->
<footer>...</footer>

<!-- index.html -->
<!--#include file="header.html" -->
<main>页面内容</main>
<!--#include file="footer.html" -->

这跟 React 里把 <Header /><Footer /> 抽成组件,思路完全一样,只是实现方式是几十年前的技术。

一句话

SSI 能实现"静态组件引入",但没有交互、没有状态,本质是服务端的 include,不是真正的组件化。够用,但别指望它能替代任何现代框架。