◆ シンボリックリンク解決後の実体があるパスを基準にモジュールを探してる
◆ --preserve-symlinks(-main) オプションでシンボリックリンクのままのパスを基準にできる

Node.js は require するときにシンボリックリンクを解決後のパスを基準にしているようです
普段はあまりこういうところでシンボリックリンクを使わないのですが 複数パッケージで同じモジュールを使うところで手抜きで使おうとしたらハマりました

シンボリックリンクとモジュール解決

例えばこういうフォルダ構造があります

/opt/
app1/
a.js
package.json
yarn.lock
node_modules/
app2/
a.js
package.json
yarn.lock
node_modules/

a.js は app1 と app2 の両方で使いたいですが全く同じものでよく 変更するときは両方が変わってほしいです
common フォルダを用意して a.js の本体をここに書き それぞれの a.js は require するだけにします

/opt/
app1/
a.js (require("../common/a.js"))
package.json
yarn.lock
node_modules/
app2/
a.js (require("../common/a.js"))
package.json
yarn.lock
node_modules/
common/
a.js

common/a.js に require がなければこれでも動きますが common/a.js はどのパッケージにも属していないことになり common/a.js から各 app フォルダの node_modules は使えません
common フォルダに package.json をおいてインストールすることもできますが app1 などにすでにインストール済みなのでそっちを使いたいです

シンボリックリンクにすれば楽に対応できるね と思ってこうしました

/opt/
app1/
a.js ---> ../common/a.js
package.json
yarn.lock
node_modules/
app2/
a.js ---> ../common/a.js
package.json
yarn.lock
node_modules/
common/
a.js

これならそれぞれに a.js が実際に配置されてるのと同じ扱いです
しかし動かしてみると Error: Cannot find module 'xxxxx'

モジュールが見つからないようです
エラーメッセージを見ると 「/opt/common/a.js」 を基準にモジュールを探そうとしているようでした
試しに app1 と common に b.js を置いて require("./b.js") でモジュールを読み込もうとすると common/b.js が読み込まれました
node_modules も相対パスもシンボリックリンクを解決した後のパスを基準にしてるようです

シンボリックリンクのまま扱ってほしいのでオプションがないか探すと

--preserve-symlinks
--preserve-symlinks-main

というのがありました
node コマンドに引数として渡すメインモジュールと require でロードされるファイルでオプションが分かれてるようです

node a.js

で実行するなら

node --preserve-symlinks-main a.js

という感じで指定するとシンボリックリンクを解決する前のパスを基準にしてくれて無事モジュールをロードできました

もっと分かりづらい問題になったかも

この例では common に切り分けましたが app2/a.js を app1/a.js へのシンボリックリンクとすることも考えられます
その場合 使おうとしているパッケージは両方の node_modules に入っているはずなのでエラーにはなりません
ですが app2/a.js 内では app1 の node_modules からモジュールがロードされます
実体が違う事による問題が起きるかもしれませんし バージョンが違っているかもしれません

/opt/
app1/
index.js
a.js
node_modules/
pkg0/
index.js
app2/
index.js
a.js ---> ../app1/a.js
node_modules/
pkg0/
index.js

app1/index.js, app2/index.js
const pkg0 = require("pkg0")
const a = require("./a.js")
console.log(pkg0.version, a.version)

app1/a.js
module.exports = require("pkg0")

app1/node_modules/pkg0/index.js
exports.version = 1

app2/node_modules/pkg0/index.js
exports.version = 2

[root@tmp0 ~]# node /opt/app1/index.js
1 1
[root@tmp0 ~]# node /opt/app2/index.js
2 1

Node.js でシンボリックリンクを含むファイルを扱うときは気をつけたほうが良さそうです