踩坑集合

坑一方面来源于 Next.js,另一方面来源于 Notion API。当然,我自己才是最大的坑。

  1. Next.js 服务端渲染
  2. Notion API 数据过滤
  3. Notion Block 数据渲染
  4. Notion 临时图片过期
  5. Next.js Image 组件使用
  6. Notion 文章页面样式渲染

以上基本就是我踩的所有坑了,在介绍踩坑经验之前,还是简单的说一下项目的初衷。

初衷

最初是因为,我学了前端,然后就想了解后端,最初是做了一个基于 edge-tts 的语音转文字全栈项目 Rotts(前端 React + 后端 Flask),但这个项目很简单,后端基本就是请求 API,获取声音列表,然后将声音、音高、文字等信息传递给 edge-tts,等待声音返回,然后播放/下载就行了。后台感觉还没有怎么体验就感觉结束了。

所以,就想着找另外一个项目,继续学习下后端。首先想到的是 Node.js,调研过程中,看到了很多人推荐的 Next.js,也是基于 Node.js。那就一拍即合,我也想简单造一个轮子,做一个将 Notion 作为 CMS 的博客系统。视觉上一切从简,减少负担,着重于内容的渲染。

本来想着有 ChatGPT,不会的问问他就行了。结果 Next.js App 太新了,他的资料库里都没有,每次问他相关内容都回答的不够准确。

项目信息

  • 名称: Brog
  • 介绍: Next.js 构建,CMS 为 Notion 的简约博客系统
  • 技术栈:React + Next.js + Typescript + TailwindCSS
  • Github:https://github.com/yikZero/Brog

踩坑第一部分 Next.js

重复请求

其实我在刚开始的获取数据的时候,就有疑问,我这边 fetch 一下,那边 fetch 一下。都是相同的数据,会不会多次请求,会很浪费呀?

为了这个,我也一直在将函数功能与请求分离开,传递好几个 props 就行……. 但其实至少在 React 里不用在意这个。

Passing data between a parent layout and its children is not possible. However, you can fetch the same data in a route more than once, and React will automatically dedupe the requests without affecting performance.

如果你 fetch 的链接和参数不变,那么你多次的请求,React 也会帮你合并成一次进行请求。所以也不用一直在组件之间转发 props,你就请求多次相同数据吧,没什么问题。React 会自行合并请求,不会多次重复请求,影响网络。

服务端组件

怎么样算是服务端组件呢,放在 app/ 目录下的应该都属于服务端组件。我不知道是不是服务端组件的时候,我把我用到的 components、lib 文件目录,全部扔到 app/ …… 就为了服务端组件。

想让其变成客户端组件,那就加一个 use client 在顶部,那就会被识别为客户端组件。Next.js 官方推荐能服务端就服务端。

next/image 应用

Next.js 官方因为 LCP performance 的原因,优化了 img 元素的应用,推荐使用官方 Image。

具体使用方法可参照 Image Optimization

我以为会很简单喽,替换个名字就好,但是其要求我提供明确的高度和宽度。我动态获取的图片,我咋知道图片的高度和宽度呢。所以也就使用了奇技淫巧…….也是 stackoverflow 上的方案。

<figure className="relative">
  <Image src={src} width={0} height={0} sizes="100vw" className="w-full h-auto"/>
</figure>

踩坑第二部分 Notion-Client

Notion API

数据获取

Notion 官方有 @notionhq/client,同时 react-notion-x 也有一个 notion-client。我是先了解到的 notion-client ,所以样式写完之后,尝试集成的是第三方实现的。

怎么说呢,notion-client 也挺好,提供一个公开的 NOTION_PAGE_ID 环境变量,即可获取到数据。但是获取到是全量数据,没办法跟官方的 API 一样根据字段名进行筛选的功能,所以整理数据会麻烦很多。这对于我这新手还是麻烦太多了…….毕竟,在 Notion 获取的数据是一层一层套娃的,每一个块都有其 ID,搞得我晕头转向。

最后也还是参考 notion-blog-nextjs 应用的官方 API,来获取到相对应的数据。

图片过期

Notion 官方提供的数据中的图片链接是 Amazon 临时链接,一个小时就会过期。然后就会导致图片挂了。

Vercel Cron: 很多人也会选择使用 Vercel cron 功能,每个小时重新构建渲染一下。但我觉得这也太浪费资源、太不环保了 (:

临时地址转化为永久地址: 方案的话可以参考 fix: solve linked img crash #524

PicGo 上传至又拍云: 因为我迁移过数据,Markdown 图片如果都是相对地址的话,简直是个灾难。所以,我现在就会选择通过 PicGo 上传至又拍云中,返回一个我的 CDN 地址。如果要迁移的话,那至少图片不会丢。