使用Node.js构建一个简单的静态页面生成器
静态页面生成器在开发相当简单的网站时非常好用,而且超级方便。 我可能已经用掉了目前似乎可用的一百种中的两三种。 但是使用一个工具对我来说还不够,通常情况就是这样,因为我真的很喜欢构建自己的工具来了解幕后发生的事情。 因此,今天,我将与您分享我自己的食谱,以使用Node.js创建一个简单的静态页面生成器。
步骤0:成分列表(又名依赖关系和需要了解的内容)
-
npm init
—我想大多数人都熟悉创建一个程序包,因此在这里我不会对其进行深入介绍。 如果您需要一些指导,请参阅文档 。 -
npm i -s live-server
生成的网站的服务器,支持热重装。 该软件包可以替代任何其他热重装服务器软件包,但是我非常喜欢它,因为它非常简单,可以完成工作。 -
npm i -s nodemon
文件并运行指定的任务。 文件更改时,我们将使用此软件包自动重建我们的静态网站。 -
npm i -s concurrently
-几乎需要并发执行脚本/任务才能使一切顺利运行。 我敢肯定,有很多很棒的程序包可以完成相同的事情,但是我对这一特定程序很熟悉,因此我会坚持下去。 - Node的文件系统模块和
npm i -s fs-extra
—文件系统模块是读取/写入/删除文件所必需的,因此我们将使用它来实际生成静态网站。fs-extra
是最棒的扩展,它使您可以执行更多操作,例如删除不考虑内容的整个文件夹,这特别有用。 -
npm i -s markdown-it
—我们将在Markdown中编写页面的内容,因此我们将使用此包作为它们的解析器。 非常简单,如果您需要它们,它有很多插件。 - Javascript模板文字 —如果您不熟悉模板文字,请不要担心。 就本文而言,您需要知道的就是可以使用反引号(
`
)编写多行字符串,并且使用${expression}
可以用内部表达式的结果替换美元符号和花括号。
步骤1:创建必要的目录和文件
在进入代码之前,我们需要为整个项目定义一个结构。 请记住,这是我对此主题的看法,它绝不是唯一或最好的,因此请随时进行您喜欢的任何调整:
- pages目录:在该目录中,我将添加用Markdown编写的页面。 然后,将使用适当的脚本将它们转换为HTML文件。
- pages_meta目录:我觉得通用元数据不是最好的主意,因此我将使用该目录内的JSON文件来添加特定于每个页面的元数据。 除文件扩展名(即
index.json
是index.md
的元数据文件)外,每个JSON文件的名称都必须与pages目录中markdown文件的确切名称匹配。 JSON文件的内容如下所示:
- build_scripts目录:在这里,我将添加脚本以将Markdown和JSON文件转换为HTML文档。 我将使用两个文件,一个builder.js脚本(它将是静态页面生成器的主要入口点)和一个page_template.js ,它将用作模板来渲染每个页面。 将代码分为两个文件可能是一个好主意,因为您可能会扩展构建文件中的逻辑以根据某些条件使用不同的模板,因此这使您可以独立于核心构建来处理页面呈现逻辑。
- css , js和images目录:这些目录包含您的页面将依赖的CSS文件,它们可能使用的脚本以及可能显示的图像。 所有这些都将复制到输出目录。
- 构建目录:这是静态页面生成器的输出目录。 您生成的静态页面和所有需要复制的文件将最终保存在此文件夹中。 您不应在此处手动更改任何内容,因为构建脚本应在输出每个新构建之前清理此文件夹。
步骤2:设定环境
我们几乎已经准备好开始编写一些代码,但是首先我们需要在package.json
定义脚本,以便我们可以启动静态页面生成器。 我设置我的方式是这样的:
"build-pages": "node ./build_scripts/builder.js", "start": "concurrently --kill-others \"nodemon -e js,json,css,md -i build -x \\\"npm run build-pages\\\"\" \"live-server ./build\""
首先,我们需要build-pages
脚本来告诉Node.js运行我们的构建脚本。 编写必要的代码后,这将从我们的文件生成静态网站。
另一个脚本start
稍微复杂一些。 我们concurrently
使用来concurrently
运行两个进程。 第一个是nodemon
,我们明确地监视扩展名为js, json, css, md
文件中的更改js, json, css, md
并忽略了build
目录。 nodemon
看到更改后,将立即执行build-pages
脚本,因此将重建静态网站。 第二个过程是从build
文件夹中运行live-server
。 这就是启动和运行静态页面生成器所需的全部内容。 现在,我们只需要编写一些代码即可将Markdown和JSON文件转换为HTML文档。
步骤2.5:喝杯咖啡(可选,但强烈建议)
如果您已经做到了这一点,那就太好了! 在接下来的几个步骤中,您将编写将影响最终结果的代码,因此在潜入水中之前,您可能想要喝杯咖啡(或想要的任何其他饮料)。
步骤3:为您的页面创建模板
请记住,我们正在使用markdown-it
将Markdown文件呈现为HTML。 但是,我们还需要输出markdown-it
未创建的HTML文档中的许多部分,例如元数据和html,head和body的包装标签。 我们将使用page_template.js文件执行此操作,并通过在模板内部创建默认的元数据对象来确保不丢失任何元数据。
我不会详细解释每一个小步骤,但是在向您展示我的源代码之前,有一件我想强调的非常重要的事情:
`${pageMeta.hasOwnProperty('stylesheets')
? pageMeta.stylesheets.length
? pageMeta.stylesheets.map(value => `<link rel="stylesheet" href="${value}">`)
: ''
: this.defaultMeta.stylesheets.map(value => `<link rel="stylesheet" href="${value}">`)
}`
在上面的代码片段中,您可以看到如何利用表达式和嵌套的模板文字在最终的HTML文档中创建多个元素。 简而言之,它确定是应使用模板中定义的默认stylesheets
属性,还是应使用为特定页面定义的stylesheets
属性,然后继续生成链接到样式表列表中定义的每个CSS文件的适当标签。 我相信这个示例展示了模板文字有多么强大,以及使用它们可以完成多少工作。
话虽如此,我们正在创建的模板必须为每个页面处理一些事情:
- 输出
<!DOCTYPE html>
,文档开头和结尾的正确<html>
标记以及<head>
和<body>
标记。 - 根据提供的元数据输出适当的
<title>
。 - 从提供的元数据中输出所有适当的
<meta>
标签。 - 根据需要输出脚本和样式表的
<script>
和<link>
标记的列表。 - 最后,输出从
<body>
内部的Markdown文件生成的HTML。
在实现所有这些功能之后,您应该最终得到类似于我的template的内容 。
步骤4:创建构建脚本
您快到了! 现在,我们只需要编写构建脚本,即可根据需要将所有内容放在一起。 请记住,有多种方法可以执行此操作,您绝对可以调整此脚本以创建更复杂的网站并处理不同的案例,但是目前,我们将坚持一个非常基本的实施方式,该操作仅会执行我认为必须建立的静态网站:
- 加载
fs-extra
,path
和您的./page_template
。 - 声明页面 , pages_meta , css , js , 图像的路径,并建立相对于
package.json
文件的构建目录。 在后面的代码中,我们将使用它们来减少混乱。 - 对所有内容使用同步方法,例如
readdirSync
。 这将确保我们的代码从上到下运行。 如果您对异步编程技能有信心,请继续进行异步实现,反正它可能会更有效率。 - 清理构建目录。
- 循环遍历pages目录中的所有页面,并将它们存储在列表中。 对pages_meta目录中的元数据文件执行相同的操作 。
- 使用Markdown和JSON文件作为模板文件的
generatePage()
函数的参数来生成每个页面。 - 照原样将css , js和images目录复制到build目录中。
这是使构建过程正常运行所需要做的全部工作。 如果您正确完成了所有操作,则应该以类似于此脚本的构建脚本结束。
步骤5:发挥创意并建立您一直想要的网站
如果您一直在遵循的话,那么您现在应该拥有一个静态页面生成器。 现在,有趣的部分开始了! 您可以根据需要进行自定义,创建所需的内容并添加所需的所有功能,但是在其他任何地方都找不到。 没有什么可以做的!
我对改进和尝试的建议:
- 添加第二个模板,该模板将在某些条件下应用。
- 将导航栏,页眉或页脚添加到模板文件中,以为您的静态网站创建应用程序外壳。
- 调整
markdown-it
的配置或添加一些插件 。 - 将构建脚本转换为异步脚本。
- 支持页面和文件的不同格式。
Github 上提供了本文的完整源代码 。 请记住对存储库加注星标,以便以后找到返回存储库的方式!
From: https://hackernoon.com/building-a-simple-static-page-generator-with-node-js-4f58f680c47d