構建基於Node.js、Git和Markdown的微型博客
本文探討瞭如何使用Node.js、Git和少量依賴項構建一個微型博客。此應用旨在從提交到存儲庫的文件中提供靜態內容。您將學習如何構建和測試應用程序,並深入了解交付解決方案的過程。最終,您將擁有一個極簡的、可運行的博客應用程序,您可以在此基礎上進行構建。
關鍵要點:
微型博客的主要組成部分
要構建一個很棒的博客,首先,您需要一些組件:
為了發送 HTTP 消息,我選擇 Node.js,因為它提供了從服務器發送超文本消息所需的一切。特別感興趣的兩個模塊是 http
和 fs
。 http
模塊將創建一個 Node HTTP 服務器。 fs
模塊將讀取文件。 Node 擁有使用 HTTP 構建微型博客的庫。
為了存儲博客文章存儲庫,我將選擇 Git 而不是功能齊全的數據庫。原因是,Git 本身就是一個具有版本控制的文本文檔存儲庫。這正是我存儲博客文章數據所需的一切。擺脫添加數據庫作為依賴項,使我不必為大量問題編寫代碼。
我選擇使用 Markdown 格式存儲博客文章,並使用 marked
解析它們。如果我以後決定這樣做,這將使我能夠自由地逐步增強原始內容。 Markdown 是普通 HTML 的一種不錯的輕量級替代方案。
對於單元測試,我選擇優秀的測試運行器 roast.it。我選擇這個替代方案是因為它沒有依賴項,並且滿足了我的單元測試需求。您可以選擇其他測試運行器,如 taper,但它大約有八個依賴項。我喜歡 roast.it 的原因是它沒有依賴項。
有了這個組件列表,我就擁有了構建微型博客所需的所有依賴項。
選擇依賴項並非易事。我認為關鍵是任何超出當前問題範圍的東西都可能成為依賴項。例如,我沒有構建測試運行器或數據存儲庫,因此將其添加到列表中。任何給定的依賴項都不能吞噬解決方案並劫持代碼。因此,只選擇輕量級組件是有意義的。
本文假設您已經熟悉 Node、npm 和 Git,以及各種測試方法。我不會逐步介紹構建微型博客的每個步驟,而是重點討論代碼的特定區域。如果您想在家中跟隨操作,代碼已上傳到 GitHub,您可以嘗試每個代碼片段。
測試
測試使您對代碼充滿信心並加強反饋循環。編程中的反饋循環是指編寫任何新代碼和運行它之間所需的時間。在任何 Web 解決方案中,這意味著要跳過許多層才能獲得任何反饋。例如,瀏覽器、Web 服務器甚至數據庫。隨著複雜性的增加,這可能意味著需要幾分鐘甚至一小時才能獲得反饋。使用單元測試,我們可以減少這些層並獲得快速反饋。這使重點放在當前問題上。
我喜歡從編寫快速的單元測試開始任何解決方案。這讓我開始為任何新代碼編寫測試。這就是您如何使用 roast.it 開始運行的方式。
在 package.json
文件中添加:
<code class="language-json">"scripts": { "test": "node test/test.js" }, "devDependencies": { "roast.it": "1.0.4" }</code>
test.js
文件是您引入所有單元測試並運行它們的地方。例如,您可以執行以下操作:
<code class="language-javascript">var roast = require('roast.it'); roast.it('Is array empty', function isArrayEmpty() { var mock = []; return mock.length === 0; }); roast.run(); roast.exit();</code>
要運行測試,請執行 npm install && npm test
。讓我高興的是,我不再需要費盡心思來測試新代碼了。這就是測試的意義所在:快樂的程序員獲得信心並專注於解決方案。
骨架
微型博客將使用 Node 來響應客戶端請求。一種有效的方法是通過 http.CreateServer()
Node API。這可以在 app.js
中的以下摘錄中看到:
<code class="language-javascript">/* app.js */ var http = require('http'); var port = process.env.port || 1337; var app = http.createServer(function requestListener(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8'}); res.end('A simple micro blog website with no frills nor nonsense.'); }); app.listen(port); console.log('Listening on http://localhost:' + port);</code>
通過 package.json
中的 npm 腳本運行此腳本:
<code class="language-json">"scripts": { "start": "node app.js" }</code>
現在,http://localhost:1337/
成為默認路由,並向客戶端返回消息。其想法是添加更多路由以返回其他響應,例如使用博客文章內容進行響應。
文件夾結構
為了構建應用程序的結構,我決定使用以下主要部分:
我將使用這些文件夾來組織代碼。以下是每個文件夾用途的概述:
blog
:存儲純 Markdown 格式的原始博客文章message
:可重用的模塊,用於構建對客戶端的響應消息route
:除默認路由之外的路由test
:編寫單元測試的地方view
:放置 HTML 模板的地方更多路由和測試
對於第一個用例,我將介紹博客文章的另一條路由。我選擇將其放在名為 BlogRoute
的可測試組件中。我喜歡的是您可以將依賴項注入其中。單元及其依賴項之間的這種關注點分離使得單元測試成為可能。每個依賴項在隔離的測試中都會獲得一個模擬。這允許您編寫不可變、可重複且快速的測試。
例如,構造函數如下所示:
<code class="language-json">"scripts": { "test": "node test/test.js" }, "devDependencies": { "roast.it": "1.0.4" }</code>
有效的單元測試是:
<code class="language-javascript">var roast = require('roast.it'); roast.it('Is array empty', function isArrayEmpty() { var mock = []; return mock.length === 0; }); roast.run(); roast.exit();</code>
目前,BlogRoute
期望一個 req
對象,它來自 Node API。為了使測試通過,只需執行以下操作:
<code class="language-javascript">/* app.js */ var http = require('http'); var port = process.env.port || 1337; var app = http.createServer(function requestListener(req, res) { res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8'}); res.end('A simple micro blog website with no frills nor nonsense.'); }); app.listen(port); console.log('Listening on http://localhost:' + port);</code>
有了這個,我們可以將其連接到請求管道。您可以在 app.js
中執行以下操作:
<code class="language-json">"scripts": { "start": "node app.js" }</code>
擁有測試的好處是我不必預先擔心實現細節。我很快就會定義 message
。 res
和 req
對象來自 http.createServer()
Node API。
存儲庫
下一個要解決的問題是在 BlogRoute.route()
中讀取原始博客文章數據。 Node 提供了一個 fs
模塊,您可以使用它從文件系統讀取。
例如:
<code class="language-javascript">/* route/blogRoute.js */ var BlogRoute = function BlogRoute(context) { this.req = context.req; };</code>
此代碼片段位於 message/readTextFile.js
中。在解決方案的核心,您讀取存儲庫中的文本文件。請注意,fs.readFile()
是一個異步操作。這就是它採用 fn
回調並使用文件數據調用它的原因。此異步解決方案使用簡單的回調。
這提供了文件 IO 的需求。我喜歡它的地方在於它只解決一個問題。由於這是一個跨領域的問題,例如讀取文件,因此無需進行單元測試。單元測試應該只測試您自己代碼的隔離性,而不是其他人的代碼。
理論上,您可以模擬內存中的文件系統並以此方式編寫單元測試,但是解決方案隨後將開始在各個地方洩漏關注點並變成混亂。
讀取文件等跨領域問題超出了代碼的範圍。例如,讀取文件取決於您無法直接控制的子系統。這使得測試變得脆弱,並增加了反饋循環的時間和復雜性。這是一個必須與您的解決方案分離的問題。
Markdown 解析器
下一個問題是將存儲庫中的原始 Markdown 數據轉換為 HTML。此過程分為兩個步驟:
view
文件夾獲取 HTML 模板在健全的編程中,其想法是將一個大問題分解成小的、易於處理的部分。讓我們解決第一個問題:如何根據我在 BlogRoute
中的內容獲取 HTML 模板?
一種方法可能是:
<code class="language-javascript">/* test/blogRouteTest.js */ roast.it('Is valid blog route', function isValidBlogRoute() { var req = { method: 'GET', url: 'http://localhost/blog/a-simple-test' }; var route = new BlogRoute({ req: req }); return route.isValidRoute(); });</code>
請記住,這將替換上一節中使用的虛擬回調,稱為 dummyTest
。
要替換回調 dummyTest
,請執行以下操作:
<code class="language-json">"scripts": { "test": "node test/test.js" }, "devDependencies": { "roast.it": "1.0.4" }</code>
(後續內容因篇幅限製而省略,請根據需要自行補充)
以上是使用node.js,git和markdown構建微博的詳細內容。更多資訊請關注PHP中文網其他相關文章!