chore: update the old blog article, enrich the content with more images.

This commit is contained in:
Yufan Sheng 2024-10-16 01:04:38 +08:00
parent cc60d4bde0
commit 3a4808001e
Signed by: syhily
GPG Key ID: DEB186763C308C31
14 changed files with 60 additions and 11 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 738 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 582 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 321 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 240 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -1,7 +1,6 @@
---
import { loadComments } from '@/components/comment/artalk';
import { increaseViews, loadComments } from '@/components/comment/artalk';
import Comment from '@/components/comment/Comment.astro';
import { increaseViews } from '@/helpers/db/query';
import { urlJoin } from '@/helpers/tools';
import options from '@/options';
@ -15,7 +14,7 @@ const { commentKey, title } = Astro.props;
const comments = await loadComments(commentKey, title, 0);
// Increase the PV.
await increaseViews(commentKey);
await increaseViews(commentKey, title);
---
<div id="comments" class="comments py-5">

View File

@ -33,6 +33,20 @@ export const loadComments = async (key: string, title: string | null, offset: nu
return data != null ? (data as Comments) : data;
};
export const increaseViews = async (key: string, title: string) => {
await fetch(urlJoin(server, '/api/v2/pages/pv'), {
method: 'POST',
headers: {
'Content-type': 'application/json; charset=UTF-8',
},
body: JSON.stringify({
page_key: key,
page_title: title,
site_name: options.title,
}),
});
};
export const createComment = async (req: CommentReq): Promise<ErrorResp | CommentResp> => {
const user = await queryUser(req.email);
if (user !== null && user.name !== null) {

View File

@ -2,7 +2,7 @@
title: 弃用 WordPress 了,但我相当“后悔”
slug: switch-blog-to-nextjs
date: 2024-04-07 16:09:09
updated: 2024-06-23 15:21:05
updated: 2024-10-16 00:25:05
tags:
- 博客
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 服务存储评论,毕竟数据在自己手里才最安全。
博客以前最喜欢的音乐播放器是 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` 这半死不活的状态,未来大概率还是要弃。😭
## Update 2024/04/14
![ContentLayer](/images/recaps/switch-blog-to-nextjs/velite.jpg)
没错,一周后我又来屁颠屁颠地更新博客啦,一周过去后,我的博客也发生了不少变化。首先是搜索终于支持了,使用的是 fuse.js。前文提到的 Contentlayer 也被我废弃,换成了更好用的 Velite。
## 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 重写了。
重写之后发现 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 前端评论模块弃用
![ContentLayer](/images/recaps/switch-blog-to-nextjs/replace-artalk.png)
Artalk 作为后端评论系统,其实没啥问题,并且有相当不错的安全机制和设计,但是其前端样式怎么定义都不是很好看。早在准备自己实现评论系统的时候,第一个想法就是基于 Artalk 的 Rest API 改成 SSR 的模式加载评论。目前经过数次修改,其评论样式和效果已经和以前使用的 WordPress 基本接近。
在做评论系统的替换的同时,也在遗忘了很久的百度网盘的网站备份目录中找到了多说和 Disqus 的备份。经过修改和迁移,已经成功将多说的评论全部导入进 Artalk。而 Disqus 的备份,受限于欧盟的 GDPR 政策,已经不再提供评论者的 Email 信息,所以只能基于历史评论进行检索对比来确定用户信息进行导入。虽然已经尽了全力,但还是有部分评论被废弃。
### 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 进行统一定义和管理,整体感受如下:
1. Actions 和 tRPC 的使用体验基本相似,都是 Typed 的。
@ -96,14 +108,45 @@ Artalk 作为后端评论系统,其实没啥问题,并且有相当不错的
### 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 和图片等内容,可以自定义它们的访问路径和 URLAstro 会在最终构建的网站结果中予以替换对应的资源路径。但是 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'` 阶段读取所有想要上传的目录,进行上传即可。
这期间对上传逻辑进行了多次重构,第一版使用 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),暂时还无法直接在生产环境使用。
## 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
---
写此文章前,本有一肚子关于清明三天折腾的坎坷想要倾诉。真正写下来的时候,却又没多少。一来是年龄的增长,很多东西不再像以前那么过激。二来,大部分问题基本解决。数数上次更新博客的时间,已经不知道是猴年马月。希望自己在未来的年月里,能笔耕不辍,多记录一点自己的生活。

View File

@ -164,10 +164,3 @@ export const queryLikesAndViews = async (permalink: string): Promise<[number, nu
return results.length > 0 ? [results[0].like ?? 0, results[0].view ?? 0] : [0, 0];
};
export const increaseViews = async (key: string): Promise<void> => {
await db
.update(atk_pages)
.set({ pv: sql`${atk_pages.pv} + 1` })
.where(eq(atk_pages.key, sql`${key}`));
};