<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="/feed.xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xmlns:fh="http://purl.org/syndication/history/1.0" xml:lang="zh-Hans">
  <id>https://normco.re/zh-hans/atom.xml</id>
  <title>PhiPhi的奇妙冒险 (简体中文)</title>
  <link rel="self" type="application/atom+xml" href="https://normco.re/zh-hans/atom.xml"/>
  <link rel="alternate" type="text/html" href="https://normco.re/zh-hans/"/>
  <fh:complete/>
  <updated>2026-04-11T07:58:46.347Z</updated>
  <subtitle>Phiphi 的个人博客，写于中国成都。</subtitle>
  <author>
    <name>Phiphi</name>
  </author>
  <entry>
    <id>https://normco.re/zh-hans/posts/alibaba-cloud-oss-cdn-deployment/</id>
    <title>这个博客如何部署到阿里云 OSS 与 CDN</title>
    <link rel="alternate" type="text/html" href="https://normco.re/zh-hans/posts/alibaba-cloud-oss-cdn-deployment/"/>
    <updated>2026-03-10T00:00:00Z</updated>
    <published>2026-03-10T00:00:00Z</published>
    <summary>一份实践向说明：我的 GitHub Actions 流水线如何完成带缓存的 Lume 构建、OIDC 角色临时授权、OSS 同步、CDN 刷新，以及自动清理。</summary>
    <content type="html">&lt;p&gt;这个站点使用 Lume 构建，并部署到阿里云 OSS，再由阿里云 CDN 对外分发。整条部署
流水线刻意保持简洁：一个 GitHub Workflow、让 Deno 出现在 runner 上，再加一个
自定义 Action；它会恢复本地构建缓存、执行构建、同步 OSS 并完成清理：
&lt;a href=&quot;https://github.com/frenchvandal/aliyun-oss-cdn-sync-action&quot;&gt;&lt;code&gt;frenchvandal/aliyun-oss-cdn-sync-action&lt;/code&gt;&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;我现在希望同时满足五件事：短时凭证、在全新 runner 上也能热启动的构建、可预测
上传、与文件类型相匹配的缓存头，以及自动的缓存一致性。这套配置同时做到五者，
而且不需要在每个仓库里额外维护部署脚本。&lt;/p&gt;
&lt;h2&gt;流水线总览&lt;/h2&gt;
&lt;p&gt;从长期生产配置来看，这个仓库里的 GitHub Workflow 现在做三件事：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;检出仓库代码。&lt;/li&gt;
&lt;li&gt;按 &lt;code&gt;.tool-versions&lt;/code&gt; 安装固定版本的 Deno，并启用 runner 侧工具缓存。&lt;/li&gt;
&lt;li&gt;调用 OSS/CDN 同步 Action；它会恢复 &lt;code&gt;_cache&lt;/code&gt;、执行 &lt;code&gt;deno task build&lt;/code&gt;、上传
&lt;code&gt;_site&lt;/code&gt;、刷新 CDN，并完成清理。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;目前，这一步构建还会为共享样式和按路由拆分的关键 CSS 生成指纹，移除 source
map，并在同步 &lt;code&gt;_site&lt;/code&gt; 之前删除最终 HTML 未引用的可选 Pagefind 文件。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-yaml&quot;&gt;name: Deploy static content to OSS

on:
  push:
    branches: [&amp;quot;master&amp;quot;]
  workflow_dispatch:

permissions:
  contents: read
  id-token: write

concurrency:
  group: &amp;quot;oss-deploy&amp;quot;
  cancel-in-progress: true

