寻求新的工作机会

Next.js 调用 Notion API 记录

Develop·

踩坑集合

坑一方面来源于 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 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 地址。如果要迁移的话,那至少图片不会丢。