使用 Hugo 生成 API 接口

本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)

本文作者: 苏洋

创建时间: 2018年09月14日 统计字数: 2654字 阅读时间: 6分钟阅读 本文链接: soulteary.com/2018/09/14/…


使用 Hugo 生成 API 接口

随着 SSG 静态生成工具的蓬勃发展,市面上能看到越来越多的静态站点,一般的使用方法是通过静态展点生成工具生成静态页面,然后进行发布。

我个人使用了一年多Hugo ,不论是稳定性还是易用性方面,都无愧于开源社区里关注度第一。

但是这类静态站点生成器就只能做一些静态站点使用了么?当然不是。

Hugo 的自定义输出功能,搭配模板生成,可以轻松输出一些静态 API 接口,而内容可以使用 Markdown 来进行编写,还允许使用目录树的方式进行管理。

不论是搭配静态生成站点使用、还是简单提供给外部其他的 SPA 应用都是很方便的。

下面就来介绍如何使用 Hugo 输出 API 接口。

声明配置

首先需要在 config.toml 中指定各种页面的输出类型为 json

[outputs]
    page = ["json"]
    home = ["json"]
    teams = ["json"]
    section = ["json"]
    taxonomy = ["json"]
复制代码

定义模板

接着

接着需要在 layouts/_default/ 中创建 single.jsonitem.jsonlist.json 并使用变量和模板函数编写即可,比如:

{
    "title": "{{ .Title }}",
    "date": "{{ .Date }}",
    "type": "{{ .Type }}",
    "permalink" : "{{ .Permalink }}",
    "summary" : "{{ .Summary }}"
}
复制代码

即可将某个 Markdown 文件转换为 下面的内容:

{
  "data": {
    "title": "About",
    "date": "2018-02-09 11:47:06 -0500 -0500",
    "type": "page",
    "permalink": "/page/about/index.json",
    "summary": "An API about our school athletes!"
  }
}
复制代码

列表文件、和独立的页面文件同理,可以参考我提供的示例项目代码。

调整输出

Hugo 输出 API 依赖模板,使用的是拼凑的方法,所以输出结果难免会像下面一样,掺杂大量无用的空格字符,甚至有可能包含错误结果。

{
	"data" : 
	{
    "name": "Frank J. Robinson",
    "contact" : "+1 (555) 555 5555",
    "permalink" : "/players/frank-j-robinson/index.json",
    "year" : "junior"
    
    	
    		,"practices" : "Monday, Thursday"
    	
    
    	
    		,"sports" : "soccer, baseball"
    	
    
   	
}

}
复制代码

为了最后产物的可用性(性能、预发正确),需要使用脚本对产物进行额外处理,这里我使用 Node.js

'use strict';

const {readdirSync, statSync, readFileSync, writeFileSync} = require('fs');
const {join} = require('path');

function getAllFiles(dirPath, ext) {
  function flatten(arr) {
    return arr.reduce((flat, toFlatten) => flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten), []);
  }

  function scanDir(dirPath, ext) {
    const result = readdirSync(dirPath);
    if (!result.length) return [];
    return result.map((dirName) => {
      const filePath = join(dirPath, dirName);
      if (statSync(filePath).isDirectory()) {
        return scanDir(join(dirPath, dirName), ext);
      } else {
        if (!ext) return filePath;
        if (filePath.lastIndexOf(ext) === filePath.indexOf(ext) && filePath.indexOf(ext) > -1) return filePath;
        return '';
      }
    });
  }

  return flatten(scanDir(dirPath, ext)).filter((file) => file);
}

const allMarkdownFiles = getAllFiles('./public', '.json');
allMarkdownFiles.forEach((item) => {
  try {
    const jsonData = JSON.stringify(JSON.parse(readFileSync(item, 'utf8')));
    writeFileSync(item, jsonData);
  } catch (e) {
    console.error(`${item} content error.`);
    writeFileSync(item, JSON.stringify({code: 500, desc: 'Unexpected token'}));
  }
});
复制代码

将脚本保存为 checker.js 执行 node checker 即可批量对 Hugo 的产物进行正确性校验和结果压缩。

比如上面的产物在执行完毕处理脚本后会变成:

{"data":{"name":"Frank J. Robinson","contact":"+1 (555) 555 5555","permalink":"/players/frank-j-robinson/index.json","year":"junior","practices":"Monday, Thursday","sports":"soccer, baseball"}}
复制代码

把这个脚本配置到 CI 中,即可完成修改 Markdown 文件,就能够自动生成高性能可用的静态 API 了。

其他

相关示例代码,可以访问:

Hugo 还有一堆其他的玩法,后面有机会再聊。

-EOF


我现在有一个小小的折腾群,里面聚集了一些喜欢折腾的小伙伴。

在不发广告的情况下,我们在里面会一起聊聊软件、HomeLab、编程上的一些问题,也会在群里不定期的分享一些技术沙龙的资料。

喜欢折腾的小伙伴欢迎扫码添加好友。(请注明来源和目的,否则不会通过审核) 关于折腾群入群的那些事

关于折腾群入群的那些事

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值