构建基于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
文件中添加:
"scripts": { "test": "node test/test.js" }, "devDependencies": { "roast.it": "1.0.4" }
test.js
文件是您引入所有单元测试并运行它们的地方。例如,您可以执行以下操作:
var roast = require('roast.it'); roast.it('Is array empty', function isArrayEmpty() { var mock = []; return mock.length === 0; }); roast.run(); roast.exit();
要运行测试,请执行 npm install && npm test
。让我高兴的是,我不再需要费尽心思来测试新代码了。这就是测试的意义所在:快乐的程序员获得信心并专注于解决方案。
骨架
微型博客将使用 Node 来响应客户端请求。一种有效的方法是通过 http.CreateServer()
Node API。这可以在 app.js
中的以下摘录中看到:
/* 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);
通过 package.json
中的 npm 脚本运行此脚本:
"scripts": { "start": "node app.js" }
现在,http://localhost:1337/
成为默认路由,并向客户端返回消息。其想法是添加更多路由以返回其他响应,例如使用博客文章内容进行响应。
文件夹结构
为了构建应用程序的结构,我决定使用以下主要部分:
我将使用这些文件夹来组织代码。以下是每个文件夹用途的概述:
blog
:存储纯 Markdown 格式的原始博客文章message
:可重用的模块,用于构建对客户端的响应消息route
:除默认路由之外的路由test
:编写单元测试的地方view
:放置 HTML 模板的地方更多路由和测试
对于第一个用例,我将介绍博客文章的另一条路由。我选择将其放在名为 BlogRoute
的可测试组件中。我喜欢的是您可以将依赖项注入其中。单元及其依赖项之间的这种关注点分离使得单元测试成为可能。每个依赖项在隔离的测试中都会获得一个模拟。这允许您编写不可变、可重复且快速的测试。
例如,构造函数如下所示:
"scripts": { "test": "node test/test.js" }, "devDependencies": { "roast.it": "1.0.4" }
有效的单元测试是:
var roast = require('roast.it'); roast.it('Is array empty', function isArrayEmpty() { var mock = []; return mock.length === 0; }); roast.run(); roast.exit();
目前,BlogRoute
期望一个 req
对象,它来自 Node API。为了使测试通过,只需执行以下操作:
/* 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);
有了这个,我们可以将其连接到请求管道。您可以在 app.js
中执行以下操作:
"scripts": { "start": "node app.js" }
拥有测试的好处是我不必预先担心实现细节。我很快就会定义 message
。res
和 req
对象来自 http.createServer()
Node API。
存储库
下一个要解决的问题是在 BlogRoute.route()
中读取原始博客文章数据。Node 提供了一个 fs
模块,您可以使用它从文件系统读取。
例如:
/* route/blogRoute.js */ var BlogRoute = function BlogRoute(context) { this.req = context.req; };
此代码片段位于 message/readTextFile.js
中。在解决方案的核心,您读取存储库中的文本文件。请注意,fs.readFile()
是一个异步操作。这就是它采用 fn
回调并使用文件数据调用它的原因。此异步解决方案使用简单的回调。
这提供了文件 IO 的需求。我喜欢它的地方在于它只解决一个问题。由于这是一个跨领域的问题,例如读取文件,因此无需进行单元测试。单元测试应该只测试您自己代码的隔离性,而不是其他人的代码。
理论上,您可以模拟内存中的文件系统并以此方式编写单元测试,但是解决方案随后将开始在各个地方泄漏关注点并变成混乱。
读取文件等跨领域问题超出了代码的范围。例如,读取文件取决于您无法直接控制的子系统。这使得测试变得脆弱,并增加了反馈循环的时间和复杂性。这是一个必须与您的解决方案分离的问题。
Markdown 解析器
下一个问题是将存储库中的原始 Markdown 数据转换为 HTML。此过程分为两个步骤:
view
文件夹获取 HTML 模板在健全的编程中,其想法是将一个大问题分解成小的、易于处理的部分。让我们解决第一个问题:如何根据我在 BlogRoute
中的内容获取 HTML 模板?
一种方法可能是:
/* 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(); });
请记住,这将替换上一节中使用的虚拟回调,称为 dummyTest
。
要替换回调 dummyTest
,请执行以下操作:
"scripts": { "test": "node test/test.js" }, "devDependencies": { "roast.it": "1.0.4" }
(后续内容因篇幅限制而省略,请根据需要自行补充)
以上是使用node.js,git和markdown构建微博的详细内容。更多信息请关注PHP中文网其他相关文章!