4

digital envelope routines::unsupported

 9 months ago
source link: https://blog.othree.net/log/2023/09/15/digital-envelope-routines-unsupported/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

digital envelope routines::unsupported

Node.js 16 LTS 已經結束維護,所以手上的東西就開始需要升級升級,然後就必須要來正面面對這個我逃避已久的錯誤訊息:

digital envelope routines::unsupported

這錯誤基本上就是發生在幾個網站的專案,尤其是 build 專案時特別會容易看到,而且這個錯誤其實和一般看到的 JS 錯誤長得不太一樣,全貌其實是這樣:

digital envelope routines::unsupported
Error: error:0308010C:digital envelope routines::unsupported

首先是錯誤訊息,前面有一些 hex 值,不知道是什麼,然後下面 trace 的地方,可以看到幾乎都是 node_module 內的東西,不是因為我們自己的 code 造成的,所以就很讓人困惑,想說是不是什麼系統問題、還是有什麼偷用非公開 API 造成不相容的狀況。總之以前就是遇到這個問題就是又降版回來,沒有仔細深究,這次終於要來認真處理,不過搜尋結果,幾乎都是說加一個--openssl-legacy-providerflag,都沒人說到底是什麼問題,尋找許久,終於在 StackOverflow 找到一則最正確的答案,沒想到和 OpenSSL 1.x 的生命已經到盡頭有關。

結果這個錯誤,其實是因為 Node.js 17 開始,從 OpenSSL 1.x 換到 3.x,然後 OpenSSL 3.x 不是向下相容的,所以有些東西有機會出錯,這邊爛掉的,其實是一些 legacy 的 hash method 預設是拿掉的,而 Webpack 在建立 bundle 檔案時,如果檔名有用到 hash 的話,預設的 hash method 用的就是已經被淘汰的 md4,然後 md4 是用 Node.js 的 crypto 來呼叫 OpenSSL 做事,Node.js 的文件也有提到支援的演算法是依據你的 OpenSSL 版本和系統而定,所以其實並沒有保證 md4 一定可以用,而如果使用了 OpenSSL 不支援的演算法,跑出來的錯誤訊息就是像上面截圖一樣特別了,然後我還特別去用 OpenSSL 3 cli 跑跑看,結果出來的錯誤訊息真的就是差不多:

OpenSSL 3 error

使用 flag 開啟舊演算法的支援其實我覺得還算可以接受,畢竟是 build 而已,不是拿來跑服務,不過這個 flag 似乎有點特殊,似乎不能直接放在NODE_OPTIONS裡面,而且同個程式庫要是拿到舊版 Node.js 環境去跑,加這個 flag 反而跑不起來,所以最理想還是把問題解決掉。

那這個問題應該怎麼處理呢?其實簡單說就是把套件升級升級就好了,因為現在的套件新版本都有處理這個問題,不過走上升級這條路之前可以先試試看 StackOverflow 上的解法(有可能讓你專案爛掉,請先備份):

npm audit fix --force

如果你用的是 yarn,沒有audit fix可用,但是也有人提供用 npm 來修理的流程,不過我是沒試過這個流程,我自己有一個專案是靠yarn upgrade升級後解決問題的(實際上是把所有有用到的 loader-utils 都升級到 2.0.4,本來有個套件用到 2.0.0),剩下的還是無法修好的就要靠手工了,然後因為我處理的網站只有 Gatsby 和 CRE(Create React App) 兩種,所以以下就是只有說明這兩個系統的為主,兩者其實都是使用 Webpack 作打包工具的,而 Webpack 是從 v5.61.0 開始保證支援 Node.js 17 的,我稍微查了一下 Gatsby 是從 4.2.0,而 CRA 的則是要最新版 react-script 5.0.1 才保證支援,為什麼說是保證呢?因為^的 semver range 的關係,例如要是你的 react-script 是 5.0.0,那你本地可能會是裝到 Webpack v5.60.0,那就不支援 Node.js 17 了,像我就是有 Gatsby 3.x 的,升級到 4.x 就沒事了。

Gatsby 和 CRA 其實都還好,最慘的是 eject 過的 CRA 了,只能手工升級,基本上就是去 react-script 那邊,複製需要的檔案回到你的專案覆蓋過去,最主要的是scripts/config/下的檔案,然後根據自己的修改紀錄把自己作過的修改改回去,接著更新package.json裡面的 dependencies,版本號就是參照 react-script 那邊的 package.json,最主要的就是webpack相關的,接著安裝套件後重新 build,要是還有一樣的錯誤,就看 trace 看看是哪個相依套件,看有沒有新版有修正就更新試試看,大概就是這樣,很容易漏東西所以會一直重複測試,蠻花時間的,不過最後 build 成功還是有成就感的。

PS. 還要小心其他升級的後遺症,如果是 app 最好要測試過各種行為,像我遇到 Webpack 5 不支援 polyfill Buffer 的問題,剛好那個錯誤又被 catch 掉,所以我 build 是沒問題的,就是測試跑不過,後來參考網路上的文章處理。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK