使用 Astro 构建并部署个人博客到 GitHub Pages 全流程指南

作为开发者,我们很多人都希望拥有一个属于自己的博客。它不仅可以记录成长历程、展示作品,还能帮助我们梳理和积累知识。我自己也一直在维护博客,并在过程中不断学习新技术。最近我尝试了一个新兴的静态站点生成器 Astro,并成功将博客部署到了 GitHub Pages。这篇文章将一步步分享整个流程,包括 Astro 项目创建、路径配置、图片处理、分支推送、Token 设置等关键细节,希望对你有所帮助。

1. 为什么选择 Astro?

市面上有很多静态网站生成器(SSG),例如 Hexo、Hugo、11ty 等等。而 Astro 是近年来备受关注的一款,原因包括:

  • 极快的加载速度:Astro 默认采用静态渲染,生成纯静态的页面,没有多余的前端负担。这意味着用户打开你的博客会非常迅速,体验流畅。
  • 框架无关且兼容多框架:Astro 并不局限于某个前端框架。你可以在 Astro 项目中混用 React、Vue、Svelte 等组件 。对于熟悉这些框架的前端开发者来说,迁移成本低,想用哪种组件就用哪种。
  • 支持 Markdown 和 MDX:写博客离不开 Markdown。Astro 原生支持 Markdown,同时也支持 MDX(在 Markdown 中使用JSX组件)。这意味着你可以一边用简洁的 Markdown 写作,一边插入动态组件丰富内容,灵活性很高。
  • 部署简单、生态活跃:Astro 的社区非常活跃,新手遇到问题可以很容易地找到资源和解答。而且部署非常方便,官方文档提供了多种部署方案。对于我们来说,省心是很重要的因素。

相比一些老牌的静态站点工具,Astro 更现代化、更易上手,也更符合当前前端的发展趋势 。如果你想尝试新的技术栈,Astro 值得一试。

2. 创建 Astro 博客项目

在开始之前,请确保你已经安装了 Node.js(建议版本 ≥ 18,以满足 Astro 的要求)。现在,我们使用官方脚手架命令来创建项目:

npm create astro@latest

执行上述命令后,Astro 会启动交互式向导,引导你初始化项目。按照提示选择项目模板,这里我们选择 Blog 模板(博客模版),以便快速生成一个带有示例文章和布局的博客框架 。脚手架会自动下载所需文件并安装依赖(如果没有自动安装,记得进入项目目录后运行 npm install)。

依赖安装完成后,在项目目录运行开发服务器:

npm run dev

Astro 启动本地服务的默认端口是 4321,你可以打开浏览器访问 http://localhost:4321 查看博客的预览效果 。如果一切顺利,你现在应该可以看到一个默认的 Astro 博客站点在本地跑起来了。

小提示:如果 4321 端口被占用了,Astro 会尝试使用下一个可用端口。终端会打印实际使用的地址,请以终端输出为准。

现在,我们已经成功创建了 Astro 项目并在本地运行起来,接下来就可以根据需要自定义博客内容了。

3. 自定义页面内容

Astro 的博客模板已经为我们生成了基本的页面和示例内容。你可以根据个人需求,对这些页面进行修改或新增页面。常见的定制包括:

  • 首页内容:编辑 src/pages/index.astro 文件,修改首页显示的内容。
  • 关于页面:编辑 src/pages/about.astro(或将其改名为 about.html.astro,详见下节)来自定义“关于我”页面的信息。
  • 博客文章:在 src/content/blog/ 目录下撰写或添加 Markdown/MDX 文件来发布文章。

一般来说,博客模板会附带几篇示例博文。你可以参考它们的格式,然后撰写自己的文章:文件放在 src/content/blog/ 下,使用 markdown 前置 YAML (---) 来写标题、日期等元信息,内容用 Markdown 语法书写。Astro 会在构建时把这些文章生成静态页面。

下面是一个关于页面的示例代码片段,使用 Astro 组件和 Markdown 语法编写:

3.1 关于我页面示例(About Me)

<Layout
  title="About Me"                         <!-- 页面标题,将会显示在页面头部或标签页标题 -->
  description="Software Engineer & AI Explorer"  <!-- 页面描述,有利于SEO -->
  pubDate="2025-04-02"                     <!-- 发布日期 -->
  heroImage="/blog-placeholder-about.jpg"  <!-- 页眉背景图(从 public/ 文件夹引用) -->
>
  <p>
    Hi! I’m Yuxu Ge, a software engineer and AI enthusiast with 10+ years of backend experience.
    I'm currently pursuing an MSc in AI, exploring LLMs, RAG, agents and virtual intelligence.
  </p>
</Layout>

上面这段代码定义了一个关于我的页面。在 Astro 中,页面组件可以使用类似 HTML + JSX 的语法。这里我们利用博客模板提供的 组件,传入了标题、描述、日期、头图等属性,然后在其子节点中写入页面内容。你可以根据自己的情况修改这些文字,比如将 Yuxu Ge 改成你的名字,描述你的背景等。注意 heroImage 引用了 /blog-placeholder-about.jpg,这是放在 public/ 目录下的一张图片(Astro 会自动映射 /public 为网站根路径,关于图片的处理我们稍后详谈)。

3.2 生成 /about.html而不是/about/index.html

默认情况下,Astro 会将每个页面生成为一个文件夹形式,比如 about.astro 会输出为 dist/about/index.html(访问时对应 /about/ 路径)。如果你更希望关于页的路径直接是 /about.html(这样访问路径中会带有文件名),可以通过重命名页面文件实现:

src/pages/about.html.astro

将页面文件名改为以上格式,Astro 构建时就会直接生成 dist/about.html 文件 。简单来说,在文件名中加入 .html 可以让 Astro 输出独立的 HTML 文件而非目录。这纯粹是路径风格的选择问题:两种方式都能正常访问页面,使用哪种取决于你的喜好。

完成内容定制后,你的博客在本地看起来应该更有个人特色了。不过,光有本地页面还不够,我们还需要考虑图片资源和部署等问题。下一节先来看看在 Astro 中如何正确地处理 Markdown 文档中的图片资源。

4. 正确处理 Markdown 中的图片

写技术博客往往需要插入图片(如截图、示意图等)。在 Astro 中,如果图片路径处理不当,可能会出现开发时能看到图片但部署后图片丢失的问题。Astro 官方给出了推荐的解决方案:

  • 将图片放入 public/ 目录:例如你有一张图片想在文章中使用,可以将其保存路径如:public/images/blog/my-post/image.jpg 。
  • 在 Markdown 中使用绝对路径引用:假设上面的图片,你可以在文章 Markdown 文件中这样插入:
![示意图](/images/blog/my-post/image.jpg)
  • 路径以斜杠开头 /,表示从网站根目录查找,对应到 public 文件夹。

按照上述方式放置和引用图片,好处是在本地写作时编辑器预览能找到图片,在 Astro 构建时也会将 public 下的图片原封不动地打包进最终的 dist 目录 。因此,无论开发环境还是部署后,图片都能正常显示。

反之,不要把图片直接和 Markdown 文件混在一起(例如放在 src/content 内)。因为 Astro 不会处理 src/content 目录下的二进制文件,如果你这么做,结果很可能是本地编辑器能看到图片(因为引用的是本地路径),但实际构建出的站点并没有那些图片文件,用户在浏览器访问时就会出现 404 找不到图片 。简单打个比方:只有把物品放进行李箱(public 文件夹)里,搬家公司(Astro 打包过程)才会帮你运走;如果你把东西留在房间地板上(src/content),最后它们一定会被落下。

总之,记住一条原则:所有希望在网站上引用的静态资源(图片、视频等)都放进 public/ 里。这样可以避免很多路径问题。

