如何部署低成本高容灾能力的博客网站

2024-12-15

先谈下感受,最近通过搭建这个博客网站,对很多网站搭建相关知识和技术有了更进一步的认识,且通过实操实现了很好的效果,下面就来详细讲述一下整体的过程。

背景

在最开始搭建这个博客网站的时候,由于对前端的技术栈不够熟悉,所以一开始选择的是使用最广泛的React框架搭建了一套前端项目, 并把后端SpringBoot服务同时搭建起来,用于数据存储和权限管理。前后端分离的项目有很多好处,然而, 对于博客网站这种静态资源偏多的项目,变更并不频繁,且没有较多的动态交互,所以更加适合采用静态页面生成技术。 所以,在进一步了解了SSG相关的技术栈后,结合自己的项目情况,将该博客项目迁移至了新的项目上,网站加载速率明显提升,用户交互体验更好, 整体效果符合预期。

相关技术栈

  • Nextjs
  • Vercel
  • AWS

什么是 SSG 静态页面生成技术?

SSG (Static Site Generation) 是一种网站生成技术,能够在构建阶段将网页的 HTML 文件预先生成并存储为静态文件。 与传统的动态渲染方式不同,SSG 页面在用户请求时无需后端处理或数据库查询,而是直接返回静态 HTML,提高了页面加载速度和稳定性。

SSG 的优点:

  1. 加载速度快:由于页面是静态的,浏览器可以直接加载 HTML 和资源,无需服务器动态渲染。
  2. SEO 友好:页面在构建时已生成完整的 HTML,有助于搜索引擎抓取。
  3. 高扩展性:由于静态文件可以部署到全球 CDN 上,用户可快速访问。
  4. 安全性强:没有运行时依赖后端逻辑,减少了潜在安全漏洞。

适用场景:

  • 内容较少变化的网站,如博客、文档网站。
  • 需要优化初次加载速度的网站。
  • SEO 优化需求高的网站。

Next.js 对 SSG 的支持

Next.js 是一个基于 React 的框架,它以其灵活的渲染模式支持 SSG。Next.js 通过 getStaticProps 和 getStaticPaths 提供了强大的工具来实现 SSG。

关键特性:

  1. getStaticProps:
    • 用于在构建时获取页面所需的数据。
    • 返回的数据将被注入页面组件的 props 中,生成静态 HTML。
    • 示例:
        javascript
        export async function getStaticProps() {
            const data = await fetchData();
            return {
                props: { data },
            };
        }
  2. getStaticPaths:
    • 用于生成动态路由的静态页面,例如博客的详情页。
    • 在构建时,根据返回的路径生成每个页面的 HTML。
    • 示例:
        javascript
        export async function getStaticPaths() {
            const paths = getBlogPaths(); // 返回如 [{ params: { id: '1' } }]
            return {
                paths,
                fallback: false, // 或 true
            };
        }
  3. 增量静态生成 (ISR):
    • Next.js 提供了 增量静态生成 功能,允许开发者在构建后自动更新生成的静态页面。
    • 示例:
        javascript
        export async function getStaticProps() {
            const data = await fetchData();
            return {
                props: { data },
                revalidate: 60, // 每 60 秒重新生成一次页面
            };
        }

SSG 的工作原理:

  1. 在构建阶段调用 getStaticPropsgetStaticPaths,生成静态 HTML 文件。
  2. 部署时,这些 HTML 文件与其他静态资源一起存储在服务器或 CDN。
  3. 用户请求时,直接从 CDN 返回页面内容。

Vercel 对 SSG 的支持

Vercel 是 Next.js 的官方托管平台,针对 SSG 和其他渲染模式提供了高度优化的支持。

关键特性:

  1. 全球分布式 CDN:
    • SSG 生成的静态文件可以部署到 Vercel 的全球 CDN 节点,确保快速访问。
  2. 自动构建和部署:
    • 与 GitHub/GitLab 集成,每次代码更新后,Vercel 会自动重新构建静态页面。
  3. ISR 原生支持:
    • Vercel 原生支持 Next.js 的增量静态生成,通过自动管理缓存实现实时更新。
  4. 预览模式:
    • Vercel 支持 Next.js 的 Preview Mode,允许开发者查看未发布的内容变更。
  5. 零配置优化:
    • Vercel 自动配置 HTTP 缓存头,确保静态资源的高效缓存和有效更新。

配合工作流:

  1. 开发者在本地使用 Next.js 编写代码。
  2. 推送代码到 GitHub/GitLab。
  3. Vercel 监测到代码更新,触发构建过程:
    • 运行 getStaticProps 和 getStaticPaths,生成静态页面。
    • 将 HTML 和资源部署到全球 CDN。
  4. 用户访问时,从最近的 CDN 节点快速获取内容。

迁移过程

  1. Vercel上注册账号,选择一个合适的博客模板项目,关联github账号后初始化repo并部署
  2. 基于该博客模板进行样式的修改,并将原有博客改为markdown文本模式加入新项目,修改完成后部署
  3. 将原有域名映射至新的Vercel部署的服务
  4. 对项目增加Github workflow配置,使其自动化部署至AWS s3,并使用Cloudfont加速

技术收获

双域名多云容灾

在做域名映射时,由于原有域名是在AWS购买的,而AWS上购买的根域名只能映射到AWS上自己的产品,无法映射外部域名, 所以,最终无心插柳柳成荫,考虑到AWS有Free Tier套餐,而Vercel本身也提供一定量的免费使用套餐,所以,这里产生了一个个人认为非常棒的idea。 就是把根域名blogofvictor.link仍然映射至AWS的S3并通过Cloudfont CDN加速,并修改项目的github workflow配置,使其自动化部署至s3, 并将www.blogofvictor.link映射至Vercel的域名,这样就形成了一个低成本高容灾能力的博客网站。两个产品本身都是接近零成本,且即使其中一个云服务完全宕机,也不影响该博客网站的正常展示。

AWS的Cloudfont路由逻辑问题

由于AWS的S3只负责静态资源的存储,并没有动态路由的能力,而Next.js 的路由是基于客户端渲染的。所以,当访问对应的博客页面时,AWS会存在跳转失败的问题, 经过深入研究后,发现是CloudFront Functions路由逻辑有问题。需要将逻辑改为:如果 URI 不包含文件扩展名,尝试为 URI 添加 .html 后缀。 对应function代码为

function handler(event) {
    var request = event.request;
    var uri = request.uri;

    // 检查 URI 是否包含文件扩展名
    if (!uri.includes('.')) {
        // 如果 URI 不包含扩展名,尝试加上 .html 后缀
        request.uri = uri + '.html';
    }

    return request;
}