jobs:
  deploy:
    environment:
      name: development
    runs-on: macos-26
    steps:
      - name: Checkout
        uses: actions/checkout@v6
        with:
          fetch-depth: 0

      - name: Setup Deno environment
        uses: denoland/setup-deno@v2
        with:
          deno-version-file: .tool-versions
          cache: true

      - name: Deploy to Alibaba Cloud OSS
        uses: frenchvandal/aliyun-oss-cdn-sync-action@master
        with:
          role-oidc-arn: ${{ secrets.ALIBABA_CLOUD_ROLE_ARN }}
          oidc-provider-arn: ${{ secrets.ALIBABA_CLOUD_OIDC_PROVIDER_ARN }}
          role-session-name: ${{ github.run_id }}
          role-session-expiration: 3600
          cache-enabled: true
          cache-key: &amp;gt;-
            lume-cache-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles(&apos;deno.lock&apos;) }}-${{ hashFiles(&apos;_cache/**/*&apos;) || &apos;empty&apos; }}
          cache-restore-keys: |
            lume-cache-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles(&apos;deno.lock&apos;) }}-
            lume-cache-${{ runner.os }}-${{ runner.arch }}-
          input-dir: _site
          bucket: ${{ secrets.OSS_BUCKET }}
          region: ${{ secrets.OSS_REGION }}
          audience: ${{ github.repository_id }}
          cdn-enabled: true
          cdn-base-url: ${{ secrets.OSS_CDN_BASE_URL }}
          cdn-actions: refresh
          build-command: deno task build
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在这个仓库里，我现在只保留 &lt;code&gt;cdn-actions: refresh&lt;/code&gt;。Action 仍支持
&lt;code&gt;refresh,preload&lt;/code&gt;，只是这个站点当前不再为每次部署开启 preload。&lt;/p&gt;
&lt;h2&gt;为什么选 OIDC，而不是长期 Access Key&lt;/h2&gt;
&lt;p&gt;这个 Action 在运行时通过 GitHub OIDC 去扮演阿里云 RAM 角色。仓库中不保存长期
Access Key。Workflow 只需要 &lt;code&gt;id-token: write&lt;/code&gt;，再加上 RAM 角色和 OIDC Provider
的 ARN。&lt;/p&gt;
&lt;p&gt;现在认证路径也只走 OIDC。如果角色扮演失败，Action 不会再从输入或环境变量回退到
静态 Access Key。&lt;/p&gt;
&lt;p&gt;当前配置还传入了 &lt;code&gt;audience: ${{ github.repository_id }}&lt;/code&gt;。GitHub 可以为自定义
audience 签发 ID token，而阿里云 RAM 可以把这个 &lt;code&gt;aud&lt;/code&gt; 值与 OIDC 身份提供商里配置
的 Client ID，以及角色信任策略中的条件进行校验。这样比单纯依赖默认 audience
更收敛。&lt;/p&gt;
&lt;h2&gt;Action 内部是怎么执行的&lt;/h2&gt;
&lt;p&gt;这个 Action 被拆成三个阶段：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;pre&lt;/strong&gt;：通过 OIDC 扮演 RAM 角色，并把临时凭证写入 action state。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;main&lt;/strong&gt;：按需恢复本地 &lt;code&gt;_cache&lt;/code&gt; 目录，执行 &lt;code&gt;build-command&lt;/code&gt;，上传本地文件到
OSS，写入缓存头，并在启用时执行 CDN 动作。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;post&lt;/strong&gt;：比较目标前缀下的远端对象与本地文件，删除远端孤儿对象，在需要时刷新被
删除 URL 的 CDN 缓存，写入 CDN 任务摘要，并在配置了 &lt;code&gt;cache-key&lt;/code&gt; 时保存
&lt;code&gt;_cache&lt;/code&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;清理阶段通过 &lt;code&gt;post-if: always()&lt;/code&gt; 执行，所以即使前面步骤失败也会运行。清理和 CDN
调用，以及缓存恢复或保存，都被设计为&amp;quot;非致命&amp;quot;：会记录警告，但不会因为 CDN API
或缓存服务的短暂抖动而阻塞部署。&lt;/p&gt;
&lt;h2&gt;上传、缓存、配额与漂移控制&lt;/h2&gt;
&lt;p&gt;下面这些实现细节对可靠性非常关键：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;build-command&lt;/code&gt; 在 Action 内部执行，而且发生在 OSS 上传或 CDN 调用之前。&lt;/li&gt;
&lt;li&gt;如果 &lt;code&gt;cache-enabled&lt;/code&gt; 为 &lt;code&gt;true&lt;/code&gt; 且配置了 &lt;code&gt;cache-key&lt;/code&gt;，那么会先恢复 &lt;code&gt;_cache&lt;/code&gt;，
build 结束后还可以在 &lt;code&gt;post&lt;/code&gt; 阶段保存一份新的快照。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cache-enabled&lt;/code&gt; 只控制恢复路径，所以我可以临时关闭 warm cache，同时保留
post-step 的缓存保存。&lt;/li&gt;
&lt;li&gt;上传通过 &lt;code&gt;max-concurrency&lt;/code&gt; 并行化。&lt;/li&gt;
&lt;li&gt;全局 API 限速通过 &lt;code&gt;api-rps-limit&lt;/code&gt; 控制。&lt;/li&gt;
&lt;li&gt;每个文件上传失败后最多重试三次。&lt;/li&gt;
&lt;li&gt;部分上传失败会通过 &lt;code&gt;failed-count&lt;/code&gt; 和 GitHub Actions job summary 暴露出来，
而不是埋在日志里。&lt;/li&gt;
&lt;li&gt;上传阶段现在会自动写入 &lt;code&gt;Cache-Control&lt;/code&gt;：HTML 与 &lt;code&gt;sw.js&lt;/code&gt; 会被更积极地重新验证，
带哈希的资源按 immutable 处理，常见静态资源也会拿到更短的重新验证窗口，而不是
一刀切的统一策略。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;cdn-actions&lt;/code&gt; 只接受 &lt;code&gt;refresh&lt;/code&gt; 或 &lt;code&gt;refresh,preload&lt;/code&gt;；如果 CDN
已启用而这个值为空或无效，Action 会回退到 &lt;code&gt;refresh&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;Action 会在提交 refresh 或 preload 批次前检查剩余 CDN 配额。&lt;/li&gt;
&lt;li&gt;删除 OSS 对象时可触发对应 URL 的 CDN 刷新，减少旧缓存窗口，也能抑制对象随时间
漂移。&lt;/li&gt;
&lt;li&gt;Action 还会为部署、清理和 CDN 任务状态写入 GitHub Actions job summary。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;最后一点很容易被低估：长期运行的静态站点仅有上传远远不够。你还需要删除机制，以及
对不该再存在对象的缓存失效处理。&lt;/p&gt;
&lt;h2&gt;最小化 RAM 权限&lt;/h2&gt;
&lt;p&gt;权限上，这个角色需要目标 bucket 范围内的 OSS 权限，用于列举、上传和删除对象。
CDN 一侧，这个 workflow 需要 refresh 权限，以及用于查询配额和任务状态的只读 API
权限。如果启用 preload，再补上对应权限即可。此外，Trust Policy 必须允许 GitHub
OIDC Provider 扮演部署角色。&lt;/p&gt;
&lt;p&gt;我把它单独作为&amp;quot;部署角色&amp;quot;维护，不与更宽泛的运营权限混用。&lt;/p&gt;
&lt;h2&gt;在其他仓库复用这个 Action&lt;/h2&gt;
&lt;p&gt;这个 Action 已发布，可直接复用：
&lt;a href=&quot;https://github.com/frenchvandal/aliyun-oss-cdn-sync-action&quot;&gt;github.com/frenchvandal/aliyun-oss-cdn-sync-action&lt;/a&gt;。&lt;/p&gt;
&lt;p&gt;这个仓库目前跟踪 &lt;code&gt;@master&lt;/code&gt;，因为站点和 Action 是一起维护、一起验证的。放到独立
仓库里时，我通常会固定到 &lt;code&gt;@v1&lt;/code&gt;，或者更进一步固定到完整的 commit SHA。我现在也把
build 和 &lt;code&gt;_cache&lt;/code&gt; 生命周期交给 Action 自己管理，这让消费端 workflow 更短，也更偏
声明式。&lt;/p&gt;
&lt;p&gt;对我来说，最关键的结果还是一样：部署保持&amp;quot;无聊&amp;quot;。恢复缓存、build、sync、
refresh、cleanup，结束。&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>https://normco.re/zh-hans/posts/lorem-ipsum/</id>
    <title>Lorem Ipsum 与占位文本的艺术</title>
    <link rel="alternate" type="text/html" href="https://normco.re/zh-hans/posts/lorem-ipsum/"/>
    <updated>2026-02-18T00:00:00Z</updated>
    <published>2026-02-18T00:00:00Z</published>
    <summary>关于占位文本的历史、价值，以及它为何仍在现代设计流程中有效。</summary>
    <content type="html">&lt;p&gt;Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis
nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.&lt;/p&gt;
&lt;p&gt;很多人都听过这段文字，却很少知道它的来源。它其实来自西塞罗 &lt;em&gt;de Finibus Bonorum
et Malorum&lt;/em&gt; 的一段打乱文本，这部哲学著作写于公元前 45 年。自 16
世纪起，它就被作为排版占位文本使用：一位不知名的印刷工把活字顺序打乱，
做出了一本字体样张。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://normco.re/posts/lorem-ipsum/images/amol-srivastava-uOYc6OlgpUI-unsplash.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2&gt;为什么占位文本仍然重要&lt;/h2&gt;
&lt;p&gt;Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu
fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
culpa qui officia deserunt mollit anim id est laborum.&lt;/p&gt;
&lt;p&gt;当你用真实文案设计版面时，你其实是在为那一批具体句子做设计。
占位文本迫使你先为结构而不是语义做决定。这是一种很有价值的约束：
它能暴露设计是否能承受不确定性，比如三行标题、没有自然换气点的段落，
或者一个超出容器长度的长单词。&lt;/p&gt;
&lt;h2&gt;关于&amp;quot;逼真度&amp;quot;的问题&lt;/h2&gt;
&lt;p&gt;Ut enim ad minima veniam, quis nostrum exercitationem ullam corporis suscipit
laboriosam? 在设计中，真实内容的还原度与抽象带来的自由之间，总是存在张力。&lt;/p&gt;
&lt;p&gt;高保真原型需要先有真实内容。低保真线框图则在不被语义分散注意力的前提下传达结构。
两种方法都合理，关键是判断当下该用哪一种工具。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;// A small utility to generate repeating text blocks.
function lorem(words: number): string {
  const base = &amp;quot;lorem ipsum dolor sit amet consectetur adipiscing elit&amp;quot;;
  const tokens = base.split(&amp;quot; &amp;quot;);
  const result: string[] = [];
  for (let i = 0; i &amp;lt; words; i++) {
    result.push(tokens[i % tokens.length] ?? &amp;quot;&amp;quot;);
  }
  return result.join(&amp;quot; &amp;quot;);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed
quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://normco.re/posts/lorem-ipsum/images/scott-rodgerson-z0MDyylvY1k-unsplash.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2&gt;结语&lt;/h2&gt;
&lt;p&gt;Lorem ipsum 不只是填充物。它像一面镜子，照出设计在剥离语义后留下的纯结构：
有形式、无内容。也正因为如此，它才能跨越这么多时代继续存在。&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>https://normco.re/zh-hans/posts/vestibulum-ante/</id>
    <title>Vestibulum Ante：关于门槛与新的开始</title>
    <link rel="alternate" type="text/html" href="https://normco.re/zh-hans/posts/vestibulum-ante/"/>
    <updated>2025-09-04T00:00:00Z</updated>
    <published>2025-09-04T00:00:00Z</published>
    <summary>关于过渡、人生中的中间地带，以及站在门槛上的意义。</summary>
    <content type="html">&lt;p&gt;Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia
curae. 拉丁词 &lt;em&gt;vestibulum&lt;/em&gt; 指前庭、入口、门前空间，
它的语义重量远比现代&amp;quot;门厅&amp;quot;这个词听上去更深。&lt;/p&gt;
&lt;p&gt;门槛既不是结束，也不是开始。它是两者之间的临界地带：开口前屏住的一口气，
钥匙拧动后那一瞬停顿。它是&amp;quot;旧的已结束，而新的尚未开始&amp;quot;的位置。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://normco.re/posts/vestibulum-ante/images/bruno-martins-4cwf-iW6I1Q-unsplash.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2&gt;中间地带的价值&lt;/h2&gt;
&lt;p&gt;Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac
turpis egestas. 我们生活在一个低估&amp;quot;过渡期&amp;quot;的文化里。
我们追求结果、产出和成品。那些混乱的中段、反复草稿、犹疑时刻和缓慢积累的理解，
往往既不被记录，也不被庆祝。&lt;/p&gt;
&lt;p&gt;但人生大部分时间都发生在中间地带。通勤路上，候诊室里，
发送一条消息到收到回复之间，
以及&amp;quot;知道自己想要什么&amp;quot;到&amp;quot;知道如何得到它&amp;quot;之间的那些年。&lt;/p&gt;
&lt;h2&gt;站在门口&lt;/h2&gt;
&lt;p&gt;Fusce suscipit varius mi. Cum sociis natoque penatibus et magnis dis parturient
montes, nascetur ridiculus mus. Phasellus viverra nulla ut metus varius laoreet.&lt;/p&gt;
&lt;p&gt;我在初秋的一个星期二搬到成都。这座城市的&amp;quot;温暖&amp;quot;让我意外，
不是夏天的热，而是一种&amp;quot;它已经决定要喜欢你&amp;quot;的温度。
街道闻起来是辣椒油和桂花的味道，一切都同时有一点陌生，也有一点亲切。&lt;/p&gt;
&lt;p&gt;我想，这就是门槛的感觉。它既不敌对，也不主动欢迎。
它只是敞开着，等你决定要把它变成什么。&lt;/p&gt;
&lt;h2&gt;尾声&lt;/h2&gt;
&lt;p&gt;Quisque sit amet est et sapien ullamcorper pharetra. Vestibulum erat wisi,
condimentum sed, commodo vitae, ornare sit amet, wisi. Aenean fermentum, elit
eget tincidunt condimentum, eros ipsum rutrum orci, sagittis tempus lacus enim
ac dui.&lt;/p&gt;
&lt;p&gt;每篇文本都有自己的&amp;quot;前厅&amp;quot;：标题页、引言、第一段。
这个空间负责让读者为接下来的内容做好准备。它值得被认真写好。&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>https://normco.re/zh-hans/posts/proin-facilisis/</id>
    <title>Proin Facilisis：让事情更轻松</title>
    <link rel="alternate" type="text/html" href="https://normco.re/zh-hans/posts/proin-facilisis/"/>
    <updated>2025-04-12T00:00:00Z</updated>
    <published>2025-04-12T00:00:00Z</published>
    <summary>关于降低摩擦的哲学：在代码、设计和日常生活中。</summary>
    <content type="html">&lt;p&gt;&lt;em&gt;Proin facilisis&lt;/em&gt; 在拉丁语里可以理解为&amp;quot;促进顺畅&amp;quot;。它曾出现在古老植物学文本中，
形容一种能帮助消化、疏通阻滞的植物。作为软件设计哲学，这个词意外地贴切。&lt;/p&gt;
&lt;p&gt;好的软件会降低摩擦。它会提前预判用户的下一步，在恰当时机给出恰当的可供性，
然后退到背景里。&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://normco.re/posts/proin-facilisis/images/brett-jordan-92-mTYj5oGs-unsplash.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;h2&gt;先做&amp;quot;摩擦清单&amp;quot;&lt;/h2&gt;
&lt;p&gt;Proin in tellus sit amet nibh dignissim sagittis. 减少摩擦的第一步是把它画出来：
用户在哪些环节会放慢？注意力在哪些节点会飙升？错误会集中出现在哪里？&lt;/p&gt;
&lt;p&gt;在典型 Web
应用里，高摩擦时刻通常很稳定：注册引导、表单提交、错误恢复、加载状态。
这些就是产品的&amp;quot;门厅&amp;quot;，是用户为了抵达价值必须跨过的门槛。&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;// Friction shows up in code too.
// Compare these two approaches to handling a missing value:

// High friction — the caller must always check:
function getUser(id: string): User | undefined {/* … */}

// Lower friction — the error is explicit and handled at the boundary:
function getUser(id: string): User {
  const user = db.find(id);
  if (user === undefined) {
    throw new Error(`User not found: ${id}`);
  }
  return user;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;&amp;quot;简单&amp;quot;本身的悖论&lt;/h2&gt;
&lt;p&gt;Vivamus pretium aliquet erat. &amp;quot;让事情变简单&amp;quot;最困难的地方在于：它真的很难。
你需要深入理解用户、场景和失败模式。也就是说，构建者要多做工作，用户才能少费力。&lt;/p&gt;
&lt;p&gt;这也是为什么&amp;quot;简单&amp;quot;是一种慷慨。每移除一个不必要步骤，都是把时间还给用户，
让他们去做真正重要的事。&lt;/p&gt;
&lt;h2&gt;如何把 facilisis 落地&lt;/h2&gt;
&lt;p&gt;Donec aliquet metus ut erat semper, et tincidunt nulla luctus.
我经常回到这些原则：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;默认值应覆盖多数人多数场景。&lt;/li&gt;
&lt;li&gt;错误信息应说明问题，也说明修复路径。&lt;/li&gt;
&lt;li&gt;主流程不应要求额外思考。&lt;/li&gt;
&lt;li&gt;配置应当可选，而不是前置门槛。&lt;/li&gt;
&lt;li&gt;文档是产品的一部分，而不是附录。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Nulla facilisi. Phasellus blandit leo ut odio. Nam sed nulla non diam tincidunt
tempus. 这个原则的名字本身也提醒我们：&lt;em&gt;nulla
facilisi&lt;/em&gt;，没有真正&amp;quot;天然简单&amp;quot;的事。好的简单，从来都不是偶然。&lt;/p&gt;
</content>
  </entry>
  <entry>
    <id>https://normco.re/zh-hans/posts/instructions/</id>
    <title>如何安装这个主题？</title>
    <link rel="alternate" type="text/html" href="https://normco.re/zh-hans/posts/instructions/"/>
    <updated>2022-06-12T00:00:00Z</updated>
    <published>2022-06-12T00:00:00Z</published>
    <summary>一份快速指南，帮助你为 Lume 配置 Simple Blog 主题。</summary>
    <content type="html">&lt;p&gt;&lt;strong&gt;Simple blog&lt;/strong&gt; 是一个为 Lume 准备的简洁极简博客主题，支持标签和作者。
你可以&lt;strong&gt;在几秒内&lt;/strong&gt;搭建自己的博客，并为读者提供 Atom 与 JSON 订阅源。&lt;/p&gt;
&lt;p&gt;配置这个主题&lt;strong&gt;最快最简单&lt;/strong&gt;的方法是使用
&lt;a href=&quot;https://deno.land/x/lume_init&quot;&gt;Lume init 命令&lt;/a&gt;，你也可以直接从
&lt;a href=&quot;https://lume.land/theme/simple-blog/&quot;&gt;Simple Blog 主题页面&lt;/a&gt;复制。运行：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;deno run -A https://lume.land/init.ts --theme=simple-blog
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;即可创建一个已经配置好 Simple Blog 的新项目。然后编辑博客根目录下的 &lt;code&gt;_data.yml&lt;/code&gt;
文件，自定义站点标题、描述和元数据。&lt;/p&gt;
&lt;p&gt;文章需要保存在 &lt;code&gt;posts&lt;/code&gt; 目录中，例如：&lt;code&gt;posts/my-first-post.md&lt;/code&gt;。&lt;/p&gt;
&lt;h2&gt;作为远程主题安装&lt;/h2&gt;
&lt;p&gt;如果要把这个主题接入一个已有的 Lume 项目，可以在 &lt;code&gt;_config.ts&lt;/code&gt;
中以远程模块方式导入。后续更新时，只需调整导入 URL 里的版本号：&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;import lume from &amp;quot;lume/mod.ts&amp;quot;;
import blog from &amp;quot;https://deno.land/x/lume_theme_simple_blog@v0.15.6/mod.ts&amp;quot;;

const site = lume();

site.use(blog());

export default site;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后把
&lt;a href=&quot;https://github.com/lumeland/theme-simple-blog/blob/main/src/_data.yml&quot;&gt;&lt;code&gt;_data.yml&lt;/code&gt;&lt;/a&gt;
复制到博客根目录，并填入你的信息。&lt;/p&gt;
&lt;h2&gt;个性化&lt;/h2&gt;
&lt;p&gt;你也可以使用 &lt;a href=&quot;https://lume.land/cms&quot;&gt;lumeCMS&lt;/a&gt; 来定制博客并更轻松地发布内容。&lt;/p&gt;
</content>
  </entry>
</feed>
