什么是 hakyll
hakyll 是類似于 jekyll 的一個用來搭建靜態(tài)站點的工具
hakyll 與 jekyll 的不同
hakyll 與其他大多數(shù)同類工具相比擁有非常大的靈活性切威,github 默認的靜態(tài)網頁生成器 jekyll 是一個遵循約定大于配置的工具,使用 jekyll 就必須遵循它的約定。
比如博文需要以 yy-mm-dd 開頭的文件名形式存放在 posts 文件夾下彤蔽。
而 hakyll 就擁有更大的靈活性宰闰,hakyll 的哲學在于,用戶書寫內容收厨,hakyll 負責把這些內容轉化成不同的展現(xiàn)形式柒啤。
這樣生成的站點形式就不局限于博客,也可以包含 slides 或者 pdf 之類的內容龄砰。
hakyll 的安裝與基本使用
hakyll 使用非常高大上的 haskell 語言編寫,所以要使用 hakyll 就需要
haskell 環(huán)境讨衣。在 mac 下的安裝非常簡單:
brew install ghc cabal-install
安裝完成后記得把 $HOME/.cabal/bin 加入到 $PATH换棚。
然后就可以新建一個站點了
$ hakyll-init my-site
$ cd my-site
$ ghc --make -threaded site.hs
$ ./site build
$ ./site watch
打開 http://localhost:8000/ 就能看到默認生成的站點了,如果你只想像使用 jekyll 一樣使用 hakyll 的話反镇,到這里就夠了固蚤,同樣在 posts 文件夾下書寫你的博文就可以了。
hakyll 的高級功能
如果你想領略 hakyll 的強大而靈活的配置歹茶,那么請往下看夕玩。
hakyll 的工作原理
如果你照著上面的方式安裝并初始化了 hakyll 的話你弦,你的站點文件結構就會類似于
.
├── README.md
├── about.rst
├── contact.markdown
├── css
│ └── default.scss
├── images
│ └── haskell-logo.png
├── index.html
├── posts
│ └── use-hakyll-to-build-static-website.org
├── site
├── site.hi
├── site.hs
├── site.o
└── templates
├── archive.html
├── default.html
├── post-list.html
└── post.html
這樣, 其實除了 site 開頭的幾個文件以外 (site 是編譯好的二進制文件,
有100mb 左右大小, 記得不要納入版本控制!),其他都是靜態(tài)文件燎孟,且結構是可以隨便定義的禽作。其中 site.hs 可以認為是 hakyll 的配置文件,打開它就會看到一大堆看(高)不(大)懂(上)的 haskell 代碼揩页。
稍微觀察一下就會發(fā)現(xiàn), 其中有三個關鍵詞
- match
- route
- compile
match 就是匹配, 后面的文件名是你站點目錄下的源文件, 比如 'css/*' 就指代
css 文件夾下的所有文件
route 和我們通常程序中所有的路由有點不同, 指的是 match
到的文件會被放置在編譯好的站點的位置(默認是 site 文件夾)
compile 就像是一個管道旷偿。一個資源,從 match (頭) 到 route(尾)的過程中需要做的轉換工作爆侣,比如 markdown -> html萍程, 或者壓縮混淆等。
這樣一來 hakyll 的結構就很清楚了兔仰,用戶提供原始的數(shù)據(jù)茫负,然后 hakyll 就去編譯他們并且放置到正確的位置。
下面舉幾個實際的例子乎赴,來表現(xiàn)一下 hakyll 的強大忍法。
sass 支持
-- 使用 compass 來處理 scss 樣式
match (fromList ["sass/main.scss", "sass/blog.scss"]) $ do
route $ setExtension "css"
compile $ getResourceString >>=
withItemBody (unixFilter "sass" ["-s", "--scss", "-I", "sass/"]) >>=
return . fmap compressCss
創(chuàng)建不存在的頁面
create ["archive.html"] $ do
route idRoute
compile $ do
posts <- recentFirst =<< loadAll "posts/*"
let archiveCtx =
listField "posts" postCtx (return posts) `mappend`
constField "title" "Archives" `mappend`
defaultContext
makeItem ""
>>= loadAndApplyTemplate "templates/archive.html" archiveCtx
>>= loadAndApplyTemplate "templates/default.html" archiveCtx
>>= relativizeUrls
這個例子中 archive.html 這個頁面原本是不存在的,里面的內容都是動態(tài)獲取的无虚,它讀取了 posts 下的所有文件缔赠,然后讀取他們的 title 屬性, 然后列出來,這和 jekyll 的讀取一個對象的屬性并循環(huán)出來(命令式編程風格)不同友题,畢竟 haskell 是函數(shù)式語言嗤堰。
幻燈片
match "slides/*" $ do
route $ setExtension "html"
compile $ getResourceString >>=
withItemBody (unixFilter "pandoc" ["-s", "--mathml", "-i", "-t", "dzslides"])
使用強大的 pandoc,直接就把 markdown 文件變成 slides 了度宦。
真實的例子
這里 列出了很多使用 hakyll 的網站踢匣,都有源碼在 github 上,可供參考戈抄。
總結
hakyll 將 Haskell 的函數(shù)式編程思想帶到了靜態(tài)網站的構建中离唬,學習使用 hakyll 對理解函數(shù)式編程是很有幫助的。