跳过主内容
Deno 2 终于来了 🎉️
了解更多
Building a static site with Lume.

如何使用 Lume 构建静态网站

  • Óscar Otero

这是一篇由 Óscar Otero(Lume 的创建者)撰写的客座博客文章。

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

但是对于不需要服务器动态响应的用例,例如博客、文档和登录页面,静态网站(一个预先构建的网站,包含要交付给浏览器的确切 HTML、CSS 和 JavaScript 文件)是一个更好且更有效率的替代方案。

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

查看源代码查看实时演示.

设置

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

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

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

  • _config.ts:用于自定义 Lume 的配置文件。
  • deno.json:带有某些用于运行 Lume 的有用任务的 Deno 配置文件。
  • import_map.json:Deno 用于解析裸规范的导入映射文件。

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

构建博客:简单方法

博客是静态网站生成器和 Lume 最常见的用例示例,当然,Lume 可以为您构建一个。如果您没有寻找过于复杂的东西,那么 “简单博客”主题 可能就足够了。您只需要在 _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;

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

---
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 文件作为布局。请注意,布局可以访问帖子的前端 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 文件没有前端 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 Actions 模式。这是因为 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 Actions 工作流程文件需要一些调整,这些调整以 #TODO 注释标记。

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

请注意,如果您想使用 Lume 的中间件(例如 expires 用于缓存或 not_found 用于显示自定义 404 页面),您需要创建一个新的 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 中打个招呼吧!