# 用 Lume 构建静态站

Lume 是 Deno-first 的静态站生成器，适合文档、博客与内容站：构建产物是纯静态文件，可托管在任意静态服务器上。本站就是用 Lume 3 构建的，下面的示例直接取自本仓库的真实 `_config.ts` 与 `deno.json`。

## 创建项目

```bash
deno run -A https://lume.land/init.ts
cd my-site
deno task lume -s   # dev server，带监听与热重载
deno task lume      # 构建到 _site/
```

官方推荐项目级安装而非全局 CLI：init 脚本会生成一个 `deno.json`，其中包含 `lume` task 和同名的具名权限配置。升级用 `deno task lume upgrade`。如果教程里出现 `deno.land/x/lume/init.ts` 或要求全局 `deno install` lume 命令，说明写作时间较早——当前域名是 `lume.land`。

## 核心概念

配置集中在 `_config.ts`：创建站点、注册插件、声明共享数据。

```ts title="_config.ts（本站实际配置的节选）"
import lume from "lume/mod.ts";
import jsx from "lume/plugins/jsx.ts";
import mdx from "lume/plugins/mdx.ts";
import sitemap from "lume/plugins/sitemap.ts";

const site = lume({ location: new URL("https://example.com") });

site.use(jsx());
site.use(mdx());
site.use(sitemap({ query: "indexable=true", items: { lastmod: "=lastModified" } }));

site.copy("static", ".");
site.data("layout", "doc.tsx");

export default site;
```

- **插件**：Markdown、Vento、搜索、分页等开箱即用；JSX、MDX、sitemap、feed 等按需 `site.use()` 注册。
- **`_includes/`**：布局与模板片段目录，页面用 frontmatter 的 `layout` 指定，也可用 `site.data("layout", ...)` 设全站默认。
- **`_components/`**：可复用组件，所有模板里通过全局 `comp` 变量访问，跨引擎可用（JSX 写的组件可以在 Vento 里用）。本页底部的 Callout 就是 `_components/` 里的组件。
- **`preprocess` vs `process`**：`site.preprocess([".mdx"], ...)` 在渲染前运行，适合注入数据——本站用它给每个页面写入 `locale` 和 `lastModified`；`site.process([".html"], ...)` 在渲染后拿到 `page.document` 做 DOM 操作——本站用它给表格包滚动容器、给外链加 `rel="noreferrer"`。

## 权限收窄

Lume 需要读源文件、写 `_site/`、联网拉取依赖，很多教程图省事直接 `-A`。Deno 2 的具名权限配置可以把权限收窄并固定下来，本站的 `deno.json` 就是一个完整示例：

```json title="deno.json（节选）"
{
  "tasks": {
    "lume": "deno run -P=lume lume/cli.ts"
  },
  "permissions": {
    "lume": {
      "read": true,
      "write": true,
      "import": ["cdn.jsdelivr.net:443", "jsr.io:443", "deno.land:443"],
      "net": ["cdn.jsdelivr.net:443", "jsr.io:443", "deno.land:443", "esm.sh:443"],
      "env": true,
      "run": true,
      "ffi": true,
      "sys": true
    }
  }
}
```

`deno run -P=lume` 表示只应用名为 `lume` 的这份配置，除此之外无权限。进一步收紧的方向：把 `net`/`import` 限定为你的依赖实际所在的主机（如上），把 `write` 从 `true` 收窄为 `["_site"]`，把 `env` 收窄为构建真正读取的变量名（如 `["SITE_URL"]`）。改完跑一遍 `deno task lume`，缺哪个权限 Deno 会明确报出来。

## 构建与部署

`deno task lume` 输出到 `_site/`，是纯静态产物：Nginx、对象存储、Cloudflare Pages、GitHub Pages 都能直接托管。新版 Deno Deploy 对静态站有一等支持，并能自动识别 Lume 项目、无需额外配置；注意 Deploy Classic 不支持静态托管，老文档里的“用 `Deno.serve` 起一个文件服务器”方案只适用于 Classic。

## Lume 还是 Fresh

与[决策表](/docs/web)一致：页面在构建期就能全部确定（文档、博客、营销页）选 Lume；需要请求期渲染、数据库读写或交互 island 选 Fresh。两者的客户端 JavaScript 都可以接近零，区别在于 HTML 何时生成。

<Callout type="info" title="适用边界">
Lume 组件只在构建期运行，不向浏览器发送运行时代码。交互需求（表单状态、客户端路由）一旦成为主体，就应评估 Fresh 而不是在静态页里堆 `<script>`。
</Callout>

官方参考：[Lume 安装](https://lume.land/docs/overview/installation/)、[Processors](https://lume.land/docs/core/processors/)、[Components](https://lume.land/docs/core/components/)、[插件列表](https://lume.land/plugins/?status=all)、[Deno Deploy 框架支持](https://docs.deno.com/deploy/reference/frameworks/)。
