為什麼不該更新 discord.js v14?踩坑經驗「這三點」聽完再決定!
•2023年1月22日
discord.js 是一個在 Discord 上開發機器人的 JavaScript 框架,因為他簡單且強大的函式庫,讓入門開發者能快速的製作出穩定的機器人,而同時也因為這些方便而損失了很多性能上的優勢,我們將會來逐一探討。
前言
還記得剛開始摸索的時候是在 2019 年的樣子,那時候 Google 上壓根沒什麼中文的 Discord 機器人教學,亂翻看到了一篇在講 discord.js 的文章,就此掉入了這個大坑裡面,
後來機器龍在疫情線上上課那時候大爆炸才開始意識到這些嚴重性,每天跟穩定性戰鬥,還好在那時候也有救星的出現,我們最下面的章節將會談到除了 discord.js 還有 其他的選擇。
所以是為什麼?
機器龍的精神食糧
以下是我踩坑了挺多次總結出來的問題點,比較屬於我個人的意見,可能每個人的感受也不會相同,看完了再來決定要不要使用 discord.js,或是也可以直接跳去看 我該繼續用 discord.js 嗎?:
大更新像是抄家一樣
人都是有惰性存在的,而使用 discord.js 絕對可以讓你改掉這個壞習慣,我們知道這個套件有許多貼心幫你包好的如 avatarURL
、awaitMessageComponent
函式,好用歸好用,不過遇到 discord.js 大更新時你就得開始忙起來了,
到文章撰寫的時候 discord.js 已經更新到了 v14,我們可以翻閱一下從 v13 更新到 v14、v12 更新到 v13 的文件,看到側邊欄的目錄超過整個頁面的長度,我覺得我還是去躺好好了...
雖然開發團隊在 Discord 伺服器中提及到 v13 版將會繼續支援,並且還沒有訂定該版本的結束週期 EOL (End-of-life),但可以確定的是,這個版本終將會被棄用,還是必須要進行痛苦的轉移過程。
機器龍的精神食糧
不過他們的其中一位開發者 McSquiddleton 在一篇 Reddit 文章 When should I upgrade to V14? 中指到:
「因為 Discord 將棄用舊版的 Gateway 格式,於是我們推送了 v13 更新,而 v13 升級到 v14 只是一些命名上的更改。」
不過這部分可能每個人的看法不同,如果你很喜歡 discord.js 並且想要避免每次大更新都要重寫一次,可以將大量使用的函式包一個自己的版本,我們拿 User#avatarURL
來舉個例子:
這樣每當大更新時只需要更改自己包的版本就好了,剩下的時間拿來多打點 APEX 也不過分。
快取無法更動
discord.js 完善的快取系統在普通的小量使用上確實是挺方便的,不過在規模越來越成長下,越需要去注意到記憶體的控管,是不是可以努力減少一些不必要的快取,
而 discord.js 的快取在預設都是無法更動的,雖然有提供了 Options#makeCache
的選項,不過在文檔中說明到 GuildManager
、ChannelManager
等核心的功能還是不能被覆寫,像是頻道、身分組及表情符號是最占用記憶體的前幾名,這樣還是令人堪憂。
機器龍的精神食糧
discord.js-light
幸好有人發現了這個問題並製作出 discord.js-light 套件,可以直接覆蓋掉幾乎所有的 Manager 設定,不過因為還是第三方軟體,並不是 discord.js 自帶功能,最好在使用之前注意會不會讓程式崩壞。
我自己有發現了一個神奇但是挺好用的解法,可以直接使用 JavaScript 神奇的 ProtoType 特性,
舉個例子:若你發現你真的不會使用到 ChannelManager#cache
裡的東西,先將 bot.channels
的 set
函式清空,需要用到時使用 ChannelManager#cache
的原型 Map
來執行 set
的工作,
可以看到機器人在準備完成後,預先快取的頻道數量是 0
,而當我們需要手動抓取頻道的時候,使用 resolveChannel
函式去手動執行快取的操作,雖然這不是個最佳解,不過 JavaScript 是個神奇的語言所以... 恩!
機器龍的精神食糧
機器人規模成長後難維護
當機器人成長到一定的大小後,如何架構將是一個重要的課題,架構層面我們先從如何做解耦 (decouple) 開始,可以把它簡單的理解成兩個元件要如何做拆解,詳細的架構說明可以參考 Day 23: 元件原則 — 耦合性 by JC。
Discord 機器人通常可以拆解為 Gateway 和 Discord 溝通或是接收 Discord 的事件,REST API Proxy 執行發送訊息等操作,而到我最後使用 v13 版本時,所有功能還是都包在一起的,可能他們有在嘗試做一些改變不過我不太確定。
緊耦合對維護來說非常困難,機器人在上線時會依照伺服器數量來分配分片 (Sharding) 的數量,每個分片上線都要先等待五秒的冷卻時間,若每次更新需要重開時,都需要經過一次這樣的上線流程,
而造成的下線時間 (Downtime) 十幾分鐘可是對穩定性和可靠性非常大的致命傷,可以看我們 Google 搜尋結果都可以被洗成這樣了...
那我有其他的選擇嗎?
Create-React-App 在過去是個很棒的 React 工具,用簡單的 react-scripts
指令就可以跑起 React,而不用擔心後面 babel、webpack 繁雜的設定等等,
機器龍的精神食糧
而在時代不斷的更迭到了現在 2023 年,我們有了更多如 Vite、NextJS 等的新選擇,在速度與可擴展性上都有大幅的提升,從前端框架的現象我們也可以來觀察一下,JavaScript 是否還有其他解決方案來製作 Discord 機器人。
先看一下函式庫比較圖表
Discord API Library Comparisons 這網站統計了大多數用來呼叫 Discord API 的套件,我們將會專注在套件的支援程度上面,
可以看到除了 discord.js 之外,其他套件也不惶多讓,下面將來講一下我們觀察到的結果。
Discordeno
Discordeno 是使用 Deno 編寫的 Discord API 套件,並且在 NodeJS 也可以使用,從他們的 GitHub 首頁來看,上面列舉了許多讓人心動的優勢,讓我們能夠信任並且把機器龍轉移過去:
零下線時間
在我們前面有講到的元件之間的耦合性問題,Discordeno 允許我們將 REST、Gateway 分開來部屬,這樣當我們有要推新功能時,就不用去重啟整個架構,達成幾乎完全沒下線時間 (Zero Downtime)。
蓋掉你不喜歡的東西
Discordeno 使用函式化 (Functional API) 的概念來設計,終結掉物件導向錯綜複雜的繼承等關係,並且在閱讀上也非常的簡單,
還有如前面提及到快取的問題,Discordeno 的一切都是可以被覆寫的!例如我希望快取存放在 Redis 上,或是我不需要快取表情符號,你都可以透過覆寫預設的函式來達成效果,有非常好的彈性。
不過不太建議去過度的覆寫 Discordeno 內建的函式,還是使用上面自己包一個函式出來,這樣在未來可能有大更新時會比較輕鬆。
缺少教學文件
雖然說這是個很美好的框架及架構,不過因為目前使用者及開發者人數還沒有達到如隔壁 discord.js 那麼熱門,因此許多東西需要去翻閱原始碼直接了解怎麼運作,可能對新手來說會是一個比較大的負擔,不過你終究都要用的,那為什麼不一開始就用。
而網頁上列舉到的套件我們還沒有去實際體驗過,因此還沒有來得及寫心得,各位有想法想補充也可以到點選右邊編輯此頁面的按鈕,來幫我們補充。
我該繼續用 discord.js 嗎?
discord.js 在活躍的社群及各位開發者的努力下,API 覆蓋率將近 100%,相信之後將會進續演進的更好,若期待之後的演變,可以繼續跟隨 discord.js 的腳步,若你已迫不及待的想要做出更多的優化或改變,或許這篇文章是你的契機可以開始尋找適合你的新套件。
機器龍的精神食糧