主页关于链接归档相册

自用 Next.js 博客程序之随便扯扯

记录

简单写篇介绍文,给期末作业做准备。


因为面向路人的关系,不扯什么简单的 CSS 设计和类似 PJAX 之类的了。

基本信息

项目已开源至 Github:Cesirdy/next-blog

首先使用了如下项目:

  • Next.js
  • Tailwind CSS
  • React

设计理念之没有设计就是最好的设计,毕竟本质是写文章的地方,不搞什么二次元花里胡哨的影响阅读的设计,同时尽量实现较高的性能。
PageSpeed Insights 性能报告说 100 分,但是整体资源大小比较大,只能说遗憾。

不讲样式和 UI 设计这种基础,目前实现了如下功能:

  • Markdown 文章解析
  • 简单的文章排版优化(基于 @sofish 的开源项目 typo.css)
  • 文章内目录跳转(自动检测文章内所有标题并生成)
  • 文章内图片懒加载并自动优化格式 & 同站链接预加载(兼容自 Next.js 自带组件)
  • 评论组件(Disqus X DisqusJS 并懒加载)
  • 代码高亮
  • 分类 & 归档功能(带有分类过滤)
  • 深色模式(带缓存记录)
  • 独立页(与文章页实现方式一样)
  • 链接页
  • 导航栏
  • 移动端自适应
  • Sitemap(借助插件)和 RSS(脚本生成)

文章生成

类似 Hexo 等静态站点生成器的思路,本地写文章(文件形式)并通过程序生成为一个完整的站点。

流程大致是:

  1. 写文章
  2. 处理文章信息
  3. 生成为 JSON + HTML
  4. 部署

大概就是这样吧:

+---------+        +--------+           +--------+  Build    +-------+
| Sources | -----> | Github | --------> | Vercel | --------> | Pages |
+---------+  Push  +--------+  trigger  +--------+  Deploy   +-------+

一般主流都是只生成 HTML,但是 Next.js 可以同时生成包含文章信息的 JSON。
直接通过链接访问页面时会加载 HTML,在这之后通过页面内点击访问其他页面,会加载 JSON,通过 JSON 的内容来动态修改页面,从而减少用户加载开销。
也就是不用每次访问其他页面都加载一整个 HTML 以及其包含的需要加载的 JS 和 CSS。

生成的 HTML 中,首页展示最新 5 篇。
归档页展示所有文章,可以根据文章分类选择性展示特定分类的文章。

文章采用 Markdown 格式并通过 next-mdx-remote 这个库解析展示,只能说好用。
排版修改自 @sofish 的开源项目 typo.css,主要修改了一些符合个人喜好的东西。
像代码高亮及目录也是提升阅读体验的一环。

next-mdx-remote 默认会将图片和超链接直接解析为 HTML,但是可以通过 components 将其解析为 Next.js 自带的图片和链接优化组件。这部分还是挺简单的。

样式

样式部分没有采用传统的 CSS 实现方式,而是使用了 Tailwind CSS。
一般来说,一个网站越复杂,样式也就越多,CSS 文件也越大,维护难度也会提升。
而近年以 Tailwind CSS 为代表的 ​Atomic CSS​ 也逐渐火了起来。

简单来说,​Atomic CSS ​是一种 ​​CSS​​ ​编程思路,它倾向于创建小巧且单一用途的​ class​,并多次复用。 简单的例子:

<style>
  .text-white { color: white; }
  .bg-black { background-color: black; }
  .text-center { text-align: center; }
</style>

<div class="text-white bg-black text-center">hello Atomic CSS</div>

看到以上的示例,可能很快就想到,直接使用行内样式不是更好吗,还省去了 ​Atomic 类的定义。这个问题可以从样式编写、一致性、功能和缓存四个方面来回答。

在样式编写方面,​Atomic CSS 可以充分利用 CSS 预处理器和后处理器进行样式编写,而行内样式缺乏成熟的工具支持和维护。
在一致性方面,​Atomic CSS 框架通过预定义的设计系统实现一致性,而行内样式和传统 CSS 类定义的可选值没有限制。
在功能方面,​Atomic CSS 支持媒体查询和状态处理,而行内样式缺少这些功能。
在打包方面,​Atomic CSS 样式定义和 JS 逻辑分离,修改元素的 class 属性通常不会影响最终打包输出的样式文件,而行内样式的修改会导致整个 bundle 的改变。

与此同时,很容易也能想到:样式越多,复用的几率也就越大。因此使用 ​Atomic CSS 通常可以得到一个相比之下较小的 CSS 文件。
使用 Atomic CSS 相较于传统 CSS 方法,CSS 产物大小与项目复杂程度和组件数量之间的关系不再是线性正相关。随着组件数量的增加以及可复用的 CSS 规则增多,最终的 CSS 产物大小与项目复杂程度呈对数关系。 大小对比 目前博客的 CSS 经过压缩传输后仅有 2.5 kB,而之前使用传统 CSS 编写的旧博客则高达 6.2 kB,实际不经过压缩的原尺寸更大。

深色模式

至于深色模式,则是为了美观牺牲了一定功能性。

目前采用的方案是:

  1. 首次加载,检测用户系统设置偏好,即是否为深色模式
  2. 将用户偏好计入浏览器缓存,并通过 CSS 的 @media 设置样式,同时修改 HTML 类名。
  3. 用户点击切换按钮后,通过修改类名以实现应用不同样式。
  4. 二次访问,查询浏览器缓存并应用样式,以此实现记忆用户偏好功能。

同时也会查询缓存并在按钮上应用样式以提示用户目前的模式,比如有个蓝色下边框。嗯。

评论

国内在多年前,大概是 2016 年左右,是有“多说”这家第三方评论系统的,但是倒闭了。
后面只能说没有“多说”这么好用的了。
秉承着白嫖还要稳定的原则,没有选择各个自建评论系统的方案,选择了 DisqusJS 的方案。

DisqusJS 的反代目前是使用了 Vercel,但是国内的访问速度也还是欠佳。只能说勉强能用。

然后做了个简单的懒加载,点击按钮才会加载对应组件,毕竟 Disqus 还是挺臃肿的。

杂项

一些杂的简单提一嘴,不展开了。 返回顶部使用了最简单的锚点,毕竟能用越少的 JS 越好。至于这个平滑的返回顶部可以阅读往期文章:《关于页面滚动的两个 CSS 属性》
链接页尝试性地使用了 grid 布局,相当不错。 文章信息的处理比较弱智,目前不知道对性能有没有影响。 像 RSS 和 Sitemap 这两个,只有 RSS 的通过文件生成感觉还算比较优雅。

the end.