这个网站是如何构建的

使用方式

本站源码完全公开:GitHub - la3rence/site.

直接将 Markdown 文件 (.md) 存放在 posts 文件夹下即可渲染当前文件,使之成为静态页面(SSG)。 博客的首页索引目录也为同步生成,而无需手动维护。

About 页面也同理基于 readme.md 文件生成而来。

博客相关的信息配置,如标题、作者等可在 lib/config.mjs 文件中配置。

推荐使用 pnpm 来作为 node.js 的依赖管理工具(相比官方 npm,pnpm 拥有非常大的优势: 速度更快,且节省空间)。

pnpm install
pnpm dev
 
# [Optional] install turbo via `pnpm i -g turbo`
# and you can try `turbo` for run any script in package.json like:
turbo dev
turbo build

本地访问 http://localhost:3000 即可。

通过 pnpm build 来打包,pnpm start 则用于生产环境的启动。 通过 pnpm fmt 来将所有代码和文本进行格式化。

这篇文章展示了此博客项目所能展示的一切媒体信息,比如代码引用、表格展示、图片、视频、豆瓣卡片等等。

2024/07 更新:

  • 顶部导航栏启用毛玻璃动态悬浮
  • 全新的 edge to edge 设计风格,充分利用屏幕区域展示代码和图片

技术细节

此站点由 Vercel 公司开源的 Next.js 框架和 TailwindCSS 样式构成。前者是一项基于 React 的 SSG/SSR 开源项目,后者是一个目前流行的原子化 CSS 库,让不太会写 CSS、基础薄弱的我也能快速的写出灵活的样式。

Next.js 会主动调用我们写好的一些函数 (getStaticProps()),让组件得到数据的输入,从而在构建阶段将 React 组件提前渲染完成。remark 库可以将原生的 markdown 语法编译成 html 对应的 dom - 在此项目中,我们让它固定遍历 posts 文件夹下的 markdown 文件,依次编译,让其作为 [id].js 的动态路由页面的 props,从而渲染出博客文章:

export const getStaticProps = async context => {
  const { id } = context.params;
  const mdData = await getMdContentById(id);
  return {
    props: mdData,
  };
};
SSG in '[id].js': fetch data in build time

这样做的好处很多:

  • 适合被 CDN 缓存
  • 优秀的 SEO 表现
  • 节省网络带宽、流量
  • O(1) 时间复杂度的 TTFB

总之一个字,快!如果你尝试关闭当前浏览器的 JavaScript 功能,这个网站也一样能正确渲染并展现。

不光如此,Next.js 也提供了服务端渲染的能力,同样也能带来较好的 SEO 体验,不展开说了。

上述这种技术被称之为 JAMstackJavaScript, API & Markup.

一种有趣的说法是,JAMstack 是 CDN 优先的应用程序。

It's now possible, instead, to push content directly to the network and design frameworks that optimize for this capability. As a result, with optimizations like static asset hoisting, websites are now becoming faster and more reliable than ever before.

Movie

你可以编写特定的 React 组件来让 Markdown 支持更丰富的页面内容,这种实现方式和 MDX 类似。 The source of this component is coded via react component in markdown!

Code:

// filename: how.md
<div>
  <douban id="3042261"></douban>
<div>

Result:

Images

Random Image
Random Image

Video

可以直接通过 <bilibili /> 组件展示来自于 B 站视频,基于 iframe.

Tweet / 𝕏

<tweet /> 组件展示推文:

Open Graph

Open Graph (OG, 开放图谱协议) 用于社交网络分享网页时展示特定的富媒体信息。

Open Graph
Open Graph

Tables

JAMstack.

ROLEPROVIDED BY
JClient-side JS injected via React Hooks (state, event listeners, effects)
AAPI pages inside the pages/api directory.
MPages with no data dependencies or pages with static data deps that trigger build-time static site generation.

GitHub Gist

export default function compare<T>(a0: T, b0: T): number {
if (a0 === b0) return 0;
if (a0 > b0) return 1;
return -1;
}
view raw gist-test.ts hosted with ❤ by GitHub

WebSub for RSS

基于 GitHub Actions 来支持 WebSub 标准,即之前的 PubSubHubbub。这使得支持 WebSub 的 RSS 客户端不仅能立刻获取到新文章,也能减少客户端和服务端之间的轮询次数以及流量。细节: site/issue/324.

ActivityPub

网站通过最基本的一些 ActivityPub 和 WebFinger 协议部分实现了与联邦宇宙的交互。实现细节

I18n

网站通过简单的配置以支持国际化。通过 markdown 文件名的中间后缀来和 Next.js 原生 locale 路由来实现区分语言类型展示不同文本。

And more to do

Markdown 目前采用 GitHub Flavored Markdown (GFM) ,并尝试添加新的语法元素支持。

例如:https://github.com/orgs/community/discussions/16925

[!NOTE]
Critical content demanding immediate user attention due to potential risks.

Ref 参考链接