ssi在现代项目中越来越难用,因其运行完全依赖服务器配置(如apache需开启includes模块、nginx需手动启用ssi并限定.shtml后缀),本地无法直接预览,且仅支持静态拼接,缺乏传参、条件渲染和循环等动态能力,调试路径易错位,多文件包含还易引发dom结构冲突与样式重复。

服务端包含(SSI)为什么在现代项目里越来越难用
SSI 本身不依赖任何框架或构建流程,但它的运行完全绑定服务器配置——Apache 要开 Includes 模块,Nginx 需要手动启用 shtml 类型并配置 ssi on,本地开发时甚至无法直接双击 HTML 文件预览。更关键的是,SSI 只支持静态文件拼接,不能传参、不能条件渲染、不能循环生成列表,遇到带变量的导航栏就只能退回到 PHP 的 include()。
- Apache 默认禁用 SSI,需在
.htaccess或主配置中显式开启:Options +Includes和AddType text/html .shtml - Nginx 不原生支持 SSI,必须用
ssi on;+add_header配合,且只对.shtml后缀生效 - SSI 指令如
<!--#include file="header.html" -->中的路径是相对于当前请求 URL 的,不是文件系统路径,调试时容易错位 - 所有被 include 的内容会直接插入 DOM,如果 header.html 里写了
<style></style>标签,多个页面重复加载会造成样式冲突
Jinja2 / Flask 的 extends 和 include 容易忽略的上下文陷阱
Flask 项目里用 {% extends "base.html" %} 看似简单,但实际部署时经常卡在上下文传递失败或模板路径解析错误上。Jinja2 对语法位置极其敏感,且子模板默认收不到父模板的变量,除非显式声明。
-
{% extends %}必须是模板文件的第一行,前面不能有空格、BOM 字符或 HTML 注释,否则报错TemplateSyntaxError: expected token 'name', got 'extends' -
{% include "nav.html" %}默认不继承当前上下文,若 nav.html 需要user_name变量,得写成{% include "nav.html" with context %} - 所有
{% include %}的路径都基于 Flask 的templates/目录,不是相对于当前模板文件位置,{% include "./partial/footer.html" %}会 404 - 多层继承(base → layout → page)超过 3 层后,
{% block content %}被覆盖的位置很难追踪,建议用{% block title prepend %}这类修饰符明确意图
posthtml-include 构建时合并 HTML 片段的路径和结构限制
静态站点生成场景下,posthtml-include 是比 JS 动态加载更可靠的选择,但它对片段格式和路径约定非常严格——稍不注意就会生成嵌套 ... 这种非法结构。
-
<include src="header.html"></include>中的src默认按项目根目录解析,不支持./或../相对路径;需通过插件选项配置root才能统一处理 - 被 include 的 HTML 文件严禁包含
、、标签,否则最终页面会出现多重根节点,浏览器解析异常 - Webpack 用户若用
html-loader,必须开启preprocessor选项,否则会被当成纯文本输出,而不是内联内容 - 所有片段需保证 UTF-8 编码且无 BOM,否则构建时可能静默失败,页面显示乱码
Web Components 自定义元素在 Shadow DOM 封装上的硬约束
Web Components 是唯一真正实现“样式+行为+结构”三重隔离的原生方案,但它的封装性恰恰来自一系列强制规则:<template></template> 必须在文档顶层、class 必须先定义再注册、生命周期钩子不能操作全局环境。
-
<template></template>标签不能嵌套在<div> 或其他组件内部,否则 <code>template.content返回空 DocumentFragment - 调用
customElements.define('my-button', MyButton)前,MyButton类必须已定义,否则抛出TypeError: Class constructor cannot be invoked without 'new' -
connectedCallback里禁止直接修改document.body或向document.head插入样式表,这会破坏 Shadow DOM 的封装边界 - IE 完全不支持,Edge 79+ 才稳定可用;若需兼容旧版,必须引入
@webcomponents/webcomponentsjspolyfill,且 polyfill 加载时机要早于自定义元素使用
真正决定复用效果的,从来不是“用了哪种技术”,而是你是否清楚每种方案的边界在哪里——SSI 的路径是服务器视角,Jinja2 的路径是模板引擎视角,posthtml-include 的路径是构建系统视角,Web Components 的路径则是浏览器 DOM 视角。混用时没对齐这些视角,问题就藏在看不见的地方。











