从 WordPress 切换到 Hugo
已发表: 2022-03-10当 WordPress 5 发布时,我对使用 Gutenberg 编辑器创建自定义块感到兴奋,因为我个人博客上的帖子有几个可以变成块的功能,从而更容易设置我的内容。 拥有它绝对是一件很酷的事情,但它仍然感觉很臃肿。
大约在同一时间,我开始阅读越来越多的关于静态站点生成器和 JAMstack 的内容(Chris Ferdinandi 的这篇文章说服了我)。 对于个人的业余项目,您可以忽略各种各样的问题,但作为专业人士,您必须确保输出尽可能好的质量。 性能、安全性和可访问性成为首先要考虑的事情。 您绝对可以将 WordPress 优化得非常快,但比 CDN 上不需要每次都查询数据库或生成页面的静态站点更快? 没那么容易。
我认为我可以通过我的个人项目将其付诸实践来学习,然后能够将其用于专业项目,也许你们中的一些人也想知道如何。 在本文中,我将介绍如何从 WordPress 过渡到名为 Hugo 的特定静态站点生成器。
Hugo 是用 Go 构建的,一旦你习惯了语法,这是一种非常快速且易于使用的语言,我将对此进行解释。 这一切都在本地编译,因此您可以直接在计算机上预览您的站点。 然后该项目将保存到私有存储库。 此外,我将引导您了解如何在 Netlify 上托管它,并将您的图像保存在 Git LFS(大文件存储)上。 最后,我们将了解如何设置内容管理系统以使用 Netlify CMS 添加帖子和图像(类似于 WordPress 后端)。
请注意,所有这些都是完全免费的,如果您问我,这真是太棒了(尽管如果您用完所有 LFS 存储或您的网站流量很大,您将不得不支付额外费用)。 另外,我是从 Bitbucket 用户的角度编写的,它在 Mac 上运行。 有些步骤可能略有不同,但无论您使用什么设置,您都应该能够遵循。
您需要熟悉 HTML、CSS、JS、Git 和命令终端。 对像 Liquid 这样的模板语言有一些概念也很有用,但我们将回顾 Hugo 的模板以帮助您入门。 尽管如此,我还是会提供尽可能多的细节!
我知道这听起来很多,在我开始研究这个之前,它也适合我。 我将尝试通过分解步骤来使您的过渡尽可能顺利。 找到所有资源并不是很困难,但是我涉及到一些猜测,从一个文档到下一个文档。
- 从 WordPress 导出内容
- 准备你的博客设计
- 设置新存储库
- 激活 Git LFS(可选)
- 在 Netlify 上创建站点
- 准备 Netlify 大型媒体(可选)
- 在您的计算机上设置 Hugo
- 创建您的自定义主题
- 关于 Hugo 语法的注释
- 内容和数据
- 在 Netlify 上部署
- 设置自定义域
- 在 Netlify CMS 上编辑内容
注意:如果您对其中一些有疑问,请在评论中告诉我,我会尽力提供帮助,但请注意,这注定适用于没有十几个小部件的简单静态博客或评论(您可以稍后设置),而不是公司网站或个人投资组合。 不过,您无疑可以,但为了简单起见,我将坚持使用简单的静态博客。
先决条件
在我们做任何事情之前,让我们创建一个项目文件夹,从我们的工具到本地存储库的所有内容都将驻留。 我将其称为“WP2Hugo”(您可以随意称呼它)。
本教程将使用一些命令行工具,例如 npm 和 Git。 如果您还没有它们,请在您的机器上安装它们:
- 安装 Git
- 安装 Node.js 和 npm(Node.js 包括 npm)
- 安装 Homebrew(推荐给 macOS/Linux 用户)
安装完这些,让我们开始吧!
1. 从 WordPress 导出内容
首先,我们需要从 WordPress 导出您的内容:帖子、页面和上传。 Hugo 提到了一些可用的工具,但就个人而言,只有一个有效:blog2md。 这是通过在命令终端中运行带有 Node.js 的 JavaScript 文件来工作的。 它采用 WordPress 导出的 XML 文件,并输出具有正确结构的 Markdown 文件,将您的 HTML 转换为 Markdown 并添加所谓的 Front Matter,这是一种在每个文件开头格式化元数据的方法。
转到您的 WordPress 管理员,然后打开工具菜单、导出子菜单。 你可以从那里导出你想要的东西。 我将导出的文件称为YOUR-WP-EXPORT.xml 。
您可以准确选择要从 WordPress 博客导出的数据。
在我们的 WP2Hugo 文件夹中,我建议创建一个名为blog2md
的新文件夹,您将在其中放置来自 blog2md 工具的文件,以及从 WordPress 导出的 XML ( YOUR-WP-EXPORT.xml )。 此外,在其中创建一个新文件夹, out
您的 Markdown 帖子的所在位置。 然后,打开您的命令终端,并使用cd
命令导航到您新创建的“blog2md”文件夹(或键入带有空格的cd
并将文件夹拖到终端中)。
您现在可以运行以下命令来获取您的帖子:
npm install node index.js w YOUR-WP-EXPORT.xml out
查看/WP2Hugo/blog2md/out
目录以检查您的所有帖子(和潜在页面)是否都在那里。 如果是这样,您可能会注意到文档中有一些关于评论的内容:我有一个无评论博客,所以我不需要执行它们,但 Hugo 确实提供了几个评论选项。 如果您对 WordPress 有任何意见,您可以将它们导出以供以后使用 Disqus 等专业服务重新实施。
如果您对 JS 足够熟悉,则可以通过编辑wordpressImport
函数来调整index.js文件以更改发布文件的输出方式。 您可能想要捕获特色图片、删除永久链接、更改日期格式或设置类型(如果您有帖子和页面)。 您必须根据自己的需要对其进行调整,但要知道循环( posts.forEach(function(post){ ... })
)会遍历导出的所有帖子,因此您可以检查 XML 内容该循环中的每个帖子并自定义您的 Front Matter。
此外,如果您需要更新帖子中包含的 URL(在我的情况下,我想让图像链接相对而不是绝对)或日期格式,这是这样做的好时机,但不要为此失眠. 许多文本编辑器提供批量编辑功能,因此您可以插入正则表达式并在文件中进行所需的更改。 此外,您可以根据需要多次运行blog2md
脚本,因为它将覆盖输出文件夹中任何先前存在的文件。
一旦你有你导出的 Markdown 文件,你的内容就准备好了。 下一步是让您的 WordPress 主题准备好在 Hugo 中工作。
2. 准备你的博客设计
我的博客有一个典型的布局,带有标题、导航栏、内容和侧边栏以及页脚——设置起来非常简单。 我没有复制我的 WordPress 主题,而是从头开始重建它,以确保没有多余的样式或无用的标记。 这是实施新的 CSS 技术( pssst...Grid 非常棒! )并设置更一致的命名策略(类似于 CSS Wizardry 的指南)的好时机。 您可以随心所欲,但请记住,我们正在努力优化我们的博客,因此最好回顾一下您拥有的内容并决定是否仍然值得保留。
首先将您的博客分成几部分,这样您就可以清楚地看到哪些内容去了哪里。 这将帮助您构建标记和样式。 顺便说一句,Hugo 具有将 Sass 编译为 CSS 的内置功能,所以您可以随意将这些样式分解为更小的文件!
当我说简单时,我的意思是非常简单。
或者,您现在可以完全绕过此步骤,并在设置 Hugo 站点时随时为您的博客设置样式。 我已经有了基本的标记,并且更喜欢样式的迭代方法。 这也是查看哪些有效,哪些无效的好方法。
3. 建立一个新的仓库
既然这已经解决了,我们需要设置一个存储库。 我假设您将要为此创建一个新的存储库,这将是使用 Git LFS(大型文件系统)的绝佳机会。 我建议现在这样做的原因是,当您已经拥有数百个图像时,实施 Git LFS 并不那么顺利。 我已经做到了,但这是您可能想要避免的头痛。 这也将为 Netlify 带来其他好处。
虽然我将通过 Bitbucket 及其专有的 Git GUI、Sourcetree 来完成所有这些工作,但您绝对可以使用 GitHub 和 GitLab 以及他们自己的桌面工具来完成这一切。 您也可以直接在命令终端中执行此操作,但我喜欢尽可能自动化和简化流程,从而降低犯愚蠢错误的风险。
在您选择的 Git 平台上创建新存储库后,在本地项目文件夹 (WP2Hugo) 中创建一个空文件夹,例如hugorepo
,然后打开命令终端或 Git GUI 工具并初始化本地 Git 存储库; 然后,将其链接到远程存储库(您通常可以在新创建的远程存储库上找到要使用的确切命令)。
我建议创建一个dev
(或stage
)分支,以便您的主分支严格用于生产部署。 它还将限制仅在您完成一系列潜在更改时才生成新版本。 创建分支可以在本地完成,也可以在存储库的远程网页上完成。
通过单击分支切换器并输入新名称,GitHub 可以轻松创建分支。 在 GitLab 上,您需要打开“加号”下拉菜单才能访问该选项。 Bitbucket 要求您打开左侧的“加号”菜单以打开滑出式菜单,然后单击“开始工作”部分中的“创建分支”。
4. 激活 Git LFS(可选)
Git 大文件系统是 Git 的一项功能,可让您以更有效的方式保存大文件,例如 Photoshop 文档、ZIP 存档以及在我们的示例中的图像。 由于图像可能需要版本控制但不完全是代码,因此将它们与常规文本文件不同地存储是有意义的。 它的工作方式是将图像存储在远程服务器上,存储库中的文件将是一个文本文件,其中包含指向该远程资源的指针。
唉,这不是您只需单击即可启用的选项。 您必须设置存储库以激活 LFS,这需要在本地进行一些工作。 安装 Git 后,您需要安装 Git-LFS 扩展:
git lfs install
如果像我一样,该命令对您不起作用,请尝试使用 Homebrew 替代方法(适用于 macOS 或 Linux):
brew install git-lfs
完成后,您必须指定要在存储库中跟踪哪些文件。 我会将我上传到 WordPress 的/upload
文件夹中的所有图像托管在我的 Hugo 设置中的同名文件夹中,除了这个文件夹将位于/static
文件夹中(编译后将解析为根目录)。 确定您的文件夹结构,并在其中跟踪您的文件:
git lfs track "static/uploads/*"
这将跟踪/static/uploads
文件夹中的任何文件。 您还可以使用以下内容:
git lfs track "*.jpg"
这将跟踪存储库中的所有 JPG 文件。 例如,您可以混合搭配以仅跟踪特定文件夹中的 JPG。
有了它,您可以将 LFS 配置文件提交到您的存储库并将其推送到您的远程存储库。 下次您在本地提交与 LFS 跟踪配置匹配的文件时,它将被“转换”为 LFS 资源。 如果在开发分支上工作,请将此提交合并到您的主分支中。
现在让我们来看看 Netlify。
5. 在 Netlify 上创建站点
此时,您的存储库已设置完毕,因此您可以继续在 Netlify 上创建一个帐户。 如果您愿意,您甚至可以使用您的 GitHub、GitLab 或 Bitbucket 帐户登录。 进入仪表板后,单击右上角的“从 Git 新建站点”按钮,然后创建新的 Netlify 站点。
注意:您现在可以将所有选项保留为默认值。
选择您的 Git 提供程序:这将打开一个弹出窗口来对您进行身份验证。 完成后,窗口将关闭,您将看到您有权访问的 Git 提供程序上的存储库列表。 选择您新创建的存储库并继续。 你会被问到一些事情,其中大部分你可以默认离开,因为所有选项都可以在以后编辑。
现在,在站点设置中,单击“更改站点名称”并将您的站点命名为您想要的任何名称 - 我将使用chris-smashing-hugo-blog
。 我们现在可以通过chris-smashing-hugo-blog.netlify.com
访问该站点:一个漂亮的 404 页面!
6. 准备 Netlify 大型媒体(可选)
如果您设置了 Git LFS 并计划使用 Netlify,您将需要遵循这些步骤。 这有点复杂,但绝对值得:它使您能够在将自动转换的图像 URL 上设置查询字符串。
假设您有一个指向Portrait.jpg的链接,这是一个 900×1600 像素的图像。 使用 Netlify 大型媒体,您可以调用文件Portrait.jpg?nf_resize=fit&w=420 ,它会按比例缩放它。 如果您同时定义w
和h
,并设置nf_resize=smartcrop
,它将通过裁剪来调整大小以专注于图像的兴趣点(由奇特的算法确定,也就是机器人大脑魔法! )。 我发现这是获得 WordPress 生成的缩略图的好方法,而无需在我的存储库中为图像创建多个文件。
如果这听起来对您有吸引力,让我们进行设置!
第一步是通过 npm 安装 Netlify 的命令行界面(CLI):
npm install netlify-cli -g
如果它有效,运行命令netlify
应该会产生有关该工具的信息。
然后,您需要确保您位于本地存储库文件夹中(我之前命名为“hugorepo”),然后执行:
netlify login
授权令牌。 接下来,我们必须安装 Netlify 大型媒体插件。 跑步:
netlify plugins:install netlify-lm-plugin netlify lm:install
在结果消息的末尾应该显示一个命令行,您必须复制它(在 Mac 上应该类似于/Users/YOURNAME/.netlify/helper/path.bash.inc
运行它。 请注意,Keychain 可能会在 macOS 上要求您提供机器的管理员密码。
下一步是链接 Netlify:
netlify link
您可以在此处提供您的站点名称(我提供了之前给它的chris-smashing-hugo-blog
名称)。 有了这个,您只需要通过执行以下命令来设置大型媒体功能:
netlify lm:setup
将这些新更改提交到本地存储库,并将它们推送到远程开发分支。 我在 Sourcetree 和 Keychain 上遇到了一些错误,如git "credential-netlify" is not a git command
。 如果是这种情况,请尝试使用以下命令手动推送:
git add -A git commit -m "Set up Netlify Large media" git push
如果这不起作用,您可能需要安装 Netlify credential Helper。 以下是使用 Homebrew 进行操作的方法:
brew tap netlify/git-credential-netlify brew install git-credential-netlify
现在尝试推送您的提交(使用您的 GUI 或命令终端):它应该可以工作!
注意:如果您更改了 Netlify 密码,请再次运行netlify logout
和netlify login
。
你可能会问:“所有这些,我们甚至还没有初始化我们的 Hugo 构建?” 是的,我知道,这需要一段时间,但过渡的所有准备工作都已完成。 我们现在可以建立我们的 Hugo 博客了!
7. 在你的电脑上设置 Hugo
您首先需要使用提供的任何选项在您的计算机上安装 Hugo。 我将使用 Homebrew,但 Windows 用户可以使用 Scoop 或 Chocolatey,或者直接下载包。
brew install hugo
然后,您需要创建一个新的 Hugo 站点,但它不喜欢将其设置在非空文件夹中。 第一个选项:您可以在新文件夹中创建它并将其内容移动到本地存储库文件夹:
hugo new site your_temporary_folder
第二种选择:您可以使用标志强制它安装在本地存储库中,只需确保在正确的文件夹中运行它:
hugo new site . --force
您现在有一个 Hugo 站点,您可以使用以下命令启动它:
hugo server
您将在localhost
上获得本地预览。 可悲的是,您没有内容,也没有自己的主题。 不用担心,我们很快就会进行设置!
让我们首先看一下配置文件(在我的例子中是config.toml ):让我们设置博客的名称和基本 URL(这必须与 Netlify 仪表板上的 URL 匹配):
title = "Chris' Smashing Hugo Blog" baseURL = "https://chris-smashing-hugo-blog.netlify.com"
在本地开发时,此链接将被覆盖,因此您不应遇到 404 错误。
让我们以 Markdown 格式将我们导出的文章提供给 Hugo。 从第一步开始,它们应该位于/WP2Hugo/blog2md/out
文件夹中。 在 Hugo 文件夹(又名本地存储库目录)中,访问content
文件夹并创建一个名为posts
的子文件夹。 把你的 Markdown 文件放在那里,然后让我们设置一个主题。
8. 创建您的自定义主题
对于这一步,我建议下载 Saito 样板,这是一个包含您开始需要的所有部分的主题(并且没有样式)——一个非常有用的起点。 当然,如果您想跳过这部分过程,您可以查看 Hugo 的现成主题集合。 全取决于你!
从本地存储库文件夹中,将主题克隆到themes/saito
:
git submodule add https://github.com/hakuoku/saito-boilerplate.git themes/saito
您可以将此文件夹重命名为您想要的任何名称,例如cool-theme
。 你必须通过编辑config.toml/yaml/json文件来告诉你的 Hugo 配置你想使用哪个主题。 将主题值编辑为saito
或cool-theme
或任何主题的文件夹名称。 您的预览现在应该显示您的博客标题以及版权行。 这是一个开始,对吧?
打开主题的layout/partials/home.html文件并编辑它以显示您的内容,限制为posts
类型的前五个项目(在content/posts/
文件夹内),包括range
、 first
和where
:
<div class="container"> {{ range first 5 (where .Paginator.Pages "Type" "posts") }} <article class="post post--{{ .Params.class }}"> <h2 class="post__title">{{ .Title }}</h2> <section class="post__content"> {{ .Content }} </section> </article> {{ end }} </div>
您的内容现在以最基本的方式可见。 是时候把它变成你的了——让我们开始吧!
与 Hugo 一起制作模板
如果您愿意,可以先阅读 Hugo 模板简介,但我将尝试复习一些有助于您理解基础知识的要点。
Hugo 中的所有操作都定义在分隔符中:双花括号(例如{{ .Title }}
),如果您之前做过一些模板操作,应该会觉得很熟悉。 如果还没有,请将其视为在标记中的特定点执行操作或注入值的一种方式。 对于块,它们以{{ end }}
标记结束,用于除短代码之外的所有操作。
主题有一个layout
文件夹,其中包含布局的各个部分。 _default
文件夹将是 Hugo 的起点, baseof.html是(您猜对了! )布局的基础。 它将调用每个组件,称为“partials”(更多信息请参见 Hugo 关于 Partial Template 的文档),类似于您在 PHP 中使用include
的方式,您可能已经在 WordPress 主题中看到过。 部分可以调用其他部分——只是不要让它成为一个无限循环。
您可以使用{{ partial "file.html" . }}
{{ partial "file.html" . }}
语法。 partial
部分非常简单,但另外两个部分可能需要解释。 您可能希望必须编写partials/file.html ,但由于所有的 partials 都在 partials”文件夹中,Hugo 可以很好地找到该文件夹。 当然,如果您需要更多的组织,您可以在“partials”文件夹中创建子文件夹。
您可能已经注意到一个杂散点:这是您传递给局部的上下文。 如果您有一个菜单部分,以及一个链接和标签列表,您可以将该列表传递给部分,以便它只能访问该列表,而不能访问其他任何内容。 我将在下一节中详细讨论这个难以捉摸的点。
您的baseof.html文件是一个 shell,它调用呈现您的博客布局所需的所有各种部分。 它应该有最少的 HTML 和大量的部分:
<!DOCTYPE html> <html lang="{{ .Site.LanguageCode }}"> <head> <title>{{ block "title" . }}{{ .Site.Title }}{{ end }}</title> {{ partial "head.html" . }} </head> <body> {{ partial "header.html" . }} {{ partial "nav.html" . }} <main> {{ block "main" . }}{{ end }} </main> <aside> {{ partial "sidebar.html" . }} </aside> {{ partial "footer.html" . }} </body> </html>
{{ block "main" . }}{{ end }}
{{ block "main" . }}{{ end }}
行不同,因为它是一个块,它是使用基于当前页面(主页、单个帖子页面等)的内容的模板定义的,带有{{ define "main" }}
。
样式表
在您的主题中,创建一个名为assets
的文件夹,我们将在其中放置一个css
文件夹。 它将包含我们的 SCSS 文件,或可信赖的 ol' CSS 文件。 现在, partials
文件夹中应该有一个css.html文件(由head.html 调用)。 要将 Sass/SCSS 转换为 CSS,并缩小样式表,我们将使用这一系列函数(使用 Hugo Pipes 语法,而不是将函数相互包装):
{{ $style := resources.Get "css/style.scss" | toCSS | minify | fingerprint }}
作为奖励——因为我很难找到一个直接的答案——如果你想使用 Autoprefixer,Hugo 还实现了 PostCSS。 您可以在第一行的toCSS
和minify
之间添加一个额外的管道函数,如下所示:
{{ $style := resources.Get "css/style.scss" | toCSS | postCSS | minify | fingerprint }}
在你的 Hugo 博客的根目录下创建一个“postcss.config.js”文件,并传入选项,例如:
module.exports = { plugins: { autoprefixer: { browsers: [ "> 1%", "last 2 versions" ] } }, }
快! 从 Sass 到前缀、缩小的 CSS。 “指纹”管道功能是确保文件名是唯一的,例如style.c66e6096bdc14c2d3a737cff95b85ad89c99b9d1.min.css 。 如果您更改样式表,则指纹会更改,因此文件名会不同,因此您将获得有效的缓存破坏解决方案。
9. 关于 Hugo 语法的注释
我想确保您理解“点”,这就是 Hugo 如何定义您将在模板中使用的变量(或者用我自己的话来说,提供上下文参考)。
点和范围
Dot 就像一个顶级变量,您可以在任何模板或简码中使用它,但它的值仅限于其上下文。 像baseof.html这样的顶级模板中的点值与循环块或with
块中的值不同。
假设这是在我们的head.html部分模板中:
{{ with .Site.Title }}
{{ . }} {{ 结尾 }}
即使我们在主范围内运行它,Dot 的值也会根据上下文发生变化,在本例中为.Site.Title
。 因此,要打印该值,您只需要编写.
而不是再次重新输入变量名。 一开始这让我很困惑,但你很快就习惯了,它有助于减少冗余,因为你只为变量命名一次。 如果某些东西不起作用,通常是因为您试图在作用域块内调用顶级变量。
那么如何在作用域块内使用顶级作用域呢? 好吧,假设您要检查一个值但使用另一个值。 您可以使用$
,它始终是顶级范围:
{{ with .Site.Params.InfoEnglish }}{{ $.Site.Params.DescriptionEnglish }}{{ end }}
在我们的条件内,范围是.Site.Params.InfoEnglish
但我们仍然可以使用$
访问它之外的值,直观地使用.Site.Params.DescriptionEnglish
将不起作用,因为它会尝试解析为.Site.Params.InfoEnglish.Site.Params.DescriptionEnglish
,抛出错误。
自定义变量
您可以使用以下语法分配变量:
{{ $customvar := "custom value" }}
变量名必须以$
开头,如果是第一次赋值,赋值运算符必须是:=
=
否则像这样:
{{ $customvar = "updated value" }}
您可能会遇到的问题是,这不会超出范围,这让我想到了下一点。
刮
Scratch 功能允许您分配在所有上下文中可用的值。 假设您在movies.json文件中有一个电影列表:
[ { "name": "The Room", "rating": 4 }, { "name": "Back to the Future", "rating": 10 }, { "name": "The Artist", "rating": 7 } ]
现在,您想要遍历文件的内容并存储您最喜欢的内容以供以后使用。 这就是 Scratch 发挥作用的地方:
{{ .Scratch.Set "favouriteMovie" "None" }}{{ /* Optional, just to get you to see the difference syntax based on the scope */ }} {{ range .Site.Data.movies }} {{ if ge .rating 10 }} {{ /* We must use .Scratch prefixed with a $, because the scope is .Site.Data.movies, at the current index of the loop */ }} {{ $.Scratch.Set "favouriteMovie" .name }} {{ end }} {{ end }} [...] My favourite movie is {{ .Scratch.Get "favouriteMovie" }} <!-- Expected output => My favourite movie is Back to the Future -->
使用 Scratch,我们可以从循环内部提取一个值并在任何地方使用它。 随着您的主题变得越来越复杂,您可能会发现自己正在使用 Scratch。
注意:这只是一个示例,因为可以优化此循环以在不使用 Scratch 的情况下输出此结果,但这应该让您更好地了解它的工作原理。
条件句
从 JavaScript 或 PHP 的角度来看,条件句的语法与您所期望的略有不同。 本质上,有些函数接受两个参数(如果您直接调用值,括号是可选的):
{{ if eq .Site.LanguageCode "en-us" }}Welcome!{{ end }}
这些功能有几个:
-
eq
检查是否相等 ne
检查不平等gt
检查大于ge
检查大于或等于- 它检查
lt
-
le
检查小于或等于
注意:您可以在 Hugo 函数快速参考中了解有关 Hugo 提供的所有函数。
空白
如果你和我一样对输出很挑剔,你可能会注意到一些不需要的空行。 这是因为 Hugo 会按原样解析您的标记,例如,在未满足的条件周围留下空白行。
假设我们有这个假设的部分:
{{ if eq .Site.LanguageCode "en-us" }} <p>Welcome to my blog!</p> {{ end }} <img src="/uploads/portrait.jpg" alt="Blog Author">
如果网站的语言代码不是en-us
,这将是 HTML 输出(注意图像标签前的三个空行):
<img src="/uploads/portrait.jpg" alt="Blog Author">
Hugo 提供了一种语法来解决这个问题,在分隔符内部的花括号旁边使用连字符。 {{-
将修剪大括号之前的空格, -}}
将修剪大括号之后的空格。 您可以同时使用其中一个或两个,但只需确保连字符和分隔符内的操作之间有一个空格。
因此,如果您的模板包含以下内容:
{{- if eq .Site.LanguageCode "en-us" -}} <p>Welcome to my blog!</p> {{- end -}} <img src="/uploads/portrait.jpg" alt="Blog Author">
…然后标记将导致这个(没有空行):
<img src="/uploads/portrait.jpg" alt="Blog Author">
这对于其他情况很有帮助,例如带有display: inline-block
的元素,它们之间不应有空格。 相反,如果您想确保每个元素都在标记中的自己的行中(例如在{{ range }}
循环中),则必须小心放置连字符以避免“贪婪”的空白修剪。
如果站点的语言代码匹配“ en-us
”(在p
和img
标签之间不再有换行符),上面的示例将输出以下内容:
<p>Welcome to my blog!</p><img src="/uploads/portrait.jpg" alt="Blog Author">
10. 内容和数据
您的内容存储为 Markdown 文件,但您也可以使用 HTML。 Hugo 将在构建您的网站时正确呈现它。
您的主页将调用_default/list.html
布局,可能如下所示:
{{ define "main" }} {{ partial "list.html" . }} {{ end }}
主块调用带有上下文的list.html
部分.
,也就是顶级。 list.html
部分可能如下所示:
{{ define "main" }} <ol class="articles"> {{ range .Paginator.Pages }} <li> <article> <a href="{{ .URL }}"> <h2>{{ .Title }}</h2> <img src="{{ .Params.featuredimage }}" alt=""> <time datetime="{{ .Date.Format "2006-01-02" }}"> {{ .Date.Format "January 2 2006" }} </time> </a> </article> </li> {{ end }} </ol> {{ partial "pagination.html" . }} {{ end }}
现在我们有一个基本的文章列表,您可以根据需要设置样式! 每页的文章数在配置文件中定义, paginate = 5
(在 TOML 中)。
你可能会像我一样对 Hugo 中的日期格式感到困惑。 每次将单位映射到一个数字(第一个月、第二天、第三个小时等),当我看到下面 Go 语言文档提供的视觉解释时,我就更有意义了——这有点奇怪,但也有点聪明!
Jan 2 15:04:05 2006 MST => 1 2 3 4 5 6 -7
现在剩下要做的就是在一个页面上显示您的帖子。 您可以编辑post.html
部分以自定义文章的布局:
<article> <header> <h1>{{ .Title }}</h1> <p> Posted on <time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "2006. 1. 2" }}</time> </p> </header> <section> {{ .Content }} </section> </article>
这就是您展示内容的方式!
如果您想自定义 URL,请通过添加[permalinks]
选项 (TOML) 来更新您的配置文件,在这种情况下,这将使 URL 看起来像my-blog.com/post-slug/
:
[permalinks] posts = ":filename/"
如果您想生成内容的 RSS 提要(因为 RSS 很棒),请在您的站点配置文件中添加以下内容(如果检测到这些选项,Saito 的默认模板将在head.html中显示适当的标签):
rssLimit = 10 [outputFormats] [outputFormats.RSS] mediatype = "application/rss" baseName = "feed"
但是,如果您在帖子之外有某种内容怎么办? 这就是数据模板的用武之地:您可以创建 JSON 文件并提取其数据以创建菜单或侧边栏中的元素。 YAML 和 TOML 也是选项,但对于复杂数据(例如嵌套对象)的可读性较差。 当然,您可以在站点的配置文件中设置它,但对我来说,它不太容易导航,也不太宽容。
让我们创建一个您可能希望在侧边栏中显示的“酷站点”列表 - 每个站点都有一个链接和一个标签,作为 JSON 中的数组:
{ "coolsites": [ { "link": "https://smashingmagazine.com", "label": "Smashing Magazine" }, { "link": "https://gohugo.io/", "label": "Hugo" }, { "link": "https://netlify.com", "label": "Netlify" } ] }
您可以将此文件保存在存储库根目录或主题根目录中的data
文件夹中,例如/data/coolsites.json
。 然后,在您的sidebar.html
部分中,您可以使用.Site.Data.coolsites
使用range
对其进行迭代:
<h3>Cool Sites:</h3> <ul> {{ range .Site.Data.coolsites.coolsites }} <li><a href="{{ .link }}">{{ .label }}</a></li> {{ end }} </ul>
这对于您想要迭代的任何类型的自定义数据都非常有用。 我用它为我的主题创建了一个谷歌字体列表,帖子可以属于哪些类别,作者(带有个人简介、头像和主页链接)、要显示的菜单以及显示顺序。 你真的可以用这个做很多事情,而且非常简单。
关于数据等的最后一个想法:您放入 Hugo /static
文件夹中的任何内容都将在实时构建的根 ( /
) 上可用。 主题文件夹也是如此。
11. 在 Netlify 上部署
所以你已经完成了,或者你只是想看看 Netlify 运行了什么样的魔法? 对我来说听起来不错,只要您的本地 Hugo 服务器不返回错误。
提交您的更改并将它们推送到您的远程开发分支 ( dev
)。 接下来前往 Netlify,并访问您网站的设置。 您将看到“构建和部署”选项。 我们需要在这里改变几件事。
- 首先,在“构建设置”部分,确保“构建命令”设置为
hugo
,并且“发布目录”设置为public
(建议您保留在 Hugo 配置文件中的默认设置); - 接下来,在“部署上下文”部分,将“生产分支”设置为存储库中的主分支。 我还建议您将“分支部署”设置为“仅部署生产分支”;
- 最后,在“环境变量”部分,编辑变量并单击“新建变量”。 我们将使用以下对将 Hugo 环境设置为 0.53:将 key 设置为
HUGO_VERSION
并将 value 设置为0.53
。
现在转到您的远程存储库并将您的开发分支合并到您的主分支:这将是部署您更新的博客的钩子(这可以自定义,但默认值对我来说是合理的)。
回到您的 Netlify 仪表板,您的站点的“生产部署”应该有一些新活动。 如果一切顺利,这应该处理并解析为“已发布”标签。 单击部署项将打开带有操作日志的概览。 在顶部,您将看到“预览部署”。 继续,点击它——你应得的。 它还活着!
12. 设置自定义域
将 URL 设置为my-super-site.netlify.com
不符合您的口味,而您已经拥有my-super-site.com
? 我知道了。 让我们改变它!
前往您的域注册商并转到您域的 DNS 设置。 在这里,您必须创建一个新条目:您可以设置指向my-super-site.netlify.com
的 ALIAS/CNAME 记录,或者设置将您的域指向 Netlify 的负载均衡器的 A 记录,即在撰写本文时为104.198.14.52
。
您可以在 Netlify 的自定义域文档中找到最新信息。 负载均衡器 IP 将位于“根和 www 自定义域的手动 DNS 配置”下的 DNS 设置部分。
完成后,转到您网站在 Netlify 上的仪表板,然后单击“域设置”,您将在其中看到“添加自定义域”。 输入您的域名进行验证。
您还可以通过“域”选项卡中的仪表板来管理您的域。 此页面上的界面感觉不那么令人困惑,但也许它会帮助您更了解您的 DNS 设置,就像它对我所做的那样。
注意:如果您想通过他们购买域名,Netlify 也可以为您处理一切。 这更容易,但需要额外的费用。
设置自定义域后,在“域设置”中,向下滚动到“HTTPS”部分并启用 SSL/TLS 证书。 这可能需要几分钟,但它会授予您免费证书:您的域现在在 HTTPS 上运行。
13. 在 Netlify CMS 上编辑内容
如果您想像在 WordPress 的后端界面上那样编辑文章、上传图片和更改博客设置,您可以使用 Netlify CMS,它提供了一个非常好的教程。 它是一个可以为你处理所有事情的文件(它与生成器无关:它可以与 Jekyll、Eleventy 等一起使用)。
您只需要在一个文件夹中上传两个文件:
- CMS(单个 HTML 文件);
- 一个配置文件(一个 YAML 文件)。
后者将保存您特定站点的所有设置。
转到您的 Hugo 根目录的/static
文件夹并创建一个新文件夹,您将通过my-super-site.com/FOLDER_NAME
访问该文件夹(我将调用我的admin
)。 在此admin
文件夹中,通过复制 Netlify CMS 提供的标记创建一个index.html文件:
<!doctype html> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Content Manager</title> </head> <body> <!-- Include the script that builds the page and powers Netlify CMS --> <script src="https://unpkg.com/netlify-cms@^2.0.0/dist/netlify-cms.js"></script> </body> </html>
您需要创建的另一个文件是配置文件: config.yml 。 它将允许您定义站点的设置(名称、URL 等),以便您可以设置帖子的头条内容应包含的内容,以及您的数据文件(如果有)应如何编辑。 设置起来有点复杂,但这并不意味着它不容易。
如果您使用的是 GitHub 或 GitLab,请使用以下命令启动config.yml 文件:
backend: name: git-gateway branch: dev # Branch to update (optional; defaults to master)
如果您使用的是 Bitbucket,情况会有所不同:
backend: name: bitbucket repo: your-username/your-hugorepo branch: dev # Branch to update (optional; defaults to master)
然后,对于我们的上传,我们必须告诉 CMS 将它们存储在哪里:
media_folder: "static/images/uploads" # Media files will be stored in the repo under static/images/uploads public_folder: "/images/uploads" # The src attribute for uploaded media will begin with /images/uploads
当您创建新帖子时,CMS 将为文件名生成 slug,您可以使用三个选项对其进行自定义:
slug: encoding: "ascii" # You can also use "unicode" for non-Latin clean_accents: true # Removes diacritics from characters like e or a sanitize_replacement: "-" # Replace unsafe characters with this string
最后,您需要定义帖子中数据的结构。 我还将定义数据文件coolsites的结构——以防万一我想将另一个站点添加到列表中。 这些是用绝对是最冗长的collections
对象设置的,还有一些不错的选项,您可以在此处阅读更多信息。
collections: - name: "articles" # Used in routes, eg, /admin/collections/blog label: "Articles" # Used in the Netlify CMS user interface folder: "content/posts" # The path to the folder where the posts are stored, usually content/posts for Hugo create: true # Allow users to create new documents in this collection slug: "{{slug}}" # Filename template, eg, post-title.md fields: # The fields for each document, usually in front matter - {label: "Title", name: "title", widget: "string", required: true} - {label: "Draft", name: "draft", widget: "boolean", default: true } - {label: "Type", name: "type", widget: "hidden", default: "post" } - {label: "Publish Date", name: "date", widget: "date", format: "YYYY-MM-DD"} - {label: "Featured Image", name: "featuredimage", widget: "image"} - {label: "Author", name: "author", widget: "string"} - {label: "Body", name: "body", widget: "markdown"} - name: 'coolsites' label: 'Cool Sites' file: 'data/coolsites.json' description: 'Website to check out' fields: - name: coolsites label: Sites label_singular: 'Site' widget: list fields: - { label: 'Site URL', name: 'link', widget: 'string', hint: 'https://…' } - { label: 'Site Name', name: 'label', widget: 'string' }
注意:您可以在 Netlify CMS Widgets 文档中阅读有关如何配置各个字段的更多信息,该文档介绍了每种类型的小部件以及如何使用它们 - 特别适用于日期格式。
验证
我们需要做的最后一件事是确保只有授权用户才能访问后端! 使用 Git 提供者的身份验证是解决此问题的一种简单方法。
前往您的 Netlify 站点,然后单击“设置”选项卡。 然后转到左侧菜单中的最后一个链接“访问控制”。 在这里,您可以通过提供为您的用户帐户(不在存储库中)定义的密钥和秘密值,将 OAuth 配置为通过 GitHub、GitLab 或 Bitbucket 运行。 您将需要使用与您的存储库相同的 Git 提供程序。
GitHub
转到 GitHub 上的“设置”页面(单击您的头像以显示菜单),然后访问“开发者设置”。 单击“注册新应用程序”并提供所需的值:
- 一个名称,例如“我的超级博客的 Netlify CMS”;
- 主页 URL,指向您的 Netlify 站点的链接;
- 描述,如果你喜欢的话;
- 应用回调 URL,必须是“
https://api.netlify.com/auth/done
”。
保存,您将看到您的客户端 ID 和客户端密码。 将它们提供给 Netlify 的访问控制。
GitLab
点击头像进入设置页面,点击左侧“用户设置”菜单中的“应用程序”。 您将看到一个用于添加新应用程序的表单。 提供以下信息:
- 一个名称,例如“我的超级博客的 Netlify CMS”;
- 一个重定向 URI,它必须是“
https://api.netlify.com/auth/done
”; - 应检查的范围是:
-
api
-
read_user
-
read_repository
-
write_repository
-
read_registry
-
保存您的应用程序将为您提供您的应用程序 ID 和密码,您现在可以在 Netlify 的访问控制中输入。
比特桶
转到您的用户帐户设置(单击您的头像,然后单击“Bitbucket 设置”)。 在“访问管理”下,单击“OAth”。 在“OAuth 消费者”部分中,单击“添加消费者”。 您可以将大多数内容保留为默认值,但以下内容除外:
- 一个名称,例如“我的超级博客的 Netlify CMS”;
- 回调 URL,必须是“
https://api.netlify.com/auth/done
”; - 应该检查的权限是:
- 帐户:电子邮件、阅读、写作
- 存储库:读取、写入、管理
- 拉取请求:读、写
- Webhook:读写
保存后,您可以访问您的密钥和秘密,然后您可以在 Netlify 的访问控制中提供这些信息。
提供令牌后,转到 Netlify,然后找到站点设置。 前往“身份”并启用该功能。 您现在可以添加外部提供程序:选择您的 Git 提供程序并单击“启用”。
如果您需要更多详细信息,Netlify CMS 有一个您可以阅读的身份验证指南。
您现在可以访问您的 Netlify 站点的后端并编辑内容。 每个编辑都是对你的 repo 的提交,在你的配置文件中指定的分支中。 如果您将main
分支保留为 Netlify CMS 的目标,则每次保存时,它将运行一个新构建。 更方便,但没有“中间状态”那么干净。
将它保存在dev
分支上可以让您更好地控制何时要运行新构建。 如果您的博客有很多内容并且需要更长的构建时间,这一点尤其重要。 无论哪种方式都行得通; 这只是你想如何运行你的博客的问题。
另外,请注意 Git LFS 是您在本地安装的,因此通过 Netlify CMS 上传的图像将是“正常的”。 如果您在本地拉入远程分支,则应将图像转换为 LFS,然后您可以将其提交并推送到远程分支。 此外,Netlify CMS 目前不支持 LFS,因此图像不会显示在 CMS 中,但它们会显示在您的最终构建中。
推荐阅读:静态站点生成器评论:Jekyll、Middleman、Roots、Hugo
结论
什么骑! 在本教程中,您学习了如何将 WordPress 帖子导出到 Markdown 文件、创建新存储库、设置 Git LFS、在 Netlify 上托管站点、生成 Hugo 站点、创建自己的主题以及使用 Netlify CMS 编辑内容. 还不错!
下一步是什么? 好吧,您可以尝试使用您的 Hugo 设置并阅读有关 Hugo 提供的各种工具的更多信息——为了简洁起见,我没有介绍许多工具。
探索! 玩得开心! 博客!
更多资源
- 雨果文档
- 安装
- 快速开始
- 配置
- 模板
- 分类法
- 简码
- 雨果在 Netlify
- Netlify 文档
- 自定义域
- 托管 DNS
- netlify.toml 部署脚本
- Netlify CMS 文档
- 小部件
- Git LFS