📌 小经验:我在实践中就踩过一次图片路径的坑——部署后发现文章里的图片无法加载。最后才意识到是自己偷懒把图片放错了地方。按官方建议调整到 public 后,问题迎刃而解。

现在,博客内容和资源都准备就绪,接下来就是部署环节了。我们将使用 gh-pages 工具,将生成的静态站点发布到 GitHub Pages 上。

5. 使用 gh-pages 部署博客到 GitHub Pages

要将 Astro 生成的静态网站部署到 GitHub Pages,我们可以借助社区提供的 gh-pages 工具实现。一种常见的方法是:在本地构建出静态文件,然后利用 gh-pages 将 dist 目录推送到仓库的 gh-pages 分支上。GitHub Pages 可以将该分支的内容自动发布为网站。下面是具体步骤:

  1. 安装部署工具:在项目中安装 gh-pages 作为开发依赖。

    npm install --save-dev gh-pages

    该包提供了命令行工具,方便我们将静态文件发布到指定分支。

  2. 配置 astro.config.mjs:打开项目根目录下的 astro.config.mjs,设置站点的 base 路径。

如果你的 GitHub 仓库名是比如 virtual-velocity,那么需要添加如下配置:

import { defineConfig } from 'astro/config';

export default defineConfig({
  base: '/virtual-velocity/', // 基础路径:替换为你的仓库名,加前后斜杠
});

上述配置中的 base 用来告诉 Astro,你的网站将部署在 GitHub Pages 的哪一级路径下 。例如仓库名是 virtual-velocity,GitHub Pages 部署后访问路径会是 https://用户名.github.io/virtual-velocity/,所以这里 base 要设为 /virtual-velocity/。切记,这个路径一定要与你的仓库名称一致,否则部署后页面的静态资源(CSS、JS、图片)路径会对不上,导致网站样式错乱或资源404。我第一次部署时就忘了设置 base,结果网页打开后一片混乱,定位到问题后赶紧补上这个配置,重新部署才恢复正常。就像填写邮寄地址时别忘了写单元号一样,base 相当于告诉 Astro “网站会挂在仓库名对应的子目录下”,这样生成的链接才会精确无误。

如果你的博客仓库就是像 username.github.io 这种用户主页仓库(即整站部署在根域名下),那实际上不需要设置 base(或者设成 / 即默认值)。这里主要针对项目仓库的情况需指定 base。

  1. 添加部署脚本:在项目的 package.json 文件中加入一条方便的部署脚本。在 “scripts” 部分添加:
// package.json 部分内容
"scripts": {
  "deploy": "astro build && gh-pages -d dist --branch gh-pages"  // 构建并推送到gh-pages分支
}

这行脚本包含两个命令:先运行 astro build 构建出静态文件到 dist 文件夹,然后调用 gh-pages -d dist —branch gh-pages 将 dist 目录部署到远程仓库的 gh-pages 分支上 。你也可以把这两步拆开执行,但为了方便,一键脚本是更好的选择。

  1. 执行部署命令:在项目根目录,运行下面的命令开始部署:
npm run deploy

脚本会进行静态构建并将结果推送到仓库。如果是你首次部署,该命令可能会要求输入 GitHub 凭证用于认证(因为要推送到远程仓库)。由于 GitHub 已不支持使用账号密码直接推送代码,你需要使用 Token 或 SSH 来认证(这一点我们稍后详述)。如果一切顺利,命令执行完毕后,GitHub 仓库应该已经更新了 gh-pages 分支。

  1. 验证 GitHub Pages 部署:部署完成后,登录 GitHub 打开你的仓库,进入 Settings → Pages 查看 GitHub Pages 的配置。通常,当仓库存在一个 gh-pages 分支时,GitHub 会默认使用它作为 Pages 源。如果没有生效,你可以在 Pages 设置中手动将 Source 设为 gh-pages 分支。稍等几十秒让 GitHub 完成发布,然后通过浏览器访问你的博客地址。对于项目仓库,网址一般是:
