在现代前端开发中,静态网站生成器因其部署简单、性能优异、维护成本低等优势而广受欢迎。Eleventy(11ty)作为其中的佼佼者,凭借其无框架依赖、高度可定制和极简配置的特点,逐渐成为众多开发者构建博客、文档站、作品集等项目的首选工具。
Eleventy 由 Zach Leatherman 创建,目标是提供一个不依赖特定前端框架(如 React 或 Vue)的静态站点生成方案。它支持多种模板语言,包括 Markdown、Nunjucks、Liquid、Handlebars、JavaScript(.11ty.js
)等,并通过数据文件(JSON、YAML、JavaScript)实现内容与模板的分离。这种灵活性使得 Eleventy 成为一个非常通用且易于集成的构建工具。
核心架构与工作原理
Eleventy 的设计哲学是“最小化抽象”,它没有内置复杂的构建流程或运行时框架,而是专注于将源文件转换为静态 HTML 文件。其核心处理流程可以分为以下几个阶段:
- 输入收集:Eleventy 扫描指定的输入目录(默认为 [.](file://d:\VSProjects\awesometop-spider\LICENSE)),识别所有符合模板规则的文件。
- 元数据提取:从 YAML Front Matter、数据文件(如 [.json](file://d:\VSProjects\awesometop-spider\node_modules@prisma\debug\package.json)、[.js](file://d:\VSProjects\awesometop-spider\node_modules@prisma\client\edge.js))中提取页面元信息,用于控制输出路径、模板继承、变量注入等行为。
- 模板渲染:根据模板引擎对文件进行编译,结合全局数据和局部数据生成最终的 HTML 内容。
- 输出写入:将生成的 HTML 文件写入指定的输出目录(默认为
_site
)。
Eleventy 支持多层布局嵌套,允许开发者定义基础模板(layout),并通过子模板覆盖部分内容。例如,一个典型的博客文章页面可以继承自 layouts/post.njk
,并在头部声明该布局并提供标题、日期等信息。
---
layout: layouts/post.njk
title: "我的第一篇博客"
date: 2023-10-01
---
这是文章正文内容。
Eleventy 还引入了“集合”(collections)的概念,开发者可以通过过滤和分组的方式创建自定义内容集合,比如“所有标签为 ‘javascript’ 的文章”。这为导航菜单、归档页、分类页等功能提供了强大的支持。
安装与初始化配置
Eleventy 是一个基于 Node.js 的命令行工具,因此首先需要确保系统已安装 Node.js 和 npm。
安装 Eleventy
推荐使用 npm 在项目本地安装 Eleventy,这样可以避免版本冲突问题:
npm init -y
npm install @11ty/eleventy --save-dev
随后可以在 [package.json](file://d:\VSProjects\awesometop-spider\node_modules@prisma\debug\package.json) 中添加启动脚本:
"scripts": {
"build": "eleventy",
"serve": "eleventy --serve"
}
执行以下命令即可启动本地开发服务器:
npm run serve
默认情况下,Eleventy 会在当前目录查找源文件,并将生成的 HTML 输出到 _site
目录。如果需要更改输入输出路径,可在 .eleventy.js
配置文件中设置:
module.exports = function(eleventyConfig) {
return {
dir: {
input: "src",
output: "dist"
}
};
};
基础目录结构示例
一个典型的 Eleventy 项目结构如下:
my-site/
├── .eleventy.js
├── package.json
├── src/
│ ├── _data/
│ │ └── site.json
│ ├── _includes/
│ │ └── layout.njk
│ ├── index.md
│ └── posts/
│ └── hello-world.md
└── dist/
_data/
:存放全局可用的数据文件,如站点名称、菜单项等。_includes/
:存放布局模板和组件片段。posts/
:存放 Markdown 博客文章。index.md
:首页内容。
模板系统与数据绑定
Eleventy 支持多种模板语言,开发者可以根据项目需求自由选择。每种模板都会被编译成 HTML 并写入输出目录。
使用 Nunjucks 模板
Nunjucks 是一种功能强大且语法清晰的模板语言,适合构建复杂页面。以下是一个基础布局模板:
<!-- src/_includes/layout.njk -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
</head>
<body>
<header>
<h1>{{ site.title }}</h1>
<nav>
<ul>
{% for item in menu %}
<li><a href="{{ item.url }}">{{ item.text }}</a></li>
{% endfor %}
</ul>
</nav>
</header>
<main>
{{ content | safe }}
</main>
</body>
</html>
在 Markdown 文件中引用该布局:
---
layout: layout.njk
title: 首页
menu:
- text: 首页
url: /
- text: 关于我
url: /about/
---
欢迎来到我的网站!
在这个例子中,menu
数据来自当前页面的 Front Matter,site.title
则来源于 _data/site.json
。
使用 JavaScript 模板
对于更高级的逻辑处理,Eleventy 允许使用 .11ty.js
文件编写模板。这种方式特别适用于动态生成内容,如 RSS Feed、sitemap.xml 等。
// src/rss.11ty.js
module.exports = {
data() {
return {
permalink: "/rss.xml",
eleventyExcludeFromCollections: true
};
},
render(data) {
const itemsXml = data.collections.all.map(item => `
<item>
<title>${item.data.title}</title>
<link>${item.url}</link>
<description>${item.templateContent}</description>
</item>
`).join("");
return `
<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>我的博客</title>
<link>https://example.com</link>
${itemsXml}
</channel>
</rss>
`;
}
};
上述代码会生成一个 RSS 订阅源,并将其输出为 /rss.xml
。
集合与内容组织
Eleventy 提供了灵活的内容组织机制,其中最核心的是“集合”(collections)。集合是一组具有相同特征的模板对象,可用于生成归档页、分类列表、标签云等内容。
创建自定义集合
在 .eleventy.js
中注册一个新的集合:
module.exports = function(eleventyConfig) {
eleventyConfig.addCollection("blogPosts", function(collectionApi) {
return collectionApi.getFilteredByGlob("src/posts/*.md");
});
return {};
};
然后可以在模板中访问这个集合:
<ul>
{% for post in collections.blogPosts %}
<li>
<a href="{{ post.url }}">{{ post.data.title }}</a>
</li>
{% endfor %}
</ul>
分类与标签
Eleventy 支持通过 Front Matter 定义标签,并自动聚合相关内容。例如,在 Markdown 文件中添加:
tags:
- javascript
- tutorial
随后可以创建一个按标签分组的页面:
// src/tags.11ty.js
module.exports = {
data() {
return {
permalink: "/tags/{{ tag }}/",
pagination: {
data: "collections",
size: 1,
alias: "tag",
filter: (item) => item.startsWith("tag-")
}
};
},
render(data) {
const posts = data.collections[data.tag];
return `
<h1>标签:{{ tag }}</h1>
<ul>
{% for post in posts %}
<li><a href="{{ post.url }}">{{ post.data.title }}</a></li>
{% endfor %}
</ul>
`;
}
};
总结
Eleventy 以其简洁的设计理念、灵活的模板系统和强大的内容管理能力,成为静态网站生成领域的一匹黑马。它不仅适合构建个人博客、技术文档、企业官网等项目,也因其轻量无依赖的特性,能够轻松集成到 CI/CD 流程中,提升部署效率。
通过合理的目录结构、多样化的模板语言支持以及丰富的数据绑定机制,Eleventy 为开发者提供了一个既能满足基本需求又能应对复杂场景的工具链。