avatar

老是作重造輪的事 - 又改了 chat 分站

我知道,莫再提 😂

好一陣子之前,因為一時的心血來潮所以把個人站做了一些修改(這裡就不贅述了,詳情在這邊),當初把比較會經常性更新的 Newsletter 類的文章放到了 https://chat.sylee.dev 那邊,因為希望能以最方便的方式來寫文章,所以選擇了 NotionNext 這個專案,因為它直接對接 Notion,然後佈署到 Vercel 的方法也非常方便,所以就做了這個選擇,現在看起來也的確很適合,所以「網路黑手的呢喃」這個系列才能一直寫到現在還沒斷更。

那到底這篇是又怎麼了😅

其實我還是很喜歡 NotionNext,也對目前這個流程沒什麼太大的意見,不過一切都要從 Next.js 升級開始說起(也就是 NotionNext 4.x),因為升級之後原本提交的一個文章自訂連結的功能,因為改寫之後的架構變成無法實現(作者已經把原本的 issue 改成 discussion 放到這邊了,看起來短時間之內應該不會處理),導致我得把專案的版本定死到某個版本號不能再繼續跟上 upstream 了,這個狀況一開始還沒什麼,不過時間一久,除了一些安全性更新也無法順利的補上,還可能遇到專案版本衝突的問題,所以開始萌生是不是要再找一個其他替代方案。

雖然是想找替代,不過我還是希望維持 Notion 作為 CMS 的類似方案,所以稍微看了下有沒有類似功能的專案(譬如 astro-notion-blogvue-notion),但覺得都沒有很符合自己的需要 ⬇️

所以又走上這條路

最後決定因為近期愛用的 Deno,又撿起他們家出品的 Fresh 來改改看,然後就變成這樣了😂,目前非常陽春的版本只有兩個要求:

  1. 相容原本 NotionNext 的文件格式(為了無痛轉移)
  2. 滿足最基本的文章格式顯示(NotionNext 其實功能非常強大,我也沒打算作 100% 的移植,自己寫文的用途,最早期只要能支援 Notion 格式的正常顯示就夠)。

如果沒聽過 Fresh 是什麼的話,之前「本站改版那篇」有稍微提及,簡單說就是 Deno 家自推的 SSR 框架,所以可以完美相容 Deno 以及 Deno Deploy 的佈署(是的,改版後的 chat 也從 Vercel 改到 Deno Deploy 啦)。

卡關一:支援 Notion 格式的正常顯示

第一個遇到的問題,就是如何「正確地顯示 Notion 的文章格式」,誠如前面提及如 vue-notion 這類的工具,不過找了一輪要不是框架生態圈太小眾,不然就是實作沒那麼完整,所以後來還是回到 React 生態圈,用跟 NotionNext 一樣的解法 - react-notion-x

備註:真的很感謝這位開發者實作了這個套件,幾乎支援了大多數的 Notion 文章格式,還包含了 Notion API client,以及一些資料處理會用到的小工具。比較奇耙的是當初開發的時候應該還沒有 Notion 官方的 API,所以它的客戶端是用 private API 作的,總覺得應該改成正式 API 會比較好,或許可以提個 PR,但我不敢亂立 flag 🤣。

雖然 fresh 是基於 preactjs 不過它相當程度相容 React,所以使用上沒有太大的問題,記得把 react-notion-x 的 redener 實作在 islands 裡面即可。

卡關二:整合 react-notion-x 第三方套件

能夠顯示基本的 Notion 文章格式之後遇到的第二個問題,就是支援推文的顯示,這邊一樣參考 NotionNext 的實作,一樣加上了 react-tweet-embed,也參考了它的實作方式。

不過折騰好一段時間,都沒辦法正常顯示推文,後來一個靈光閃現想起一個關鍵的問題 - ‌套件相依性。因為好一陣子沒好好寫前端的東西,有些東西都忘了。這邊要特別推薦一個好用的工具 - esm.sh,尤其如果你也打算用 fresh 的話。

esm.sh 是一個類似 CDN 的服務,不過它不單只有這個功能而已,他應該說是 Deno 前端開發的必備工具之一。如果對 Deno 有稍微研究的應該都知道,在一開始它們幾乎完全擁抱 modules import 的,所以經常可以看到像下列這種:

import {
  add,
  multiply,
} from "https://x.nest.land/ramda@0.27.0/source/index.js";

不過除了提供像一般 CDN 的功能之外,esm.sh 有一些比較特別的功能,譬如像直接支援安裝 npm、Github 套件、處理相依、支援 worker 等還有很多強大的功能,可以參考文件都有詳細的說明,都可以透過網址參數直接做到,所以後來就是用下列的方法解決遇到的各種問題:

{
    "preact": "https://esm.sh/preact@10.20.2",
    "preact-render-to-string": "https://esm.sh/*preact-render-to-string@6.4.2",
    "react": "https://esm.sh/preact@10.20.2/compat",
    "react-dom": "https://esm.sh/preact@10.20.2/compat",
    "react-notion-x": "https://esm.sh/react-notion-x@6.16.0?external=react,react-dom",
    "react-tweet-embed": "https://esm.sh/react-tweet-embed@2.0.0?external=react"
}

前面提過 preactjs 是相容 react 的,所以記得把相容的部分設定好(其實這邊也可以用 alias 的功能來處理 ⬇️

"react": "https://esm.sh/preact@10.20.2/compat",
"react-dom": "https://esm.sh/preact@10.20.2/compat",    

然後針對那些相依的套件,指定依賴為上述的 react & react-dom

"react-notion-x": "https://esm.sh/react-notion-x@6.16.0?external=react,react-dom",
"react-tweet-embed": "https://esm.sh/react-tweet-embed@2.0.0?external=react",

external 是指拿同專案已存在的其他套件(像 Deno 專案中定義在 import-maps 裡面的其他套件),如果想直接引入相依的其他套件,可以改用 deps=react,react-dom 來處理。

這樣多數問題就解決了,其中還遇到一個支援 pdf 檔案的延伸問題,在 react-notion-x 裡面是放在需要自己額外引入的功能,這部分倒不難處理,因為 esm.sh 也是支援自訂路徑的引入(如下,/build/third-party/pdf 這段),不過還有個比較大的問題是它依賴的 react-pdf 是利用 web worker 來執行的,結果沒想到 esm.sh 也已經支援這個功能了(?worker。😍

"react-notion-x-pdf": "https://esm.sh/react-notion-x@6.16.0/build/third-party/pdf?external=react&deps=react-pdf@5.7.1&worker",

在 Deno 生態中開發前端相關功能,真的不要錯過 esm.sh 這個方便又強大的工具。

結語

之後整理之後會把專案開源出來,如果想使用類似的寫作模式 & 技術棧的話可以試用看看。之後應該還會有一些待作事項,不過我怕因為不影響一般發文,就沒動力繼續了😅,目前想到的有:

Flag 不要立太多先這樣就好,說不定也根本不會進行...哈。

所以歡迎大家繼續來 https://chat.sylee.dev 恰特

by 手癢的老站長 😁

powered by WebMention.io

You can skeet this post or discuss it on BlueSky, the comments will show up here.
0Likes0Replies0Mentions

Be the first one to share this article!