https://<你的 GitHub 用户名>.github.io/<你的仓库名>/

(将其中的用户名和仓库名替换为你自己的。)例如,前面的仓库名例子,访问 https://yourname.github.io/virtual-velocity/ 就应该能看到部署后的博客主页了。

注意:如果 gh-pages 部署过程中提示错误 “分支已存在” 或 push 被拒绝,可以在脚本命令里添加 —force 参数强制覆盖远程分支。例如:gh-pages -d dist —branch gh-pages —force。下一节的问答中我们也涵盖了这个问题。

通过以上步骤,我们就把 Astro 生成的静态博客成功发布到了 GitHub Pages 上。整个流程并不复杂,一旦配置完成,以后更新内容只需一条命令就能部署,非常高效。不过在实战过程中,可能会遇到一些坑和问题,我们接下来总结一下常见的问题及解决方案。

6. 遇到的问题及解决方案汇总

在我搭建部署博客的过程中,曾遇到过一些小问题。下面整理了几项常见的问题和对应的解决方法,方便你对照排查:

  • sharp 模块缺失:首次运行项目如果出现类似 “Error: Cannot find module ‘sharp’” 的错误,这是因为 Astro 的图像优化功能默认使用了 sharp 库,但某些模板可能未自动安装它。解决办法很简单:执行 npm install sharp 安装该依赖。或者你也可以安装 Astro 提供的 Squoosh 图像处理集成来替代本地 sharp(Squoosh 基于 WebAssembly,无需本地依赖)。
  • 文章中的图片在编辑器预览可见但部署后浏览器 404:这通常是因为图片文件放错了位置。请确保将图片存放在 /public/ 目录,并使用以 / 开头的绝对路径引用(详见前文第4节)。只有放在 public 下的资源才会被正确打包到网站中,否则构建后找不到文件,浏览器自然报 404。
  • 构建输出路径为 /about/index.html 而不是 /about.html:这是 Astro 的默认行为。如果你希望直接生成根目录下的 about.html 文件,可以将页面文件命名为 about.html.astro(参考前文 3.2 节),这样构建结果就是单个 HTML 文件而非子目录。
  • 使用 gh-pages 部署时报错“remote branch already exists”:这表示目标分支上已经有内容,gh-pages 默认不覆盖已有分支。解决方法是在部署命令后加上 —force 参数强制推送覆盖。例如:gh-pages -d dist —branch gh-pages —force。但请注意,强制推送可能覆盖之前在该分支上的改动,谨慎使用。
  • 推送代码到 GitHub 遇到 SSH 连接错误 (端口 22 被阻挡):有些网络环境(例如公司内网、校园网)会阻断 SSH 所使用的 22 端口。如果你的本地仓库使用 SSH 链接远程仓库,部署时可能连不上 GitHub。解决方案是改用 HTTPS 协议的远程地址:运行 git remote set-url origin https://github.com/yourname/yourrepo.git 将远程地址切换为 HTTPS。HTTPS 通常走443端口,普遍不会被封锁。
  • GitHub 不接受账户密码推送:如今 GitHub 已经禁用了通过账号密码进行 Git 操作的方式。如果部署时终端要求输入用户名/密码,你即便输入GitHub账户密码也会失败。正确做法是使用 Personal Access Token 作为密码,或者事先配置好 SSH Key 来认证身份(具体见下一节 GitHub Token 鉴权配置)。总之,确保你的本地 Git 能够成功推送到 GitHub——这取决于你是否配置了 Token 或 SSH。

以上问题中,特别是最后关于 GitHub 认证的部分非常关键。如果没有正确配置令牌(Token)或 SSH,你的代码是推不上去的。下面我们来详细说明一下 GitHub 的鉴权设置。

7. GitHub Token 鉴权配置(重要)

