Node.js找不到模組?在npm-link底下的處理方法 / How to Handle "Module not found" Error from Modules installed from npm-link?
Node.js的專案不可或缺的就是豐富的套件。為了避免各個專案重複安裝套件而佔用硬碟大量的空間,我會選擇將套件安裝在全域目錄(global),然後用連結(symlink)的方式放到各自專案底下。這種安裝方式可以透過npm-link的「npm link <package-name>」或是@pulipuli.chen/npm-link-better套件的「nls <package-name>」來安裝。
然而,如果全域目錄的套件經過更新、移除、漏洞修復的話,很可能導致專案底下用npm-link連結的套件會發生「Module not found」錯誤。這時候要先用「npm -g i <package-name>」更新全域目錄的套件、移除專案內的套件連結、最後再重新連結套件。
「找不到模組」的問題 / Error "Module not found"
正要打開專案、啟動伺服器與Webpack、開始工作時,結果console居然跑出了錯誤訊息:
ERROR in C:/Users/.../AppData/Roaming/npm/node_modules/...
Module not found: Error: Can't resolve 'sortablejs' in 'C:\Users\...\AppData\Roaming\npm\node_modules\...'
當時我第一個反應是:我有用到sortablejs這個套件嗎?我記得並沒有這回事。讓我更仔細的看看這個錯誤訊息:
ERROR in C:/Users/.../AppData/Roaming/npm/node_modules/vuedraggable/dist/vuedraggable.common.js
這邊可以注意到兩件事請:發生錯誤的檔案是位於npm的全域目錄底下。在Windows 7中,npm的全域套件會安裝在「%USERPROFILE%\AppData\Roaming\npm\node_modules」底下,其他作業系統的目錄位置請參考「Where does npm install packages?」這篇的說明。
另一件事情是發生錯誤的套件名稱為「vuedraggable」。我的確有用到這個套件,而且我還是用@pulipuli.chen/npm-link-better套件,以npm-link連結的方式安裝。
好,現在我們知道是「vuedraggable」出問題了,我們要怎麼處理呢?
修復問題 / Fix error
要修復以npm-link安裝在專案底下的「vuedraggable」出現的「Module not found」問題,我們有三個步驟要進行:
1. 重新安裝全域套件 / Reinstall global package
首先我們先執行重新安裝套件的指令。npm套件的安裝「npm i <package-name>」。因為vuedraggable套件是安裝在全域目錄,所以指令還要加上「-g」。完整指令如下:
npm -g i <package-name>
我們要把<package-name>替換成我們要安裝的套件vuedraggable。
2. 移除專案內的套件連結 / Remove package symlink in project's node_modules folder
有時候前述的重新安裝會造成專案內的套件連結失效。我們需要再重新建立專案中的套件連結。
接下來我們到專案內安裝套件的目錄「node-modules」中,找到欲修復套件的目錄,例如這次要修復的「vuedraggable」。如果你從這裡要進入該目錄的時候發生了錯誤,那就表示這個連結失效了。
請刪除這個目錄,然後繼續下一步吧。
3. 重新連結套件 / Create symlink to package
再來就是重新用套件連結的指令來建立連結,指令如下:
npm link <package-name>
這時候回到專案,重新執行會用到該套件的指令時,應該就不會再出現找不到模組「Module not found」的錯誤了。
結語 / In closing
我把這篇的做法整理到@pulipuli.chen/npm-link-better套件裡面。未來也可以用以下指令來重新連結:
nls -U <package-name>
不過老實說,我不確定這是不是最佳的做法。對於Node.js這塊領域,我還有很多需要學習的地方。最後來講講一些其他的事情:
為什麼會發生錯誤? / Why "Module not found" occured?
我並不是完全瞭解這背後的原因,但我推測有兩個可能性。一個是發生在安裝AdonisJs套件的時候,另一個是執行「npm audit fix」的時候。
我在「Node.js前後端CORS網頁應用試作:AdonisJs聊天室」這篇有提到我開始使用了AdonisJs框架。雖然AdonisJs預設安裝只需要執行「npm i -g @adonisjs/cli」,但這只是基本功能而已。如果要用到其他功能,例如File Storage的@adonisjs/drive、WebSocket的@adonisjs/websocket,那就需要再執行安裝套件的指令。
然而,執行這個指令之後,「Module not found」的錯誤就層出不窮。
(圖片來源:HTMLHint)
另一個可能性是在執行「npm audit fix」之後。npm會自動檢查套件的版本,挑出有安全性漏洞的危險版本,告訴開發者記得要用「npm audit fix」來修正它。根據npm-audit的說明,這個指令將有安全性漏洞的套件更新到穩定的版本。有時候單純執行「npm audit fix」並無法成功,需要改成「npm audit fix --force」才行。
不過,在執行這個指令之後,好像就很容易遇到「Module not found」錯誤。
我不太確定背後運作的詳細細節,這兩個只是我觀察推測的原因。希望大家可以幫我解釋一下。
為什麼是npm-link? / Why install package with npm-link
對於大部分開發者來說,大家好像比較少人在用npm-link安裝套件。對我來說,比較常用npm-link的原因在於我會使用Chromebook開發,而Chromebook的儲存空間相當的少,就連重複套件所佔用的空間都不夠用,所以我才會使用npm-link、讓各個專案都用全域目錄中的套件。
然而用到現在,我的Chromebook連開發用的套件都裝不下了,Electron實在是太佔空間。儘管如此,我那臺只有32GB的Chromebook已經使用了一年了,市面上擁有64GB儲存空間的Chromebook仍然未成主流,只有在中、高階機型才有出現,例如Pixelbook Go。
那麼,這次關於「Module not found」問題的處理方法就講到這裡了。寫到最後,我有些問題想問問大家:
- 你有遇過Node.js模組安裝的問題嗎?
- 你遇到的是什麼問題呢?
- 你是怎麽處理它呢?
歡迎在下面的留言處跟我們分享你的想法。大家的意見是我繼續分享的動力喔!如果你覺得我這篇實用的話,請幫我在AddThis分享工具按讚、將這篇分享到Facebook等社群媒體吧!
感謝你的耐心閱讀,我是布丁,讓我們下一篇見。