chore: update the old blog article, enrich the content with more images.
BIN
public/images/recaps/switch-blog-to-nextjs/astro-actions.png
Normal file
After Width: | Height: | Size: 97 KiB |
BIN
public/images/recaps/switch-blog-to-nextjs/astro-uploader.png
Normal file
After Width: | Height: | Size: 114 KiB |
BIN
public/images/recaps/switch-blog-to-nextjs/astro.jpg
Normal file
After Width: | Height: | Size: 738 KiB |
BIN
public/images/recaps/switch-blog-to-nextjs/contentlayer.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
public/images/recaps/switch-blog-to-nextjs/next.js.png
Normal file
After Width: | Height: | Size: 582 KiB |
BIN
public/images/recaps/switch-blog-to-nextjs/open-graph.png
Normal file
After Width: | Height: | Size: 321 KiB |
BIN
public/images/recaps/switch-blog-to-nextjs/opendal.png
Normal file
After Width: | Height: | Size: 174 KiB |
BIN
public/images/recaps/switch-blog-to-nextjs/replace-artalk.png
Normal file
After Width: | Height: | Size: 96 KiB |
BIN
public/images/recaps/switch-blog-to-nextjs/velite.jpg
Normal file
After Width: | Height: | Size: 240 KiB |
BIN
public/images/recaps/switch-blog-to-nextjs/zeabur-astro.png
Normal file
After Width: | Height: | Size: 60 KiB |
@ -2,7 +2,7 @@
|
|||||||
title: 弃用 WordPress 了,但我相当“后悔”
|
title: 弃用 WordPress 了,但我相当“后悔”
|
||||||
slug: switch-blog-to-nextjs
|
slug: switch-blog-to-nextjs
|
||||||
date: 2024-04-07 16:09:09
|
date: 2024-04-07 16:09:09
|
||||||
updated: 2024-06-23 15:21:05
|
updated: 2024-10-16 00:25:05
|
||||||
tags:
|
tags:
|
||||||
- 博客
|
- 博客
|
||||||
category: 编程
|
category: 编程
|
||||||
@ -48,18 +48,26 @@ Logo 部分的字体,主要是基于 [M+A1](https://booth.pm/ja/items/2347968)
|
|||||||
|
|
||||||
## 技术选型
|
## 技术选型
|
||||||
|
|
||||||
|
![Next.js](/images/recaps/switch-blog-to-nextjs/next.js.png)
|
||||||
|
|
||||||
技术选型上这次有点激进,相比已经成熟很好用的 VitePress 等动静结合的生成工具,我义无反顾地选用了 Next.js 的 App Router,运行环境选用了更快的 Bun。至于其他方面,基本是照着 [leerob](https://leerob.io) 的博客进行仿写。所以文章格式不再是常见的 Markdown,而是能插入动态内容的 MDX。对于历史的评论,我还是舍不得丢弃,毕竟有 3000 多条。所以再三对比之下,我选择使用 [Artalk](https://artalk.js.org) 进行存储。有了多说的经历后,我也不敢使用任何第三方的 SaaS 服务存储评论,毕竟数据在自己手里才最安全。
|
技术选型上这次有点激进,相比已经成熟很好用的 VitePress 等动静结合的生成工具,我义无反顾地选用了 Next.js 的 App Router,运行环境选用了更快的 Bun。至于其他方面,基本是照着 [leerob](https://leerob.io) 的博客进行仿写。所以文章格式不再是常见的 Markdown,而是能插入动态内容的 MDX。对于历史的评论,我还是舍不得丢弃,毕竟有 3000 多条。所以再三对比之下,我选择使用 [Artalk](https://artalk.js.org) 进行存储。有了多说的经历后,我也不敢使用任何第三方的 SaaS 服务存储评论,毕竟数据在自己手里才最安全。
|
||||||
|
|
||||||
博客以前最喜欢的音乐播放器是 Hermit-X,对应的作者荒野无灯已经神隐很久,获取网易音乐信息的 [Meting API](https://github.com/metowolf/Meting) 也没持续更新。而 APlayer 更是不知道 [DIYgod](https://diygod.cc) 什么时候能来“扫墓”,上次 APlayer 的诈尸还只是更新了个 License。所以在新博客环境只有 [Aplayer React](https://aplayer-react.js.org) 这个名为 APlayer 实则是借着其样式用 React 完全重写的播放器可用,其在 RSC 下有点小问题,但估计短时间内作者也没时间修复。(谁叫我是前端菜鸟呢)
|
博客以前最喜欢的音乐播放器是 Hermit-X,对应的作者荒野无灯已经神隐很久,获取网易音乐信息的 [Meting API](https://github.com/metowolf/Meting) 也没持续更新。而 APlayer 更是不知道 [DIYgod](https://diygod.cc) 什么时候能来“扫墓”,上次 APlayer 的诈尸还只是更新了个 License。所以在新博客环境只有 [Aplayer React](https://aplayer-react.js.org) 这个名为 APlayer 实则是借着其样式用 React 完全重写的播放器可用,其在 RSC 下有点小问题,但估计短时间内作者也没时间修复。(谁叫我是前端菜鸟呢)
|
||||||
|
|
||||||
|
![ContentLayer](/images/recaps/switch-blog-to-nextjs/contentlayer.png)
|
||||||
|
|
||||||
MDX 一开始是手动使用 `fs` 加载,使用 `grey-matter` 解析 `matter` 后再用 `next-mdx-remote` 渲染。但是鉴于自己太菜,很多页面的渲染都需要全量读取博文解析。后面改成了[推友推荐](https://twitter.com/ilovek8s/status/1776809454790676827)的 `contentlayer` 先渲染静态化,再进行加载。但瞅着 `contentlayer` 这半死不活的状态,未来大概率还是要弃。😭
|
MDX 一开始是手动使用 `fs` 加载,使用 `grey-matter` 解析 `matter` 后再用 `next-mdx-remote` 渲染。但是鉴于自己太菜,很多页面的渲染都需要全量读取博文解析。后面改成了[推友推荐](https://twitter.com/ilovek8s/status/1776809454790676827)的 `contentlayer` 先渲染静态化,再进行加载。但瞅着 `contentlayer` 这半死不活的状态,未来大概率还是要弃。😭
|
||||||
|
|
||||||
## Update 2024/04/14
|
## Update 2024/04/14
|
||||||
|
|
||||||
|
![ContentLayer](/images/recaps/switch-blog-to-nextjs/velite.jpg)
|
||||||
|
|
||||||
没错,一周后我又来屁颠屁颠地更新博客啦,一周过去后,我的博客也发生了不少变化。首先是搜索终于支持了,使用的是 fuse.js。前文提到的 Contentlayer 也被我废弃,换成了更好用的 Velite。
|
没错,一周后我又来屁颠屁颠地更新博客啦,一周过去后,我的博客也发生了不少变化。首先是搜索终于支持了,使用的是 fuse.js。前文提到的 Contentlayer 也被我废弃,换成了更好用的 Velite。
|
||||||
|
|
||||||
## Update 2024/05/22
|
## Update 2024/05/22
|
||||||
|
|
||||||
|
![ContentLayer](/images/recaps/switch-blog-to-nextjs/astro.jpg)
|
||||||
|
|
||||||
今天,我把博客从 Next.js 迁移到了 Astro,重写了部分代码的实现,优化了部分设计。Next.js 版本的博客,内容管理和生成工具使用的是 Velite.js,它的设计很有想法,作者也很有经验。但是对应的 Next.js 与其集成后,却给我带来了很多解决不了的问题。首当其中的就是 Next.js 默认是 SSR,我在 MDX 中生成的内容,部分需要 inline 到 Client 端使用 JS 去动态执行,结果无法实现。其次就是 Astro 先天的在内容管理与编写上下了不少功夫。基于上述理由,我花了两天多一点的时间,就轻松把博客用 Astro 重写了。
|
今天,我把博客从 Next.js 迁移到了 Astro,重写了部分代码的实现,优化了部分设计。Next.js 版本的博客,内容管理和生成工具使用的是 Velite.js,它的设计很有想法,作者也很有经验。但是对应的 Next.js 与其集成后,却给我带来了很多解决不了的问题。首当其中的就是 Next.js 默认是 SSR,我在 MDX 中生成的内容,部分需要 inline 到 Client 端使用 JS 去动态执行,结果无法实现。其次就是 Astro 先天的在内容管理与编写上下了不少功夫。基于上述理由,我花了两天多一点的时间,就轻松把博客用 Astro 重写了。
|
||||||
|
|
||||||
重写之后发现 Astro 其实还是比较不成熟,很多东西文档并不清楚,还是要看源码来理清其设计想法。比如 `Astro:content` 的设计原理和其使用的细节问题,再比如 `Astro:asset` 这个特定的 import.meta 的使用问题。整体上而言,很多细节问题其实是 Astro 变化太快,对应的文档还没有来得及讲清楚。但是最让我失望的是,Astro 的 SSR 并不完善,它的 inline CSS 和 JS 的实现,其实是靠 Vite 整合 Rollup 提供的能力。所以在 SSR 上,如果你在一个 Astro Component 里面 `is:inline` 去定义 JS,很有可能会遇到因为模块重用而导致的坑。
|
重写之后发现 Astro 其实还是比较不成熟,很多东西文档并不清楚,还是要看源码来理清其设计想法。比如 `Astro:content` 的设计原理和其使用的细节问题,再比如 `Astro:asset` 这个特定的 import.meta 的使用问题。整体上而言,很多细节问题其实是 Astro 变化太快,对应的文档还没有来得及讲清楚。但是最让我失望的是,Astro 的 SSR 并不完善,它的 inline CSS 和 JS 的实现,其实是靠 Vite 整合 Rollup 提供的能力。所以在 SSR 上,如果你在一个 Astro Component 里面 `is:inline` 去定义 JS,很有可能会遇到因为模块重用而导致的坑。
|
||||||
@ -82,12 +90,16 @@ Astro Container API 前前后后经过数次修改。在最新的 Astro 4.11 中
|
|||||||
|
|
||||||
### Artalk 前端评论模块弃用
|
### Artalk 前端评论模块弃用
|
||||||
|
|
||||||
|
![ContentLayer](/images/recaps/switch-blog-to-nextjs/replace-artalk.png)
|
||||||
|
|
||||||
Artalk 作为后端评论系统,其实没啥问题,并且有相当不错的安全机制和设计,但是其前端样式怎么定义都不是很好看。早在准备自己实现评论系统的时候,第一个想法就是基于 Artalk 的 Rest API 改成 SSR 的模式加载评论。目前经过数次修改,其评论样式和效果已经和以前使用的 WordPress 基本接近。
|
Artalk 作为后端评论系统,其实没啥问题,并且有相当不错的安全机制和设计,但是其前端样式怎么定义都不是很好看。早在准备自己实现评论系统的时候,第一个想法就是基于 Artalk 的 Rest API 改成 SSR 的模式加载评论。目前经过数次修改,其评论样式和效果已经和以前使用的 WordPress 基本接近。
|
||||||
|
|
||||||
在做评论系统的替换的同时,也在遗忘了很久的百度网盘的网站备份目录中找到了多说和 Disqus 的备份。经过修改和迁移,已经成功将多说的评论全部导入进 Artalk。而 Disqus 的备份,受限于欧盟的 GDPR 政策,已经不再提供评论者的 Email 信息,所以只能基于历史评论进行检索对比来确定用户信息进行导入。虽然已经尽了全力,但还是有部分评论被废弃。
|
在做评论系统的替换的同时,也在遗忘了很久的百度网盘的网站备份目录中找到了多说和 Disqus 的备份。经过修改和迁移,已经成功将多说的评论全部导入进 Artalk。而 Disqus 的备份,受限于欧盟的 GDPR 政策,已经不再提供评论者的 Email 信息,所以只能基于历史评论进行检索对比来确定用户信息进行导入。虽然已经尽了全力,但还是有部分评论被废弃。
|
||||||
|
|
||||||
### Astro Actions 的使用
|
### Astro Actions 的使用
|
||||||
|
|
||||||
|
![ContentLayer](/images/recaps/switch-blog-to-nextjs/astro-actions.png)
|
||||||
|
|
||||||
因为博客的评论模块的替换,导入需要引入大量的 Rest 接口。结合以前有的喜欢按钮等接口,博客一共累计超过 4 个接口。以前都是散乱在 pages 目录里面,这次一并使用了 [Astro 4.8](https://astro.build/blog/astro-480/) 的 Actions 进行统一定义和管理,整体感受如下:
|
因为博客的评论模块的替换,导入需要引入大量的 Rest 接口。结合以前有的喜欢按钮等接口,博客一共累计超过 4 个接口。以前都是散乱在 pages 目录里面,这次一并使用了 [Astro 4.8](https://astro.build/blog/astro-480/) 的 Actions 进行统一定义和管理,整体感受如下:
|
||||||
|
|
||||||
1. Actions 和 tRPC 的使用体验基本相似,都是 Typed 的。
|
1. Actions 和 tRPC 的使用体验基本相似,都是 Typed 的。
|
||||||
@ -96,14 +108,45 @@ Artalk 作为后端评论系统,其实没啥问题,并且有相当不错的
|
|||||||
|
|
||||||
### Astro CDN 功能的整合和实现
|
### Astro CDN 功能的整合和实现
|
||||||
|
|
||||||
|
![ContentLayer](/images/recaps/switch-blog-to-nextjs/astro-uploader.png)
|
||||||
|
|
||||||
Astro 在 [2.2](https://astro.build/blog/astro-220/) 引入了 CDN Support,其主要目的是对动态构建的 CSS、JS 和图片等内容,可以自定义它们的访问路径和 URL,Astro 会在最终构建的网站结果中予以替换对应的资源路径。但是 Astro 只实现前面说的内容,如果想要在生产环境能实现全套的 CDN 支持,还需要将构建出来的文件上传到对应的 CDN 服务提供商。如,上传到 UPYUN、七牛云、S3 等对象存储。
|
Astro 在 [2.2](https://astro.build/blog/astro-220/) 引入了 CDN Support,其主要目的是对动态构建的 CSS、JS 和图片等内容,可以自定义它们的访问路径和 URL,Astro 会在最终构建的网站结果中予以替换对应的资源路径。但是 Astro 只实现前面说的内容,如果想要在生产环境能实现全套的 CDN 支持,还需要将构建出来的文件上传到对应的 CDN 服务提供商。如,上传到 UPYUN、七牛云、S3 等对象存储。
|
||||||
|
|
||||||
在这里我选用了用了近 10 年之久的 UPYUN,第一版是使用 0.25 引入的 [Astro Integration API](https://astro.build/blog/astro-025/#new-astro-integrations) 来进行实现。Astro Integration API 是一个非常经典的观察者模式的设计,它对应了 Astro 构建的几个不同阶段,允许你定义不同阶段的特殊勾子,Astro 会在对应阶段调用你的自定义逻辑。对于我而言,我只需要在 `'astro:build:done'` 阶段读取所有想要上传的目录,进行上传即可。
|
在这里我选用了用了近 10 年之久的 UPYUN,第一版是使用 0.25 引入的 [Astro Integration API](https://astro.build/blog/astro-025/#new-astro-integrations) 来进行实现。Astro Integration API 是一个非常经典的观察者模式的设计,它对应了 Astro 构建的几个不同阶段,允许你定义不同阶段的特殊勾子,Astro 会在对应阶段调用你的自定义逻辑。对于我而言,我只需要在 `'astro:build:done'` 阶段读取所有想要上传的目录,进行上传即可。
|
||||||
|
|
||||||
这期间对上传逻辑进行了多次重构,第一版使用 UPYUN Node.js SDK,但是这个 SDK 年久失修,使用的还是有安全问题的 axios 版本。对于已经习惯上 fetch 一把梭的我,有点生理不适。考虑到很多云存储都支持了 S3 协议,并且使用 S3 协议能更灵活地切换到不同的存储服务。在第二版使用了 Client S3 来进行实现,这里面遇到的唯一问题就是 ContentType 需要显式设置,而原先的 UPYUN Rest API 能根据文件名自动设置。
|
这期间对上传逻辑进行了多次重构,第一版使用 UPYUN Node.js SDK,但是这个 SDK 年久失修,使用的还是有安全问题的 axios 版本。对于已经习惯上 fetch 一把梭的我,有点生理不适。考虑到很多云存储都支持了 S3 协议,并且使用 S3 协议能更灵活地切换到不同的存储服务。在第二版使用了 Client S3 来进行实现,这里面遇到的唯一问题就是 ContentType 需要显式设置,而原先的 UPYUN Rest API 能根据文件名自动设置。
|
||||||
|
|
||||||
|
![ContentLayer](/images/recaps/switch-blog-to-nextjs/opendal.png)
|
||||||
|
|
||||||
第三版使用了基友 Tison 安利的 Apache OpenDAL™ 进行了重构,还是走的 S3 协议。Apache OpenDAL™ 是一个使用 Rust 编写的统一云存储层抽象接口,整体的代码质量和实现都很不错。但是 Node.js 部分的 Binding 使用 napi-rs 实现,对应的文档写得比较抽象,我是看 Rust 部分的文档反向推导 Node.js binding 该如何使用,期待文档的进一步完善。同时因为一些[已知问题](https://github.com/apache/opendal/issues/4782),暂时还无法直接在生产环境使用。
|
第三版使用了基友 Tison 安利的 Apache OpenDAL™ 进行了重构,还是走的 S3 协议。Apache OpenDAL™ 是一个使用 Rust 编写的统一云存储层抽象接口,整体的代码质量和实现都很不错。但是 Node.js 部分的 Binding 使用 napi-rs 实现,对应的文档写得比较抽象,我是看 Rust 部分的文档反向推导 Node.js binding 该如何使用,期待文档的进一步完善。同时因为一些[已知问题](https://github.com/apache/opendal/issues/4782),暂时还无法直接在生产环境使用。
|
||||||
|
|
||||||
|
## Update 2024/10/16
|
||||||
|
|
||||||
|
距离上次更新又过去了 4 个月,这期间看了不少书,博文倒是没写几篇。这期间博客的源码倒是没少折腾,但基本都是细枝末节的修改,如例行的升级依赖啥的,比较需要注意的更新有如下内容。
|
||||||
|
|
||||||
|
### 补完全部文章的插图
|
||||||
|
|
||||||
|
博客的文章书写时间已经有 15 年的跨度,这期间文章的很多插图,要么尺寸过小,要么丢失。在 3 年前切换回 Wordpress 时进行了统一的梳理,将所有图片去除,转成了 Markdown 格式,但并未补全全部插图。这次借着切换为 Astro 的机会,将博客的文章都配上了精美的插图,并设置了对应的封面图片。(何等可怕的工作量)
|
||||||
|
|
||||||
|
### 支持动态 OG 图片
|
||||||
|
|
||||||
|
![Open Graph](/images/recaps/switch-blog-to-nextjs/open-graph.png)
|
||||||
|
|
||||||
|
对于 OG 图片的支持,历时 3 个月才予以实现,最早的版本为选取文章的封面,后面改为使用 [@vercel/og](https://vercel.com/docs/functions/og-image-generation) 生成。博客切换为 Astro 时一并放弃了 React Server Component 方案,对应的 OG 生成暂时搁置。在仔细学习了基于 napi 的 `@napi-rs/canvas` 后,本博客的 OG 图片使用 Canvas 绘制,并在构建的时候静态生成放于对象存储上来减少字体加载、渲染等耗时。目前 OG 的样式经过多次微调,暂时满意。
|
||||||
|
|
||||||
|
### 使用 Zeabur Serverless Function 部署
|
||||||
|
|
||||||
|
![Zeabur Astro](/images/recaps/switch-blog-to-nextjs/zeabur-astro.png)
|
||||||
|
|
||||||
|
Zeabur 因为有中国区,考虑网站面向的人群,我实在是无法割舍。之前因为使用 Astro Container API,对应的包构建为 Lambda 时会有依赖问题,所以一直使用 Docker 方式在 Zeabur 部署。经过和 Zeabur 的小伙伴合作,同时完成了 Zeabur 对 `astro/env` 的支持后,现在网站已经不再使用 Docker 方式,转而使用 Zeabur 提供的 Serverless 的方式运行。
|
||||||
|
|
||||||
|
### 其他微调
|
||||||
|
|
||||||
|
* 文章页展示标签:标签更像是一个动态灵活的文章分类,之前设计新博客的时候有所遗漏,现在已经补上。
|
||||||
|
* 搜索结果支持分页:之前对 fuse.js 的理解不够深刻,经过仔细摸索,发现可以基于其结果做二次分页,于是不再限制搜索条数进行一页展示。
|
||||||
|
* 自定义鼠标样式:添加了箭头、手指的鼠标样式,并支持视网膜屏幕。
|
||||||
|
* 文章支持多别名:对于一篇文章,除了固定地址外,目前还支持了短链接别名。比如 https://yufan.me/papapa
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
写此文章前,本有一肚子关于清明三天折腾的坎坷想要倾诉。真正写下来的时候,却又没多少。一来是年龄的增长,很多东西不再像以前那么过激。二来,大部分问题基本解决。数数上次更新博客的时间,已经不知道是猴年马月。希望自己在未来的年月里,能笔耕不辍,多记录一点自己的生活。
|
写此文章前,本有一肚子关于清明三天折腾的坎坷想要倾诉。真正写下来的时候,却又没多少。一来是年龄的增长,很多东西不再像以前那么过激。二来,大部分问题基本解决。数数上次更新博客的时间,已经不知道是猴年马月。希望自己在未来的年月里,能笔耕不辍,多记录一点自己的生活。
|
||||||
|