自 2021 年末起,GitHub 已禁用使用帐户密码进行 Git 推送。也就是说,当你执行 git push 或通过类似 gh-pages 工具推送内容到 GitHub 时,不能再用用户名+密码的方式登录认证,否则会失败。取而代之,你有两个选择:

  1. 使用 Personal Access Token 进行认证:Personal Access Token(简称 PAT)是由GitHub提供的一串令牌,可以代替密码进行命令行操作。你需要先登录 GitHub,在账户设置的 Developer Settings 中生成一个 PAT(选择 classic 类型,勾选.repo 权限) 。生成后复制保存这串 Token。在推送代码时,当终端要求输入密码时,就粘贴这个 Token。注意,Token 只会显示一次,务必妥善保存;而且出于安全考虑,不要把 Token 明文写在仓库代码里或分享给他人。如果不小心泄露了 Token,可以在 GitHub上立即作废它。以后每次推送都使用 Token 替代密码即可。

    💡 提示:Token 就像 GitHub 发给你的“通行证”,权限范围由你创建时选择。一般用于仓库读写的 Token 需要勾选 repo 权限。生成 Token 的界面可以通过 GitHub 设置页面 打开。

  2. 改用 SSH Key 进行认证:SSH 是另一种常用且安全的 Git 认证方式。如果你已经在本地生成了 SSH 公私钥对,并将公钥添加到 GitHub 帐号,那么可以使用 SSH 来免密推送代码。方法是将本地仓库的远程地址改为 SSH 格式。例如:

git remote set-url origin [email protected]:yourname/yourrepo.git

把上面的 yourname/yourrepo 替换为你的 GitHub 用户名和仓库名。执行该命令后,本地仓库的 origin 地址就从 https:// 改为了 [email protected](SSH形式)。之后在有网络通畅的情况下(确保22端口不被拦截,或你在 .ssh/config 中配置了替代端口),Git 推送就会通过 SSH 完成,不再需要输入密码或 Token。使用 SSH 的前提是你已经在本机生成过 SSH Key并将公钥添加到 GitHub,如果还没有,可以参考 GitHub 官方文档生成并添加 SSH Key。

对于大多数个人开发者来说,使用 Token 认证是比较直观的方式:只需生成一次,然后每次部署用它即可。而 SSH 适合经常使用 Git 的开发者配置,一劳永逸免密码。如果你按照本文流程走下来,建议至少提前准备好上述两种方案之一,否则在部署时可能会因为没有权限推送而卡住。

总结

通过 Astro + GitHub Pages 的组合,我们可以相当迅速地搭建起一个现代化、极简且易维护的个人博客。从创建项目、个性化内容,到配置部署脚本、解决常见问题,每一步都相对清晰。一旦把这些配置琐事都处理好,今后写完文章执行一条 npm run deploy 命令,就能把最新博客内容发布上线,真正达到所写即所得的效果 。

回顾整个流程,你会发现搭建一个博客并没有想象中那么难。借助 Astro 强大的静态生成能力和 GitHub Pages 免费的托管服务,个人博客的搭建成本几乎为零,你要做的就是专心写作和分享。希望这篇指南能够帮助你避开一些坑,顺利拥有自己的线上博客主页!🙂

🌐 示例地址(部署完成后访问):https://yourname.github.io/your-repo/ (将 yourname 和 your-repo 替换为你的 GitHub 用户名和仓库名)


🔧 配置自定义域名(如 blog.geyuxu.com)

