跳至主要内容
Building a static site with Lume.

如何使用 Lume 构建静态站点

  • Óscar Otero

这是一篇客座博客,由 Lume 的创建者 Óscar Otero 撰写。

Deno 是创建动态 Web 应用程序和 API 的绝佳选择,尤其是与 Deno Deploy 结合使用以在边缘生成响应时。

但是对于不需要服务器动态响应的用例,例如博客、文档和落地页,静态站点(预构建的站点,包含要交付给浏览器的确切 HTML、CSS 和 JavaScript 文件)是更好且性能更高的替代方案。

在本教程中,我们将学习如何使用 Lume(发音为 /lume/)创建一个静态站点,Lume 是一个快速、极其灵活、可组合和可扩展的静态站点生成器,用 Deno 编写。

查看源代码在线演示.

设置

设置 Lume 项目的推荐方法是运行命令

deno run -Ar --unstable https://deno.land/x/lume/init.ts

在回答几个问题后,您将在工作目录中看到 3 个新文件

  • _config.ts:用于自定义 Lume 的配置文件。
  • deno.json:Deno 配置文件,包含一些用于运行 Lume 的实用任务。
  • import_map.json:Deno 使用的导入映射文件,用于解析裸标识符。

此外,强烈建议如果您使用 VSCode,则使用 Deno 扩展。(了解有关使用 VSCode 配置 Deno 的信息。

构建博客:简单方法

博客是静态站点生成器最常见的用例示例,Lume 当然可以为您构建一个。如果您不追求过于复杂的东西,那么 “Simple blog” 主题就足够了。您只需将其导入 _config.ts 文件并使用它。

import lume from "lume";
import blog from "https://deno.land/x/[email protected]/mod.ts";

const site = lume().use(blog());

export default site;

然后使用 markdown + front matter 格式将您的帖子保存在 /posts/ 文件夹中。例如

---
title: Static sites with Lume + Deno Deploy
date: 2022-11-05
author: Óscar Otero
tags:
  - Deno
  - Static site generators
---

Deno is always a great choice to create dynamic web applications and APIs,
especially when it's combined with Deno Deploy to generate responses at the
edge. ...

运行 deno task serve,您将在 localhost:3000 上看到您的新博客!

但是我想自己制作一些东西

好的,明白了!与其使用现有主题,不如从头开始构建一些东西。

开始入门

Lume 不要求任何文件结构即可工作,但对于本演示,我们将所有帖子文件保存在名为 /posts 的目录中。因此,我们有以下结构

|_ posts/
|  |_ my-first-post.md
|  |_ my-second-post.md
|_ config.ts
|_ deno.json
|_ import_map.json

运行 deno task serve 以在 localhost:3000 上查看站点。您将看到 404 错误页面,因为索引文件尚不存在。

Getting a 404 page not found

但是您可以看到帖子。默认情况下,帖子的 URL 根据源路径计算。例如,文件 /posts/my-first-post.md 输出 URL https://127.0.0.1:3000/posts/my-first-post/

My first post

布局

如您所见,该页面仅显示渲染为 HTML 的 markdown 内容。让我们创建一个布局,将此内容包装到适当的 HTML 结构中。默认情况下,布局存储在特殊的 _includes 文件夹中,因此我们需要创建此文件夹,并在其中创建文件 post.njk,内容如下

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{{ title }}</title>
</head>
<body>
  <main>
    <article>
      <header>
        <h1>{{ title }}</h1>
        <p>By {{ author }}</p>
      </header>

      {{ content | safe }}
    </article>
  </main>
</body>
</html>

.njk 扩展名用于 Nunjucks,这是一种由 Mozilla 创建的流行模板语言,Lume 默认支持它。当然,您可以使用其他格式,例如 JavaScript、TypeScript 甚至 JSX、Pug、Eta 等(使用插件),但现在让我们保持简单。

我们将在 posts 文件夹中创建一个 _data.yml 文件,内容如下

layout: post.njk
type: post

此文件将这两个变量分配给此目录中的所有帖子。

现在让我们忽略 type 变量。

layout 变量是一个特殊值,包含用于渲染页面的布局的文件名。这意味着此目录中的所有页面都将使用 _includes/post.njk 文件作为布局。请注意,布局可以访问帖子 front matter 的值,例如 titleauthor

我们的帖子现在看起来好一点了!

First post but with some style

列出所有帖子

假设我们想在主页中显示所有帖子的列表。对于此示例,我将在 TypeScript 中创建主页,因此我们需要在根目录中创建 index.tmpl.ts 文件,代码如下

import type { PageData } from "lume/core.ts";

export default function ({ search }: PageData) {
  const posts = search.pages("type=post");

  return `
    <h2>Posts</h2>
    <ul>
      ${
    posts.map((post) =>
      `<li><a href="${post.data.url}">${post.data.title}</a></li>`
    ).join("")
  }
    </ul>
  `;
}

在 Lume 中使用 TypeScript 构建页面很容易,我们只需要 export default 一个函数,该函数将页面内容作为 string 返回。

此函数接收页面上下文数据作为第一个参数,包括一些有趣的助手函数,例如 search,我们可以使用它来查询并返回所有带有 type=post 变量的页面。(还记得我们之前在 posts/_data.yml 文件中插入的 type 值吗?它只是一个标志,用于在此处轻松选择这些页面。)

我们的主页看起来像这样

The index page

我可以在页面中包含完整的 HTML 代码,但我喜欢布局,因此我创建了以下 _includes/homepage.njk 布局文件

---
title: The Óscar's blog
---

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>{{ title }}</title>
</head>
<body>
  <main>
    <header>
      <h1>{{ title }}</h1>
    </header>

    {{ content | safe }}
  </main>
</body>
</html>

现在我们必须配置 index.tmpl.ts 文件以使用此布局。TypeScript 文件没有 front matter 来存储数据,它们只是将值作为命名导出公开

import type { PageData } from "lume/core.ts";

export const layout = "homepage.njk";

export default function ({ search }: PageData) {
  const posts = search.pages("type=post");

  return `
    <h2>Posts</h2>
    <ul>
      ${
    posts.map((post) =>
      `<li><a href="${post.data.url}">${post.data.title}</a></li>`
    ).join("")
  }
    </ul>
  `;
}

主页现在看起来好一点了

Styling the home page

添加样式

Lume 有许多插件可用于 JavaScript,以支持 JSX、MDX 等格式。出于样式目的,有一些可用的插件可用于 SASS、PostCSS、WindiCSS 或 LighningCSS。

为简单起见,在本演示中,我们将使用出色的 missing.css(顺便说一句,文档站点也是用 Lume 构建的)。此 css 文件提供了一些不错的开箱即用样式,无需修改我们的 HTML。为此,只需在我们刚刚创建的两个布局中包含 <link rel="stylesheet" href="https://the.missing.style/"> 行。

The home page but much better styled

准备部署

静态站点的众多优点之一是托管。您可以将您的站点托管在任何地方,几乎没有服务器要求。

在本演示中,我们将使用 Deno Deploy 来提供站点服务。由于其设计,所有传入的请求都由 JavaScript 文件处理,因此我们可以自定义站点的文件交付方式。

步骤 1:在 Deno Deploy 中创建一个项目

转到 Deno Deploy 并创建一个新项目。您将看到如下屏幕

Create a new project in Deno Deploy

选择分支时,重要的一点是使用 GitHub Action 模式。这是因为 Deno Deploy 没有 CI 来构建站点,因此我们需要使用 GitHub Actions 工作流程来构建静态站点并将其上传到 Deno Deploy。

然后单击链接按钮,您将看到以下屏幕

Get the GitHub Action for Deno Deploy

Deno Deploy 已生成配置 GitHub Actions 工作流程所需的代码。复制此代码并将其保存到 .github/workflows/deploy.yml 中。

步骤 2:配置 GitHub Actions

我们刚刚创建的 GitHub Action 工作流程文件需要进行一些调整,标记为 #TODO 注释

  • 设置构建步骤。在我们的例子中,我们需要设置 Deno 并运行 deno task build
  • 更新入口点以使用 deno_stdfile_server.ts,并将 root 设置为 ./_site

请注意,如果您想使用 Lume 的中间件,例如用于缓存的 expires 或用于显示自定义 404 页面的 not_found,则需要创建一个新的 serve.ts,添加您的中间件,并将其设置为 Deno Deploy 的 entrypoint

经过这些修改后,这是最终版本

name: Deploy
on: [push]

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    permissions:
      id-token: write # Needed for auth with Deno Deploy
      contents: read # Needed to clone the repository

    steps:
      - name: Clone repository
        uses: actions/checkout@v3

      - name: Setup Deno environment
        uses: denoland/setup-deno@v1
        with:
          deno-version: v1.x

      - name: Build site
        run: deno task build

      - name: Upload to Deno Deploy
        uses: denoland/deployctl@v1
        with:
          project: oscarotero-lume-blog-demo
          entrypoint: https://deno.land/[email protected]/http/file_server.ts
          root: ./_site

将更改推送到 GitHub,您的站点将在几秒钟内构建并上传到 Deno Deploy。

Successful deployment on Deno Deploy

单击查看蓝色按钮以在 *.deno.dev 上查看您的新博客(如果您添加了自定义域名,则可以使用其他域名)。

Oscars blog served from Deno Deploy

就这样。这很容易,不是吗?查看 Lume 文档站点,以了解有关此静态站点生成器的更多信息,并在展示区中查看真实示例。

遇到困难?来 Deno 的 Discord 打个招呼!