Hugo添加自定义css和javascript
最近从Hexo切到了Hugo博客生成引擎,主要原因是Hexo太慢,且在页面数量上千时会崩溃。
Hugo is for people building a blog, a company site, a portfolio site, documentation, a single landing page, or a website with thousands of pages.
使用任何引擎,必须要解决添加自定义css和javascript的问题,才能非常方便地定制化。
可惜Hugo对于初学者不太友好,研究添加css和js费了不少功夫,需要通过读文档理解Hugo的设计思路。相比而言,Hexo的插件系统Hexo injector对新手更友好和容易理解。所以我们聊聊在Hugo中添加自定义css和js的正确方式。
不关心原理的急性子可以直接跳到修改模板代码
节进行实操
:-)
Hexo添加自定义css/js
在Hexo中添加自定义js非常简单,只要在根目录的scripts
目录增加一个新文件custom.js
,这段js就会被自动添加到<head>
的末尾(css类似):
hexo.extend.injector.register('head_end', () => {
return '<script data-ad-client="ca-pub-xxx" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>';
}, 'default');
Hugo添加自定义css/js的正确方式
所谓正确方式,类似Python中的pythonic
。在Hexo中添加css/js的Hexoic
方案是injector。那么Hugoic
的方案是什么?
Hugo依赖主题模板运行,添加自定义css,需要修改所使用的主题的模板文件。而改它们之前,必须对Hugo中的很多概念有基本认识。
Hugo模板查找顺序
首先理解Hugo的模板查找顺序:# Hugo Layouts Lookup Rules With Theme:
In Hugo, layouts can live in either the project’s or the themes' layout folders, and the most specific layout will be chosen. Hugo will interleave the lookups listed below, finding the most specific one either in the project or themes.
可惜这里没有明确表示project和theme layout哪个的优先级更高。参考 # Customizing a Theme。
定制模板方法
基于Hugo模板查找顺序,得出定制模板步骤:
- 拷贝
/themes/<yourtheme>/layouts/partials/xxx.html
到项目根目录/layouts/partials/xxx.html
,即在项目根目录中新建与主题一样的同构目录,其中xxx.html
是你要定制的模板文件 - 修改
/layouts/partials/xxx.html
,添加插入css/js的代码段
这样设计的好处在于主题repo作为submodule可以独立于项目repo升级,如果直接修改主题文件并提交,在升级主题时就会有诸多冲突,管理不便。
初次看到这种做法时很费解,到底是在project layout还是theme
layout新建模板文件xxx.html
?为什么可以这么做?耐着性子读了不少文档后才明白,Hugo有不少隐式的规则,这里原因在于project
layout文件夹中的模板文件会覆盖theme layout的模板。
layouts/_default/
中是一些主页、列表之类的默认模板,layouts/partials
中是一些更小的模板块:
Partials are smaller, context-aware components in your list and page templates that can be used economically to keep your templating DRY.
Partial模板的 # 查找顺序:
However, partials are simpler in that Hugo will only check in two places:
- layouts/partials/*<PARTIALNAME>.html
- themes/<THEME>/layouts/partials/*<PARTIALNAME>.html
This allows a theme’s end user to copy a partial’s contents into a file of the same name for further customization.
修改模板代码
终于可以开始操刀,这里以PaperMod
模板为例,拷贝/themes/PaperMod/layouts/partials/head.html
到/layouts/partials/head.html
,并在文件末尾添加如下代码:
...
{{ range .Site.Params.customcss }}
<link rel="stylesheet" href="{{ . | absURL }}">
{{- end }}
{{ range .Site.Params.customjs }}
<script type="text/javascript" src="{{ . | absURL }}"></script>
{{- end }}
{{ range $elem := .Site.Params.customjscssraw }}
{{ $elem | safeHTML }}
{{- end }}
看懂这段代码需要理解 # Context
的概念,和几个函数:range
,absURL
和safeHTML
,# Introduction to Hugo
Templating 中有详细介绍,不再赘述。
为什么有了customcss
和customjs
还要再加customjscssraw
的支持?原因在于有时添加原始html更方便,比如css带有integrity属性,或js需要async关键字等等。customjscssraw
最为灵活,与Hexo
injector可以达到一样的效果。可参考下节中的示例。
使用方法
使用很简单,在项目目录中的config.yml
中按需添加如下字段即可(此处覆盖了多种应用场景,包括多行js的情况):
params:
...
customcss:
- "css/xx.css"
customjs:
- "js/xx.js"
customjscssraw:
- "<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/@fortawesome/fontawesome-free@5.15.3/css/all.min.css' integrity='sha256-2H3fkXt6FEmrReK448mDVGKb3WW2ZZw35gI7vqHOE4Y=' crossorigin='anonymous'>"
- >
<script async src='https://www.googletagmanager.com/gtag/js?id=G-XXX'></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', 'G-XXX');
</script>
Tips:
如果插入的css/js是相对路径,别忘了在项目的static/
目录中添加对应的静态文件。