深入理解Hugo - 基础架构

777 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第2天,点击查看活动详情 ,祝福祖国,生日快乐 :)

通过个人站点和自定义主题实例,我们可以了解到如何使用Hugo创建自己的站点以及主题。 使用起来很简单,很快就能上手。

同时Hugo还是基于Apache 2.0协议的开源项目,这意味着你完全可以大胆地发挥自己的创造力。

比如针对源码领域的站点,像深入理解Hugo,将源码和注解分离,并可以在Golang Play上执行。 让源码的学习体验更加立体,不仅有解释,还能参与其中,修改样例,进一步帮助理解。

目前Hugo还无法支持构建这样的站点,主要有两个原因。 一是内容格式,Hugo目前主要支持的内容格式是Markdown,而上面的内容格式是.go源码文件。 其次是功能函数,Hugo并没有处理代码的函数可以直接使用,要想解析源码及注解。 虽然可以组合字符串函数进行处理,但使用起来繁琐,拓展起来困难,维护起来更是让人连连摇头。

不过,源码都给我们了,还能要求更多吗? 毕竟我们可是有追求的软件工程师啊!

无论是从实用的角度,还是通过学习优秀源码,来进行交流学习的角度,我们都有充分的理由来对这一宝藏进行发掘。

本章的目标就是打开藏宝图来了解Hugo的基础架构,主要从以下两个方向展开:

  • 对架构思路做一个概要说明,对基础架构有一个全貌的理解
  • 从模块代码入手,讨论配置和语言的关系、Hugo的模块、文件系统的组织、站点内容的收集方案、模板的生命周期,以及发布的流程。

通过阅读本章内容,我们将会对Hugo这个站点构建工具有一个全面的认识,并对各阶段之间的关系有一个清晰的认识,为接下来详细源码实现讲解章节打好基础。

出发吧,伟大的工程师啊!

Hugo的架构设计

结合Hugo站点构建领域事件,和Hugo游乐场源码,Hugo的架构设计会变得很清晰:

3.0-hugo-arch.svg

Hugo的架构思路很容易理解,主要分三大块,分别是配置模块,站点模块和依赖模块。

配置模块

Hugo最先解析的,就是用户项目的配置文件config.toml。 由configLoader发起,从硬盘读取配置文件,解析后存储为键值对对象。 configLoader主要需完成三件事,加载用户项目配置文件是第一件,用来理解用户的自定义需求。 第二件是补全默认配置Defaults Config,这样才能保其它模块正常运作。 第三件是生成模块配置信息,从用户项目开始,将用户项目作为第一个模块 - project module,在我们的实例中还有第二个模块,那就是主题模块mytheme。 模块之间有依赖关系,并且只有一个所有者Owner。 项目模块project module比较特殊,因为是初始模块,所以不属于任何其它模块。

type Module interface {
   ...
   // Owner In the dependency tree, this is the first 
   // module that defines this module as a dependency.
   Owner() Module
   ...
}

所有信息收集齐全后,会对外提供config.Provider服务:可查询,可更新配置项。

HugoSites模块

这是构建站点的核心模块,相当于DDD中的聚合根,内部组织构建站点所需要的全部信息,对外提供站点构建服务。

HugoSites的初始化依赖于DepsCfgSite,没错,有两个site。 HugoSites和Site的关系是一对多,Site和Language的关系是一一对应的,所以多语言站点会为每一个语言创建一个站点,共同组成了HugoSites。

语言项是由DepsCfg创建的,但会存储在config.Provider中,所以都用浅黄色标明。 而DepsCfg的初始化则依赖于Fsconfig.ProviderFs记载了源文件地址和发布地址。 源文件来自于用户项目,也就是实际的硬盘文件系统。 发布地址是获取自config.Provider,默认的是public文件夹,在这里会检测是否已经存在,如果没有则主动创建。 最后将新创建的信息如workingDir等信息同步回config.Provider。

可以看出,他们的依赖关系是HugoSites <- Site <- Language <- DepsCfg <- Fs

Deps模块

Hugo将构建站点所需要的所有服务和对象都称作依赖,全部放在了Deps中。

在构建依赖的过程中,会生成提供模板的TemplateProvider; 明确输入输出的媒体类型MediaType;和输出格式的OutputFormats;都会更新到config.Provider中。

也会为收集站点内容做好准备,会有Page Collection帮助收集。 最终发布站点时需要用到的发布服务则是Publisher。 这些都会更新到Site中。

同时,还需要将资源统一管理,明确规范,这样可以保障在使用时的便捷性,也符合面向对向设计原则中的单一职责原则。 包含提供统一标准文件结构服务的Path Spec; 和拥有所有媒体类型和输出格式信息的Resources Spec; 以及针对Content信息提供服务的Content Spec; 加上帮助定义资源策略,如过滤功能的Source Spec

有了Deps的帮助,所有构建站点所需的信息,如原材料、规则和输出格式等,都已准备妥当。

万事俱备,只欠东风!