首页
/ Hakyll教程:如何生成文件的多个版本

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

这段代码做了两件事:

  1. 默认版本:将Markdown转换为HTML,应用模板,并处理URL
  2. "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函数,我们可以:

  1. 为同一内容生成不同格式
  2. 应用不同的处理流程
  3. 输出到不同的位置
  4. 在需要时精确选择特定版本

掌握这一功能后,你将能够更好地满足各种内容发布需求,为读者提供更丰富的内容体验。