15158846557 在线咨询 在线咨询
15158846557 在线咨询
所在位置: 首页 > 营销资讯 > 网站运营 > 100行node.js搭建一个简单的静态站点生成器

100行node.js搭建一个简单的静态站点生成器

时间:2023-07-25 14:18:02 | 来源:网站运营

时间:2023-07-25 14:18:02 来源:网站运营

100行node.js搭建一个简单的静态站点生成器:最近我(作者 Victor Parmar)的一个同事想开一个博客,问我有没有什么建议。在研究了一些静态站点生成器和博客引擎后,我觉得 Hugo 是个很不错的选择。然而,我同事还有一些其它需求,比如想让博客都有自定义 URL 以及自定义 CSS 主题。虽然用 Hugo 也能实现这些要求,但是我还是决定跳过学习使用 Hugo 这部分,看看如果我同事已经有随时可用的 HTML 而且在 HTML 中写博客没有问题,能否创建一个很简单的静态站点生成器。




接下来就教你使用 node.js >= 8.11.x 创建自己的静态站点生成器。我们首先设置项目:

npm initnpm i --save-exact bluebird chokidar fs-extra mustachemkdir srcmkdir public


首先我们问一个问题——为什么需要静态站点生成器?答案是实际上你并不是很需要它。如果你的博客流量很小,只需要手工编写 HTML 页面然后发布就行了。实际上,在服务器端编程兴起之前,大部分 web 发布都是通过这种方式完成的。然而,如果你已经有了一些页面和内容,修改所有页面的共有部分(比如页脚)会很麻烦。因此,如果我们能有某种简单的模板引擎,可以分离出共有内容并将其插入需要的位置,那就再好不过了。




在讲解模板引擎前,首先设置我们的网站。我们会在项目根 src(当前网站所在的位置)和 public(包含我们生成的网站)下创建 2 个文件夹。将 src 的内容复制到 public,在你的项目根下创建如下 index.js:




const Promise = require("bluebird");const fse = require("fs-extra");Promise.resolve().then(async () => { await main();});const main = async() => { await generateSite();};const generateSite = async() => { await copyAssets();};const copyAssets = async() => { await fse.emptyDir("public"); await fse.copy("src", "public");};


通过 node index.js 运行该脚本,然后坐等胜利的喜悦就完事儿了。




图:恭喜,你现在是一名后端开发了!



在第二步,我们添加一个文件监视器,这样 src 文件夹内出现任何变动都会重新生成该网站。由于这会是个总共有 500-1000 个文件的博客(假设有 100 个博客条目),我们可以在任何变化时重新生成整个网站:




const chokidar = require("chokidar");const main = async() => { await generateSite(); watchFiles();};const watchFiles = () => { const watcher = chokidar.watch( [ "src" ], { ignored: /(^|[////])/../, // chokidar will watch folders recursively ignoreInitial: false, persistent: true } ); watcher.on("change", async path => { console.log("changed " + path + ", recompiling"); await generateSite(); }); // catch ctrl+c event and exit normally process.on("SIGINT", function() { watcher.close(); });};


上面的代码清楚的显示了为何最初的版本中有个叫 generateSite 的函数。我们现在可以通过 node index.js 启动我们的静态站点生成器,如果我们现在编辑 src 中的任何文件,产生的更改会在 public 中反映出来。在这里我们还会添加一个环境变量,用以区分开发和生产模式。在开发模式下,我们将监视产生的更改并重新生成网站,而在生产模式下,我们只重新生成:




const env = process.env.NODE_ENV || "dev";const main = async () => { console.log("Running app in " + env); await generateSite(); if (env === "dev") { watchFiles(); }};


我们可以通过 export NODE_ENV=prod || set NODE_ENV=prod && node index.js 运行以上代码。注意监视更改的源目录,并不完全需要重新编译,可以跳过这一步,只需在每次进行更改时运行脚本,但编程就是要避免做重复工作。




我们快要完成了!现在我们回到创建静态站点生成器的初步阶段:建模。我们会使用 Mustache.js 用于创建模板,因为它是最简单的方法,我们的需求也不是很复杂。我们创建一个文件夹 src/patials,它会保存我们的共有部分。然后我们略微修改网站结构,这样全部页面现在就出现在 src/pages中了。剩下的工作就是加载所有的 partials 文件、加载页面并用 Mustache 渲染它们:

const fs = require("fs");const generateSite = async () => { await copyAssets(); await buildContent();};const buildContent = async () => { const pages = await compilePages(); await writePages(pages);};const compilePages = async () => { const partials = await loadPartials(); const result = {}; const pagesDir = path.join("src", "pages"); const fileNames = await fs.readdirAsync(pagesDir); for (const fileName of fileNames) { const name = path.parse(fileName).name; const fileContent = await fs.readFileAsync(path.join(pagesDir, fileName)); result[name] = Mustache.render(fileContent.toString(), {}, partials); } return result;};const loadPartials = async () => { const result = {}; const partialsDir = path.join("src", "partials"); const fileNames = await fs.readdirAsync(partialsDir); for (const fileName of fileNames) { const name = path.parse(fileName).name; const content = await fs.readFileAsync(path.join(partialsDir, fileName)); result[name] = content.toString(); } return result;};const writePages = async pages => { for (const page of Object.keys(pages)) { await fs.writeFileAsync(path.join("public", page + ".html"), pages[page]); }};


最终的代码版本参见 GitLab 上的 Software Dawg 项目(https://gitlab.com/wheresvic/software-dawg),和教程中的内容有几处细微的不同:

脚本本身在 src 文件夹中。

略微超过了 100 行,主要是由于干净的代码实践,即常量而不是文件夹路径的字符串等。

没有复制整个 src 文件夹,脚本只复制了必需的文件,比如 CSS,图像等。

项目还用了 node-sass 来编译模板 CSS,不过该环境依赖不是必需的。




另外,你还可以全局安装 browser-sync 包,通过提供的命令行 npm run live-reload 运行,这样你的浏览器会自动刷新所有页面。注意,由于我们是根据更改重新生成整个站点,所以在 Windows 上效果不太好。




通过本文的方法,几乎完美地满足了我同事的需求,不仅非常灵活,而且还能让她根据自己的喜好进行自定义。




参考资料:
https://smalldata.tech/blog/2018/08/16/building-a-simple-static-site-generator-using-node-js



关键词:静态,成器,简单

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