靜態(tài)網(wǎng)站生成器是如何工作的

在過去的幾年里,開源靜態(tài)網(wǎng)站生成器的數(shù)量增長(zhǎng)迅速孵睬,StaticGen 上幾乎找得到每一種語(yǔ)言實(shí)現(xiàn)的版本播歼。靜態(tài)網(wǎng)站相比動(dòng)態(tài)網(wǎng)站具備無需依賴應(yīng)用服務(wù)器,性能優(yōu)越肪康,部署簡(jiǎn)單等特點(diǎn)荚恶。特別適合生成靜態(tài)文檔,個(gè)人博客磷支,飽受開發(fā)者的青睞。相比學(xué)會(huì)使用食寡,掌握工作原理也尤為重要雾狈。

一個(gè)靜態(tài)網(wǎng)站生成器的工作流程通常有以下幾個(gè)步驟:

  1. 讀取源文件(e.g. 約定 markdown 格式)
  2. 資源預(yù)處理
  3. 模板引擎渲染
  4. 生成目標(biāo)文件

第一步 讀取源文件

從使用者的角度,我們希望以 markdown 的形式進(jìn)行寫作抵皱,相比純文本更容易控制格式善榛,并且可以靈活地自定義配置(源目錄路徑、目標(biāo)目錄路徑呻畸、頁(yè)面標(biāo)題等等)移盆,覆蓋工具的默認(rèn)配置,這一步很簡(jiǎn)單伤为。

以 Node.js 為例:

// 讀取 markdown 內(nèi)容
readFile(source, (err, data) => {
  console.log(data);
})
// 讀取配置內(nèi)容
console.log(require(config))

第二步 資源預(yù)處理

也是靜態(tài)網(wǎng)站生成器的核心工作部分咒循。首先解析 markdown 內(nèi)容,分離頭部元數(shù)據(jù)(通常采用 YAML 格式绞愚,用于單頁(yè)信息配置)與主體內(nèi)容叙甸。

形似:

---
title: Hello World
---

Awesome static site generator

解析成:

const result = {
  'path/to/hello-world.md': {
    title: 'Hello World',
    content: new Buffer('Awesome static site generator.')
  }
}

通常的做法是掃描文件,匹配分隔符---位衩,分割內(nèi)容裆蒸,對(duì)頭部用相應(yīng)格式的引擎解析(e.g. YAML 格式用 yaml-parser,JSON 格式用 JSON.parse)糖驴,對(duì)主體內(nèi)容僚祷,需要把 markdown 內(nèi)容轉(zhuǎn)換成帶有標(biāo)簽的 HTML 片段,用于排版與應(yīng)用樣式贮缕,推薦比較流行的解析器 marked 辙谜。

經(jīng)過轉(zhuǎn)換后:

const markedResult = {
  'path/to/hello-world.md': {
    title: 'Hello World',
    content: new Buffer('Awesome static site generator.'),
    html: '<p>Awesome static site generator.</p>'
  }
}

對(duì)其它一些靜態(tài)資源(e.g. css, js, png),可以引入一系列工具鏈跷睦,CSS 預(yù)處理器筷弦,編譯器,打包器,流程構(gòu)建工具烂琴,將全部資源相整合爹殊。由此,可以提供一套主題配置奸绷,甚至可以開放主題插件梗夸,豐富內(nèi)容。所有的設(shè)計(jì)出發(fā)點(diǎn)都基于更好的內(nèi)容寫作号醉,而不必折騰繁瑣重復(fù)性的頁(yè)面開發(fā)工作反症。

第三步 模板引擎渲染

在上一步,我們得到了 markdown 解析后的 HTML 片段畔派,接下來要做得就是將 HTML 片段嵌入預(yù)先定義的模板铅碍,復(fù)用頁(yè)面中公共部分(e.g. 導(dǎo)航欄、側(cè)邊欄线椰、底部)胞谈,還可以嵌入變量(默認(rèn)配置及自定義配置)和靜態(tài)資源。

以模板引擎 EJS 為例:

<html>
<head><%= title %></head>
<body>
  <% include partials/navbar %>
  <%- html %>
</body>
</html>

