Hakyll教程:如何生成文件的多个版本
2025-07-10 06:58:05作者:庞眉杨Will
前言
在静态网站生成过程中,我们经常需要为同一份内容生成不同格式的版本。Hakyll作为强大的静态网站生成器,提供了version
功能来实现这一需求。本文将详细介绍如何在Hakyll中为同一文件生成多个版本,并正确使用这些版本。
基本概念
为什么需要多版本
想象这样一个场景:你希望博客文章不仅以HTML格式发布在网站上,同时还想提供原始的Markdown文件供读者下载。这就是典型的"多版本"需求。
Hakyll的版本机制
Hakyll通过version
函数允许我们为同一文件创建不同版本。其类型签名为:
version :: String -> Rules () -> Rules ()
这个函数接受一个版本标识字符串和一个规则集,为该规则集定义的内容创建指定版本。
实战示例
创建HTML和原始版本
下面是一个典型配置,为每篇博客文章生成HTML和原始Markdown两个版本:
match "posts/*" $ do
route $ setExtension "html"
compile $ pandocCompiler
>>= loadAndApplyTemplate "templates/post.html" postCtx
>>= loadAndApplyTemplate "templates/default.html" postCtx
>>= relativizeUrls
match "posts/*" $ version "raw" $ do
route idRoute
compile getResourceBody
这段代码做了两件事:
- 默认版本:将Markdown转换为HTML,应用模板,并处理URL
- "raw"版本:保留原始Markdown内容,不进行转换
路由处理
注意两个版本使用了不同的路由策略:
- HTML版本使用
setExtension "html"
改变文件扩展名 - 原始版本使用
idRoute
保持原文件名
重要注意事项
版本选择与模式匹配
当使用loadAll
等函数加载文件时,默认会匹配所有版本。例如:
loadAll "posts/*" -- 这会匹配所有版本,包括HTML和原始版本
这通常不是我们想要的行为。正确的做法是明确指定版本:
加载默认版本
loadAll ("posts/*" .&&. hasNoVersion)
加载特定版本
loadAll ("posts/*" .&&. hasVersion "raw")
版本标识符
版本标识符可以是任意字符串,但建议使用有意义的名称,如:
- "raw":原始内容
- "minified":压缩后的版本
- "mobile":移动端优化版本
高级应用
多版本模板
你可以为不同版本应用不同的模板:
match "posts/*" $ version "print" $ do
route $ setExtension "print.html"
compile $ pandocCompiler
>>= loadAndApplyTemplate "templates/print.html" postCtx
版本组合
Hakyll允许创建多个版本组合:
match "posts/*" $ version "raw" $ ...
match "posts/*" $ version "minified" $ ...
每个版本都会独立生成,互不干扰。
总结
Hakyll的版本功能为内容发布提供了极大的灵活性。通过合理使用version
函数,我们可以:
- 为同一内容生成不同格式
- 应用不同的处理流程
- 输出到不同的位置
- 在需要时精确选择特定版本
掌握这一功能后,你将能够更好地满足各种内容发布需求,为读者提供更丰富的内容体验。