[Monoepo] Symlink

2024-04-12 hit count image

JavaScriptで開発するプロジェクトでモノレポ(Monorepo)を使用するための知識であるSymlink(Symbolic Link)について説明します。

概要

モノレポで色んなモジュールの依存関係を連結する時、Symlinkを活用します。今回のブログポストではモノレポを理解するための基本知識であるSymlink(Symbolic Link)について説明します。

ブログシリーズ

このブログはシリーズで制作されています。次のリンクを通じて他のブログポストも確認してください。

SymlinkSymbolic Linkの略で、ファイルまたはディレクトリに対するショートカット(System shortcut)と考えれば良いです。

Symlink は主要 OS(macOS, Windows, Linux)でサポートする基本機能です。また、NodeJSのパッケージマネージャーであるnpmyarnでもサポートしています。

例題

npmyarnが提供するSymlink機能を確認するための例題を作ってみましょう。まず、次のようなフォルダとファイル構造を作成します。

.
└── src/
    ├── module-a/
    │   ├── index.js
    │   └── package.json
    └── module-b/
        ├── index.js
        └── package.json

module-apackage.jsonは次のようです。

// src/module-a/package.json
{
  "name": "module-a",
  "version": "1.0.0",
  "main": "index.js"
}

module-bpackage.jsonは次のようです。

// src/module-b/package.json
{
  "name": "module-b",
  "version": "1.0.0",
  "main": "index.js"
}

そして、module-bindex.jsは次のようです。

// src/module-b/index.js
console.log('module-b');

最後にmodule-aindex.jsは次のようです。

// src/module-a/index.js
console.log('module-a');

require('module-b');

このようにファイルを構成した後、次のコマンドを実行してモジュールを読み込めるか確認します。

node src/module-a/index.js

すると、次のようにエラーが発生することが確認できます。

module-a
node:internal/modules/cjs/loader:1073
  throw err;
  ^

Error: Cannot find module 'module-b'
Require stack:
- /Users/deku/temp/temp/src/module-a/index.js
    at Module._resolveFilename (node:internal/modules/cjs/loader:1070:15)
    at Module._load (node:internal/modules/cjs/loader:923:27)
    at Module.require (node:internal/modules/cjs/loader:1137:19)
    at require (node:internal/modules/helpers:121:18)
    at Object.<anonymous> (/Users/deku/temp/temp/src/module-a/index.js:3:1)
    at Module._compile (node:internal/modules/cjs/loader:1255:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1309:10)
    at Module.load (node:internal/modules/cjs/loader:1113:32)
    at Module._load (node:internal/modules/cjs/loader:960:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:83:12) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [ '/Users/deku/temp/temp/src/module-a/index.js' ]
}

Symlink機能を確認するためmodule-bフォルダに移動します。

cd src/module-b

移動した後、次のコマンドを実行してSymlinkを使う準備をします。

npm link
# yarn link

その後、module-bを使ってるmodule-aフォルダに移動します。

cd ..
cd module-a

module-aフォルダに移動したら、次のコマンドを実行してSymlinkを作成します。

npm link module-b

このようにlinkコマンドを実行すると次のようにmodule-aフォルダのnode_modulesフォルダが生成され、modules-bSymlinkが生成されたことが確認できます。

.
├── index.js
├── node_modules
│   └── module-b -> ../../module-b
└── package.json

このSymlinkフォルダはmodule-bをコピーしたのではなく、module-b自体と連動しています。そのため、src/module-b/index.jsファイルを修正するとsrc/module-a/node_modules/module-b/index.jsファイルも同時に修正され、逆にsrc/module-a/node_modules/module-b/index.jsファイルを修正するとsrc/module-b/index.jsファイルも同時に修正されます。

次はプロジェクトのルートフォルダ(/)に移動した後、次のコマンドを実行してモジュールを読み込めるか確認します。

# cd ../..
node src/module-a/index.js

すると、次のように問題なく実行されることが確認できます。

module-a
module-b

次はsrc/module-b/index.jsファイルの内容を次のように修正します。

console.log('module-b!!!!');

修正した後、src/module-a/node_modules/module-b/index.jsファイルを開いてみると修正した内容が反映されていることが確認できます。もちろん、次のコマンドを実行すると修正した内容が表示されることが確認できます。

node src/module-a/index.js

module-a
module-b!!!!

完了

これでモノレポを使うための基本知識であるSymlinkについて説明しました。モノレポで色んなモジュールの依存関係を連結する時、Symlinkを活用するので今回のブログポストを通してSymlinkを理解しておくとモノレポを使うのに役に立つと思います。

私のブログが役に立ちましたか?下にコメントを残してください。それは私にとって大きな大きな力になります!

アプリ広報

今見てるブログを作成たDekuが開発したアプリを使ってみてください。
Dekuが開発したアプリはFlutterで開発されています。

興味がある方はアプリをダウンロードしてアプリを使ってくれると本当に助かります。

Posts