// EJS 渲染
const ejsResult = ejs.render(str, {
    ...markedResult['path/to/hello-world.md']
});

我們甚至可以拋棄以往模板引擎渲染這種比較傳統(tǒng)的方式憨愉,改用 MV* 框架(e.g. React, Vue, Angular)烦绳,并結(jié)合服務(wù)端渲染技術(shù),熱替換技術(shù)及其它工具鏈配紫,打造一個(gè)更現(xiàn)代化的靜態(tài)網(wǎng)站生成器径密。

第四步 生成目標(biāo)文件

經(jīng)過前三步的解析,處理躺孝,編譯享扔,轉(zhuǎn)換,我們得到了最終的資源文件,最后一步只需清理目標(biāo)目錄,并輸出所有資源到目標(biāo)目錄邢隧,結(jié)束工作模她。

// 生成目標(biāo)文件
writeFile(destination, ejsResult, err => {
  if (err) return console.error(err)
}))

你可能還需要

  • 一個(gè)本地服務(wù)器 通過啟動(dòng)一個(gè) Node.js Server 實(shí)時(shí)預(yù)覽界面,監(jiān)聽本地文件改動(dòng),結(jié)合 live-reload 觸發(fā)頁(yè)面自動(dòng)刷新,或者利用 Webpack 熱替換功能。
  • 一個(gè)文件數(shù)據(jù)庫(kù) 持久化存儲(chǔ)部分?jǐn)?shù)據(jù)(e.g. 博客發(fā)表時(shí)間呆盖,文件哈希值,文件修改時(shí)間)贷笛,重新編譯可以跳過未改動(dòng)的文件应又。
  • 一個(gè)日志系統(tǒng) 記錄編譯過程和編譯結(jié)果,增強(qiáng) debug 可行性乏苦,按 log 層級(jí)格式化輸出不同信息到控制臺(tái)株扛。
  • 一個(gè)自動(dòng)化部署方案 整合 Git 和 WebHook尤筐,一鍵發(fā)布到 GitHub Pages 或者自己的網(wǎng)站上。

小結(jié)

本文從宏觀角度解釋了靜態(tài)網(wǎng)站生成器的工作流程(輸入 => 預(yù)處理 => 渲染 => 輸出)洞就。當(dāng)然這個(gè)過程還涉及命令行的解析盆繁,合法性校驗(yàn),錯(cuò)誤捕獲旬蟋,解析器原理油昂,編譯器原理,模板引擎原理倾贰,插件設(shè)計(jì)等等冕碟。See you next time ~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市匆浙,隨后出現(xiàn)的幾起案子安寺,更是在濱河造成了極大的恐慌,老刑警劉巖吞彤,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件我衬,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡饰恕,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門井仰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來埋嵌,“玉大人,你說我怎么就攤上這事俱恶”⑧拢” “怎么了?”我有些...
    開封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵合是,是天一觀的道長(zhǎng)了罪。 經(jīng)常有香客問我,道長(zhǎng)聪全,這世上最難降的妖魔是什么泊藕? 我笑而不...
    開封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮难礼,結(jié)果婚禮上娃圆,老公的妹妹穿的比我還像新娘。我一直安慰自己蛾茉,他們只是感情好讼呢,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著谦炬,像睡著了一般悦屏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天础爬,我揣著相機(jī)與錄音甫贯,去河邊找鬼。 笑死幕帆,一個(gè)胖子當(dāng)著我的面吹牛获搏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播失乾,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼常熙,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了碱茁?” 一聲冷哼從身側(cè)響起裸卫,我...
    開封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎纽竣,沒想到半個(gè)月后墓贿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蜓氨,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年聋袋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片穴吹。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡幽勒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出港令,到底是詐尸還是另有隱情啥容,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布顷霹,位于F島的核電站咪惠,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏淋淀。R本人自食惡果不足惜遥昧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望绅喉。 院中可真熱鬧渠鸽,春花似錦、人聲如沸柴罐。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)革屠。三九已至凿试,卻和暖如春排宰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背那婉。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來泰國(guó)打工板甘, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人详炬。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓盐类,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親呛谜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子在跳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容