Published at

我是如何搭建这个博客的

嗯!2024 年的新博客!

为什么要搭这个博客? #

人们说世界上没有两片一样的叶子。而在世人的眼里也许只能看到那一抹绿,没有人在乎两片叶子之间的细微的差别。对于现代人而言也难逃“我绝不罕有,往街里绕过一周,我便化乌有”,诚然如此。我所爱的,定然也有类似的爱;我所恨的,也不是天下一份。我所想要的,世上定然有一个人和我一样想。所以,同质的想法、重复的话,有存在的必要吗?把别人的话再说一次,那不算是种浮夸、要做大娱乐家吗? 我抱持这种想法很久。要别人完全不一样,要自己出类拔萃,要博人眼球。往往是一番痛苦挣扎之后再胎死腹中。

可我现在想变得不一样了。只是当作对自己普通人生的记录,也是件好事。就写写编程、写写游戏或者是写写玩具,对我这个已经开始常常遗忘万事细节的中年人来说,就已经有纪念品的功效了。“啊,那时候我就喜欢这种幼稚的东西啊。”确是多年后用于怀念的好物件。感谢 IT 技术,也许这种垃圾也能免费保存几十年,要比厚厚一本日记本存续得更好、更久。我确实现在看淡对别人的想法了,真的顾不上,自己开心就好了。

所以,终于有这个博客。

如果抛开框架,一个静态博客应该考虑哪些要素? #

  1. SSG
  2. 最小体积的 JavaScript bundle。要是可以不加载 js 回来,那就完美了。
  3. 图片一定是渐进的

如何选择框架?为什么是 astro? #

  1. astro 更像是 jsx 版本的模板引擎,可组合、有插槽,构建时渲染网页内容。
  2. 在处理复杂交互、模板不够用之时,又可以使用 react/vue 等更复杂的组件,即所谓的 Island。当然可以懒加载、异步加载。非常适合评论、登录这一类的辅助功能。不需要用什么 Server Component,也就不需要超大个头的 react。
  3. 简单,清晰。没有奇怪的封装,比如 GraphQL。啊,对,说的就是你,Gatsby,你坐下。

在 astro 的基础之上,要如何优化细节? #

1. 渐进图片 #

这东西 Google 提了非常之久,现在看已经是很多优秀网站的标配。

本质上是说,在移动端上用小尺寸的图片,桌面端上用大一点的。如果你把图片放大、查看原图,那再去加载原始图片。

CDN #

当然没有什么比 CDN 更能加速图片的下载了。所以我这次使用用了 ImageKit 的服务。对于我这个小破站非常合适,并且:

  1. 免费额度十分慷慨:20GB Bandwidth, 20GB Media storage, 1000 Video processing units, and 500 Extension units.
  2. 功能完备:图片压缩、减裁、格式转化一应具全。
  3. 网络快:我自己的体感上要比 cloudflare image 更快一些,而后者每个月还要 $5 的。
  4. 免费账户随意申请,不要填任何信用卡

良心啊!强烈推荐!

图片体积优化 #

以这张 Unsplash 图片来举例:https://unsplash.com/photos/a-night-sky-filled-with-stars-and-trees-eKbt1g1RT6I

a night sky filled with stars and trees

这是一张原始尺寸 6000x4000px、足足有 11+MB 的超大图片。那么我们在打开博客页面时就把它加载进来,非常浪费流量,也拖累了加载时长。如果浏览者是手持设备,这么高质量的图片,直接展现在页面里也看不到太多细节。这个时候,即使转换到 webp/avif 格式之后也仍然有 2.3MB+ 的大小,还是不够理想。

所以,我们需要把这个图片做尺寸缩小,最好是能根本设备的尺寸来缩小到对应的尺寸。一般来说,移动设备的屏幕宽度在 512px 以内,桌面端就可以大一点。而根据我的博客设计风格,最宽设置成 1024px 就非常足够了。只有当浏览者想要最高质量的图片时,也就是点击图片、查看原图时,给他提供优化格式的原始图片。

这个工作说起来不复杂,可以结合 sharp 等工具可以很容易地完成。但要不说现在日子富裕了呢,我们有更方便的 Image CDN 可以用。专业的图片 CDN 不仅仅提供 CDN 的下载加速能力,还提供非常方便的尺寸调整、格式转换等等能力。前边有提到的 ImageKit 就非常好用。

这里用一个例子概要介绍一下我是如何使用 imagekit 的。比如我们将上边的 unsplash 图片,上传到 imagekit 后可以得这样一个链接:

