<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh_CN">
  <title>叁月的博客</title>
  <subtitle>把日常写成可以翻阅的样子</subtitle>
  <link href="https://sanyue0608.site/" rel="alternate" type="text/html"/>
  <link href="https://sanyue0608.site/atom.xml" rel="self" type="application/atom+xml"/>
  <id>https://sanyue0608.site/</id>
  <updated>2026-11-12T09:30:00.000Z</updated>
  <entry>
    <title>建站踩坑记：从本地跑通到 GitHub Pages 上线</title>
    <link href="https://sanyue0608.site/posts/deploy-to-github-pages/" rel="alternate" type="text/html"/>
    <id>https://sanyue0608.site/posts/deploy-to-github-pages/</id>
    <published>2026-11-12T09:30:00.000Z</published>
    <updated>2026-11-12T09:30:00.000Z</updated>
    <summary>一个不懂前端的人把 Astro 博客从零搭到上线，中间踩过的五个坑，以及最后为什么放弃了 EdgeOne 改用 GitHub Pages。</summary>
    <content type="html"><![CDATA[<p>这个博客从「想搞一个」到真正能打开，花了两天。技术上的难点其实不多，难的是<strong>每一步都有一个看起来像玄学的报错</strong>。</p>
<p>把过程记下来，一是给以后的我省事，二是如果你也想搭一个，能少走我走过的弯路。</p>
<h2>一、选型：为什么是 Astro</h2>
<p>一开始的需求很朴素：能写文章、打开快、别让我维护服务器。</p>
<p>筛到最后剩下两个方向：WordPress 那种「动态站点」，和 Astro 这种「静态站点」。</p>
<p>最后选静态，理由很实际：</p>
<ul>
<li>文章是 Markdown 文件，存在自己电脑上，不锁在某个平台的数据库里</li>
<li>没有数据库，就没有「数据库挂了」「被拖库了」这些事</li>
<li>构建出来的是一堆 <code>.html</code>，扔到任何静态托管上都能跑，随时可以搬家</li>
</ul>
<p>主题选了开源的 <strong>Shirone</strong>——Material 3 风格、中文支持好、配置项都有中文注释。对新手来说，注释比文档管用。</p>
<h2>二、五个坑</h2>
<h3>坑 1：主题说要 Node 26，但 EdgeOne 最高只给 22</h3>
<p>主题的 <code>package.json</code> 写着 <code>engines.node: "&gt;=26.13.0"</code>。我老老实实装了 Node 26，本地跑得很好。</p>
<p>结果一上 EdgeOne 就炸：</p>
<pre><code>Node.js v22.x is not supported by Astro!
Please upgrade Node.js to a supported version: "&gt;=22.23.4"
</code></pre>
<p>这里有个反直觉的地方：<strong>主题声明的要求，往往比它依赖的框架严格得多</strong>。我把依赖一个个翻出来看：</p>
<table>
<thead>
<tr>
<th>包</th>
<th>实际要求</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>astro@7.4.5</code></td>
<td><code>&gt;=22.23.4</code></td>
</tr>
<tr>
<td><code>vite@8</code></td>
<td><code>&gt;=22.12</code></td>
</tr>
<tr>
<td><code>svelte@5</code></td>
<td><code>&gt;=18</code></td>
</tr>
</tbody>
</table>
<p><strong>没有任何一个依赖真的需要 26。</strong> 于是把 <code>engines.node</code> 改成 <code>&gt;=24.0.0</code>，本地和线上统一到 Node 24，装依赖、构建、开发服务器全部复测通过。</p>
<blockquote>
<p>教训：看到 <code>engines</code> 报错，先去看依赖的真实要求，别直接信主题写的数字。</p>
</blockquote>
<p>而且 EdgeOne 预装的最高版本是 <strong>22.11.0</strong>，比 Astro 要的 <code>22.23.4</code> 还差一点点——就差这一点点，整个构建起不来。这种"差 0.12 个版本"的坑最恶心，因为报错信息看起来像是网络问题或者配置问题。</p>
<h3>坑 2：字体是构建时从 CDN 下载的（最坑的一个）</h3>
<p>本地构建偶尔失败：</p>
<pre><code>[CannotFetchFontFile] An error occurred while fetching the font file from
https://cdn.jsdelivr.net/fontsource/fonts/jetbrains-mono@5.3.0/...
</code></pre>
<p>重跑一次又好了。我一开始以为是网络抖动。</p>
<p>后来清空构建缓存再跑，<strong>必现失败</strong>。才意识到：前面那些"成功"都是在吃缓存，真实的构建流程一直在依赖外网。</p>
<p>原因：主题的字体配置用的是 <code>source: "fontsource"</code>，Astro 在构建时要<strong>实时从 jsDelivr 下载字体文件</strong>来计算排版度量（行高、基线这些）。</p>
<p>这意味着：<strong>任何一台全新克隆、没有缓存的构建机（CI、云平台）第一次构建都会挂在这里</strong>，而且报错信息完全指向错误的方向。</p>
<p>修法很干脆：把字体文件复制进项目，改成 <code>source: "local"</code>。</p>
<pre><code>// 之前：构建时要联网下载
source: "fontsource",

// 之后：文件就在仓库里
source: "local",
variants: [{ file: "src/assets/fonts/outfit-latin-400.woff2", weight: 400 }],
</code></pre>
<p>代价是仓库多了 122KB 的字体文件，收益是<strong>构建全程零外网请求</strong>，离线也能构建。这笔账很划算。</p>
<h3>坑 3：EdgeOne 绑定域名要绑银行卡</h3>
<p>Node 版本调好之后 EdgeOne 终于能构建了。但到绑定自定义域名这一步，要求填银行卡。</p>
<p>我能理解平台要防滥用，但一个个人博客，我确实不想为此绑卡。于是换方案。</p>
<h3>坑 4：git rebase 卡在中间，仓库变成 detached HEAD</h3>
<p>改提交作者的时候跑了个 <code>git rebase</code>，它停在了交互模式没走完：</p>
<pre><code>interactive rebase in progress; onto 934f0fb
No commands remaining.
</code></pre>
<p>这时候的仓库处于"半完成"状态，之后的提交不会挂在任何分支上。修法是补一句 <code>git rebase --continue</code> 收尾，然后 <code>git push --force-with-lease</code>。</p>
<blockquote>
<p><code>--force-with-lease</code> 比 <code>--force</code> 安全：远程有你不知道的新提交时它会拒绝，而不是直接覆盖。</p>
</blockquote>
<h3>坑 5：Jekyll 会把 <code>_astro/</code> 目录吃掉</h3>
<p>GitHub Pages 默认会用 Jekyll 处理文件，而 Jekyll <strong>忽略所有下划线开头的目录</strong>。Astro 的产物里正好有 <code>_astro/</code>，里面是全部样式和脚本。</p>
<p>不处理的话：页面能打开，但<strong>没有任何样式，白板一张</strong>。</p>
<p>解法是放一个空的 <code>.nojekyll</code> 文件在产物根目录。（用 GitHub Actions 部署的话其实不会走 Jekyll，但加上没有坏处。）</p>
<h2>三、最后的架构</h2>
<p>折腾完，落成这样：</p>
<pre><code>flowchart LR
    A["本地写 Markdown&lt;br/&gt;src/content/posts"] --&gt; B["git push"]
    B --&gt; C["GitHub Actions&lt;br/&gt;pnpm build"]
    C --&gt; D["dist/ 静态产物"]
    D --&gt; E["GitHub Pages"]
    F["DNSPod&lt;br/&gt;A 记录 + CNAME"] --&gt; E
    E --&gt; G["sanyue0608.site"]
</code></pre>
<p>具体是：</p>
<ul>
<li><strong>代码</strong>放 GitHub 仓库（公开，因为免费账号的 Pages 不支持私有仓库）</li>
<li><strong>构建</strong>交给 GitHub Actions，推一次 <code>main</code> 就自动 <code>pnpm install &amp;&amp; pnpm build</code></li>
<li><strong>托管</strong>用 GitHub Pages，产物是 <code>dist/</code></li>
<li><strong>域名</strong>在 DNSPod 加四条 A 记录指向 GitHub 的 IP，<code>www</code> 走 CNAME</li>
</ul>
<p>整套东西的成本是：域名几十块一年，其余全免费。</p>
<p>日常更新就三步：</p>
<pre><code># 写文章
pnpm new-post 文章名
# 本地看效果
pnpm dev
# 推上去，2-3 分钟后线上更新
git add . &amp;&amp; git commit -m "post: 新文章" &amp;&amp; git push
</code></pre>
<h2>四、给同样想搭博客的人</h2>
<p>如果你完全不懂前端，也想搞一个：</p>
<ol>
<li><strong>先想清楚"为什么"</strong>。技术选型会变，理由不会。我是想要一个"不会被算法决定顺序、也不会被平台随时关掉"的地方。</li>
<li><strong>静态站点是新手最省心的选择</strong>。没有服务器要维护，没有数据库会挂，搬家成本几乎为零。</li>
<li><strong>报错先看第一行</strong>。这次两个大坑——Node 版本、字体 CDN——真正的错误都在日志最上面，而平台日志默认展示的往往是最后几行"失败"信息。</li>
<li><strong>"重跑一次就好了"是危险信号</strong>。它通常意味着有缓存掩盖了真实问题，等换到干净环境就会必现。</li>
<li><strong>别怕推翻方案</strong>。EdgeOne 那条路我折腾了大半天，发现要绑卡就立刻换 GitHub Pages，两小时搞定。沉没成本不该影响决策。</li>
</ol>
<h2>最后</h2>
<p>这个站现在还很空：一篇文章、一条动态、一个系列。</p>
<p>但至少它是活的——我能往里写东西，写完推一下，它就在那儿了。</p>
<p>下一篇大概会写「怎么把首页改成我想要的样子」，毕竟现在用的还是主题自带的图。</p>
]]></content>
    <author><name>叁月</name></author>
    <category term="建站"/>
  </entry>
  <entry>
    <title>你好，世界</title>
    <link href="https://sanyue0608.site/posts/hello-world/" rel="alternate" type="text/html"/>
    <id>https://sanyue0608.site/posts/hello-world/</id>
    <published>2026-11-11T12:30:00.000Z</published>
    <updated>2026-11-11T12:30:00.000Z</updated>
    <summary>这里的第一篇文章。记录一下这个小站是怎么来的，以及它以后会长成什么样。</summary>
    <content type="html"><![CDATA[<p>这是这个博客的第一篇文章。</p>
<p>建这个站花了点时间，但真正难的部分其实不是技术——是想清楚「我为什么要有一个自己的地方」。答案很简单：有些话说完了会散，有些想法不写下来就没了。我想要一个不会被算法决定顺序、也不会被平台随时关掉的角落。</p>
<h2>这里会有什么</h2>
<p>大概三类：</p>
<ul>
<li><strong>技术笔记</strong>：踩过的坑、读完文档之后的整理。写给别人看之前，先写给自己。</li>
<li><strong>生活碎片</strong>：某天的天气、某个忽然的想法，短一点的那种。</li>
<li><strong>长期的东西</strong>：一个会慢慢变长的系列，而不是发完就沉下去的单篇。</li>
</ul>
<h2>关于这个站</h2>
<p>它用 <a href="https://astro.build/">Astro</a> 构建，主题是开源的 <a href="https://github.com/LyraVoid/Shirone">Shirone</a>。选它是因为两件事：</p>
<ol>
<li><strong>静态站点</strong>——页面在你打开之前就已经生成好了，所以很快，也不需要数据库和服务器维护。</li>
<li><strong>写作体验好</strong>——Markdown 直接写，公式、代码、图表都能用，不用为了排版跟编辑器打架。</li>
</ol>
<p>:::note
下面这段是给未来的自己看的备忘：本站的文章源文件都在 <code>src/content/posts/</code>，
写一篇新文章只需要 <code>pnpm new-post 文件名</code>，然后编辑生成的 <code>.md</code> 文件。
:::</p>
<h2>一个小例子</h2>
<p>比如代码块，写起来是这样：</p>
<pre><code>// post.frontmatter 里填的那些字段，决定了文章出现在哪里、以什么顺序
export const greeting = (name: string) =&gt; `你好，${name}`;

greeting("世界"); // "你好，世界"
</code></pre>
<p>数学公式也没问题：</p>
<p>$$
\sum_{n=1}^{\infty} \frac{1}{n^2} = \frac{\pi^2}{6}
$$</p>
<h2>最后</h2>
<p>如果你刚好路过这里，欢迎随便看看。这里没有更新计划，也没有 KPI——想到了就写，写完了就放在这儿。</p>
<blockquote>
<p>把日常写成可以翻阅的样子。</p>
</blockquote>
]]></content>
    <author><name>叁月</name></author>
    <category term="生活"/>
  </entry>
</feed>
