先谈下感受,最近通过搭建这个博客网站,对很多网站搭建相关知识和技术有了更进一步的认识,且通过实操实现了很好的效果,下面就来详细讲述一下整体的过程。
背景
在最开始搭建这个博客网站的时候,由于对前端的技术栈不够熟悉,所以一开始选择的是使用最广泛的React框架搭建了一套前端项目, 并把后端SpringBoot服务同时搭建起来,用于数据存储和权限管理。前后端分离的项目有很多好处,然而, 对于博客网站这种静态资源偏多的项目,变更并不频繁,且没有较多的动态交互,所以更加适合采用静态页面生成技术。 所以,在进一步了解了SSG相关的技术栈后,结合自己的项目情况,将该博客项目迁移至了新的项目上,网站加载速率明显提升,用户交互体验更好, 整体效果符合预期。
相关技术栈
- Nextjs
- Vercel
- AWS
什么是 SSG 静态页面生成技术?
SSG (Static Site Generation) 是一种网站生成技术,能够在构建阶段将网页的 HTML 文件预先生成并存储为静态文件。 与传统的动态渲染方式不同,SSG 页面在用户请求时无需后端处理或数据库查询,而是直接返回静态 HTML,提高了页面加载速度和稳定性。
SSG 的优点:
- 加载速度快:由于页面是静态的,浏览器可以直接加载 HTML 和资源,无需服务器动态渲染。
- SEO 友好:页面在构建时已生成完整的 HTML,有助于搜索引擎抓取。
- 高扩展性:由于静态文件可以部署到全球 CDN 上,用户可快速访问。
- 安全性强:没有运行时依赖后端逻辑,减少了潜在安全漏洞。
适用场景:
- 内容较少变化的网站,如博客、文档网站。
- 需要优化初次加载速度的网站。
- SEO 优化需求高的网站。
Next.js 对 SSG 的支持
Next.js 是一个基于 React 的框架,它以其灵活的渲染模式支持 SSG。Next.js 通过 getStaticProps 和 getStaticPaths 提供了强大的工具来实现 SSG。
关键特性:
getStaticProps:
- 用于在构建时获取页面所需的数据。
- 返回的数据将被注入页面组件的 props 中,生成静态 HTML。
- 示例:
javascript export async function getStaticProps() { const data = await fetchData(); return { props: { data }, }; }
getStaticPaths:
- 用于生成动态路由的静态页面,例如博客的详情页。
- 在构建时,根据返回的路径生成每个页面的 HTML。
- 示例:
javascript export async function getStaticPaths() { const paths = getBlogPaths(); // 返回如 [{ params: { id: '1' } }] return { paths, fallback: false, // 或 true }; }
- 增量静态生成 (ISR):
- Next.js 提供了 增量静态生成 功能,允许开发者在构建后自动更新生成的静态页面。
- 示例:
javascript export async function getStaticProps() { const data = await fetchData(); return { props: { data }, revalidate: 60, // 每 60 秒重新生成一次页面 }; }
SSG 的工作原理:
- 在构建阶段调用
getStaticProps
和getStaticPaths
,生成静态 HTML 文件。 - 部署时,这些 HTML 文件与其他静态资源一起存储在服务器或 CDN。
- 用户请求时,直接从 CDN 返回页面内容。
Vercel 对 SSG 的支持
Vercel 是 Next.js 的官方托管平台,针对 SSG 和其他渲染模式提供了高度优化的支持。
关键特性:
- 全球分布式 CDN:
- SSG 生成的静态文件可以部署到 Vercel 的全球 CDN 节点,确保快速访问。
- 自动构建和部署:
- 与 GitHub/GitLab 集成,每次代码更新后,Vercel 会自动重新构建静态页面。
- ISR 原生支持:
- Vercel 原生支持 Next.js 的增量静态生成,通过自动管理缓存实现实时更新。
- 预览模式:
- Vercel 支持 Next.js 的 Preview Mode,允许开发者查看未发布的内容变更。
- 零配置优化:
- Vercel 自动配置 HTTP 缓存头,确保静态资源的高效缓存和有效更新。
配合工作流:
- 开发者在本地使用 Next.js 编写代码。
- 推送代码到 GitHub/GitLab。
- Vercel 监测到代码更新,触发构建过程:
- 运行 getStaticProps 和 getStaticPaths,生成静态页面。
- 将 HTML 和资源部署到全球 CDN。
- 用户访问时,从最近的 CDN 节点快速获取内容。
迁移过程
- 在Vercel上注册账号,选择一个合适的博客模板项目,关联github账号后初始化repo并部署
- 基于该博客模板进行样式的修改,并将原有博客改为markdown文本模式加入新项目,修改完成后部署
- 将原有域名映射至新的Vercel部署的服务
- 对项目增加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;
}