https://ik.imagekit.io/6mysxbs8t/dcleiaDupYmt9b5gDr93ZvGgStNld9hk8YD0YmTrxQg.jpg

根据 imagekit 的图片优化能力要求,只需要在 appId 6mysxbs8t 后边加上转化指令即可,比如我想生成成一个移动端使用的 512px 宽、webp 格式的图片。那对应的链接就是

https://ik.imagekit.io/6mysxbs8t/tr:w-512,f-webp/dcleiaDupYmt9b5gDr93ZvGgStNld9hk8YD0YmTrxQg.jpg

这张调整后的图片,只有 13KB。目测在移动端上使用是足够的。

响应式加载 #

现在的日子富裕了!DOUBLE KILL!

我们现在有一个新的元素叫 picture。它支持设定多个 source,每个 source 可以搭配一个 media-query

这里有一个来自 MDN 的示例:

<picture>
  <!-- 当 media-query 生效里,使用这个图片 -->
  <source srcset="mdn-logo-wide.png" media="(min-width: 600px)" />
  <!-- 默认加载这个 -->
  <img src="mdn-logo-narrow.png" alt="MDN" />
</picture>

这也就非常简单地实现了移动端、桌面端分别加载不同的尺寸的图片。

懒加载 #

现在的日子富裕了!TRIPLE KILL!

现在,img 元素有一个新的属性 loading。我们只要设定成 lazy 就行了。你的高级浏览器会只在图片被展现到视野里才开始加载图片。赞美技术的进步。

模糊占位图 #

占位图:在网络很差时,它可以临时性地给用户看到一定的内容,以提升体验。它有这么几个特点:

  1. 极致压缩: 这是一个实际尺寸很小(128px宽),并且通过高斯模糊过的图片。所以它的体积一般只有1-2KB。
  2. 直接内嵌:由于它已经非常小了,再发起一个请求不划算。因此直接以 base64 的形式嵌入。

效果如这个图片所示:

image from clipboard

这张图片的原图也在这篇博客中 😆

如何快速把图片上传到 ImageKit#

我花了一点时间,做了一个 raycast 的扩展。当前还在等待扩展的 MR。MR 通过之后大家就可以在 raycast store 中安装它。

这个插件的功能非常简单:

  1. 上传在 Finder 中选中的图片
  2. 上传剪贴板中的图片
  3. 查看上传记录

放上几张截图,一目了然:

上传后的效果图

查看上传记录

插件提供 markdown 图片引入的代码生成,方便直接写入到 markdown 文档里。

image from clipboard

CDN 预热 #

首次访问 CDN 上的图片,肉眼可见的慢。访问过之后,就变得快起来。这是 CDN 原理所决定的。

所以能预热肯定是好的。但是对于我这么一个日均 PV < 10 的小博客做个全球预热真的是太浪费了!为了地球母亲,现在还是省一点。

2. 页面预加载 #

除了第一个落地页面之外,从这个页面出发的其他所有页面,都可以被预加载。具体来说就是在 a 元素上做手脚。a 元素的功能就是在多个页面之间跳转,所以当 a 元素满足被渲染之后,我们就可以把它指向的下一个页面给提前加载回来。当然,这种渲染即预加载有点激进。astro 提供了 4 种预加载策略:

  1. load 页面渲染完成时
  2. viewporta 出现在视野时
  3. hover 当鼠标浮在链接上时
  4. tap 当用户点击 a 链接时

load 最激进,tap 最保守,我比较倾向 viewport。预加载之后,由于对应的 html 已经被 http 缓存住,当真正打开时就会非常迅速。

后续还打算做什么? #

  1. 登录
  2. 评论
  3. mdx 优化
    1. 文章提纲 table of content
    2. code 块优化
      1. copy 按钮
      2. 标题 / 文件名
      3. sandbox:类似于 MDN 上的 playground。大概会接入一个免费的 sandbox 服务。
  4. 搞花样
    1. 放一个 COBE 在页脚上
  5. 接入某个 CMS 体系,发布内容不再需要依赖 astro dev
    1. 方案0: 也许直接在 github 上编辑源码就是一个不错的选择 ⁉️
    2. 方案1: 接入 mak 在线编辑器。这个编辑器会将 markdown 文档发布到 gist。那再通过脚本工具每次构建时,把所有的 gist 拉取到本地再生成页面。或者是直接在 notion 里边写?
    3. 方案2: 由于登录和评论大概会用 supabase,所以把文档内容也放进去,可能是个好选择。