◆ プロジェクト内の複数のパッケージで共通のモジュールをロードしたい
◆ それぞれのパッケージ内でモジュールを持つと更新が不便
◆ パッケージ化してそれをローカルインストールで node_modules に入れると便利
  ◆ パッケージ名とそのルートからの相対パスで指定できる
  ◆ シンボリックリンクなので更新は即時反映される
  ◆ 自分のパッケージ内をルートからパス指定したい場合にも使える

共通モジュールを扱いたい

1 つのプロジェクト関連で複数のパッケージがあります
基本はどれも JavaScript で Node.js だったり Webpack や parcel を使ったものです
package.json があるフォルダをルートにしているものです

パッケージごとにインストールするパッケージが別だったりで分けて入るものの一応同じプロジェクトです
なので共通の定数や処理が少しあります

イメージ

- project/
----- client/
--------- client1/
------------- package.json
--------- client2/
------------- package.json
----- server/
--------- server1/
------------- package.json
--------- server2/
------------- package.json
----- batch/
--------- package.json
----- support-tool/
--------- package.json

それをどういうふうに扱うかが迷うところです

パッケージ内に埋め込む

まず 1 つ目の案は パッケージを分けている以上 独立しているものですし パッケージ外の JavaScript ファイルを相対パスでロードするのも気持ち悪いので それぞれのパッケージ内に同じファイルをコピーするというものです
1 パッケージだけ更新とかもできますし これはこれで良い気はします
ただ やっぱり更新が面倒なんですよね
パッケージが増えればそれだけ数が増えますし更新漏れが起きるかもしれません

コピーをスクリプト化しておいても場所が変わったとかパッケージ増えたとかでの手間はあります

node_modules にパッケージ化して配置

そういう面で楽にしようとすると node_modules 以下に共通のデータを export するパッケージを入れるのが向いています
個々のパッケージ内の node_modules に配置すると更新が大変なのは変わらないのでプロジェクト全体ファイルのルートに node_modules を作ります
個別に更新はできませんが 基本的に全部まとめて行うもので 個別に更新したいなんてほぼないのでそこまで問題ではありません
それに node_modules は一番近いものが優先されるのでひとつだけ変更したいならそのパッケージ内の node_modules に変更した版を入れる手もあります

この方法だと いちいち更新する手間はかかりませんしパッケージ名 (node_modules のフォルダ名) で require すればいいので良いこと多めです

ただしデメリットもあって node_modules を npm / yarn を使わずに変更するのはあまり良い方法ではないです
update などのタイミングで package.json に存在しないなら消されてしまいます
プロジェクトルートに package.json を置いて全体で共通のパッケージを入れるわけでもないならここの node_modules は npm / yarn で管理してないので大丈夫とも言えますがあまり気が進みません

npm で管理

問題が npm / yarn で管理してないことならすればいいじゃないと思ったのでローカルからインストールしてみます
共通部分をパッケージ化して package.json も用意します
そのフォルダをプロジェクトのルートに配置して そのフォルダをインストールします

npm install ./common

package.json の dependencies にはファイルスキームで記述されていました
参考までに 普通の npm パッケージで node_fetch もインストールしてみた package.json の中身です

{
"dependencies": {
"common": "file:common",
"node-fetch": "^2.6.0"
}
}

ローカルインストールの対象がプロジェクトのフォルダ外だとそのフォルダも持ってきて同じ相対パスで配置しないといけなくて面倒ですが プロジェクト内であれば気にしなくて済みます
これで node_modules にインストールされたので各パッケージ内では common というパッケージを読み込むだけで共通の定数や処理を使えます

const { app_name, sharedkey } = require("common")

ちなみに ローカルインストールではシンボリックリンク(ジャンクション)が作られるようです
コピーされるのだと同じファイルが被るなぁとか思ってましたが実体は 1 つなので無駄に容量をとったりコピーに時間がかかることもありません
しかも 実体が同じなので変更は即時反映されます
common パッケージ更新したあとに npm update 忘れたなんてことがありません

全体で共通化したいものに限らずプロジェクト内のパッケージは全部プロジェクトルートの package.json にインストールしておけば パッケージ A からパッケージ B のモジュールを使いたいとかあってもパッケージ名とルートからのパス指定で済みますし結構便利かもしれません
パッケージルートに移動するまでに ../ を繰り返すのが苦痛ですからね
別パッケージに限らず 自身のパッケージのルートからのパスを指定するのにも使えます

- common/
----- d1/
--------- d11/
------------- d111/
----------------- foo.js
----- d2/
--------- bar.js

foo.js から bar.js をインポートするとき

require("../../../d2/bar.js)

の代わりに

require("common/d2/bar.js")

が使えます

パッケージ自身を dependencies に加える

これでひらめいたのが自身を dependencies に加えるというものです
上みたいなプロジェクト内にパッケージがいくつもあるとか言う場合に限らず使えます

{
"name": "test",
"version": "1.0.0",
"dependencies": {
"self": "file:."
}
}

これで npm install すると require("self/file.js") のように self を自分のパッケージルートとしてパスを書けます
parcel だと ~ がルートを表すとかありましたが Node.js はまだそういうのがなかった気がします
ES Modules に合わせてその辺の改善もあった気はするものの LTS だと今年秋の 14 くらいでしょうか