以上步骤完成后,你的博客已经可以通过 GitHub 提供的默认域名访问(例如 https://yourname.github.io/yourrepo/)。但是很多人希望使用一个自己的域名,让博客看起来更加专业,比如将博客绑定到 blog.geyuxu.com 这样的个性域名。下面我们以此为例,介绍如何将 GitHub Pages 部署的博客绑定自定义域名:

  1. 在 GitHub 仓库中设置自定义域名:

    首先,在 GitHub 上打开你的博客仓库的设置页面。依次点击 Settings → Pages,找到 “Custom domain” 设置项。在输入框中填入你准备绑定的域名,例如:blog.geyuxu.com。填写后,点击保存(Save)。建议勾选下面的 “Enforce HTTPS” 选项,这样当别人通过 http 访问时会自动跳转到安全的 https 上。

  2. 在项目的 public/ 目录中添加 CNAME 文件:

    在本地项目的 public/ 文件夹下,新建一个名为 CNAME 的文件(没有扩展名的纯文本文件)。文件内容仅需一行,写上你的自定义域名,例如:

    blog.geyuxu.com

    保存该文件并确保提交到仓库(也就是包含在 Astro 构建的 dist 中)。CNAME 文件的作用是告诉 GitHub Pages 你的站点所对应的域名。

    ⚠️ 注意:CNAME 文件里不要包含 http:// 或 https:// 前缀,只写域名本身即可;并且确保文件中没有多余的空行或空格,否则可能识别出错。

  3. 配置域名 DNS 解析(在你的域名服务商后台操作):

登陆你购买域名的服务商控制台,在 DNS 设置中添加一条记录,将你的自定义域名指向 GitHub Pages。具体配置如下:

  • 记录类型:CNAME
  • 主机记录:填写子域名前缀,例如使用 blog.geyuxu.com 就填 blog(如果想直接绑定顶级域名如 geyuxu.com,主机记录留空或填 @,但顶级域名绑定还需添加 A 记录,稍后提及)
  • 指向(值):填写 yourname.github.io,将其替换为你的 GitHub 用户名 后加 .github.io。这表示将该子域指向你的用户页面。
  • TTL:默认值或自动。

例如,对于域名 blog.geyuxu.com,GitHub 用户名为 geyuxu 的情况,这条 CNAME 记录应是:主机记录 blog,值指向 geyuxu.github.io。配置保存生效后,blog.geyuxu.com 就会解析到 GitHub。

  1. 测试并访问:

DNS 修改通常需要一些时间生效(通常几分钟到几小时不等,取决于DNS服务商)。稍等片刻后,在浏览器中访问你的自定义域名,例如 https://blog.geyuxu.com,此时应该能够看到你的博客页面正常显示了。如果没有生效,耐心等待并检查上述步骤是否正确。

小贴士:

  • 每次使用 npm run deploy 部署时,gh-pages 工具都会自动包含并上传 public/CNAME 文件,所以在第一次设置好后,后续无需每次手动去 GitHub 设置页面修改域名。只要 CNAME 文件在,GitHub Pages 就会一直将你的站点绑定到指定域名。
  • 如果你绑定的是顶级域名(例如直接使用 geyuxu.com 而不是子域名),除了添加 CNAME 记录外,还需要在 DNS 中添加 A 记录,将裸域指向 GitHub Pages 的服务器 IP 地址(GitHub 提供了一组固定 IP)。具体的 IP 列表和说明可以参考 GitHub 官方文档
Ge Yuxu • AI & Engineering

脱敏说明:本文所有出现的表名、字段名、接口地址、变量名、IP地址及示例数据等均非真实, 仅用于阐述技术思路与实现步骤,示例代码亦非公司真实代码。 示例方案亦非公司真实完整方案,仅为本人记忆总结,用于技术学习探讨。
    • 文中所示任何标识符并不对应实际生产环境中的名称或编号。
    • 示例 SQL、脚本、代码及数据等均为演示用途,不含真实业务数据,也不具备直接运行或复现的完整上下文。
    • 读者若需在实际项目中参考本文方案,请结合自身业务场景及数据安全规范,使用符合内部命名和权限控制的配置。

版权声明:本文版权归原作者所有,未经作者事先书面许可,任何单位或个人不得以任何方式复制、转载、摘编或用于商业用途。
    • 若需非商业性引用或转载本文内容,请务必注明出处并保持内容完整。
    • 对因商业使用、篡改或不当引用本文内容所产生的法律纠纷,作者保留追究法律责任的权利。

Copyright © 1989–Present Ge Yuxu. All Rights Reserved.