[npm-link] 独自パッケージの開発を爆速に
npmのパッケージを自分で開発している時に作成しているパッケージを使用したいことはありますか?
開発している途中で検証する際、npmなどのパッケージレジストリなどにpublishして使用したいprojectでnpm installで引っ張ってくる必要があり手間がかかってしまいます
npm linkを使用することでローカル内だけでnpmのパッケージ検証が可能になります
目次
環境
node -v
v18.8.0
npm -v
8.18.0
今回の完成形
private-hello-package
// private-hello-package/package.json
{
  "name": "private-hello-package",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "type": "module"
}
// index.js
const hello = () => {
  return 'hello world';
};
export {
  hello
};
my-project
// my-project/package.json
{
  "name": "my-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node index.js"
  },
  "author": "",
  "license": "ISC",
  "type": "module"
}
// index.js
import { hello } from "private-hello-package";
const result = hello();
console.log(result);
ディレクトリ構造
root
┗ package
  ┗ private-hello-package
    ┗ index.js
    ┗ package.json
┗ my-project
  ┗ index.js
  ┗ package.json
  ┗ package.lock.json
検証
パッケージ側
npm project作成
$ npm init
また、import文を使用するためpakcage.jsonにtype: moduleを追加する
// private-hello-package/package.json
{
  "name": "private-hello-package",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "type": "module"
}
文字列を出力するindex.jsを実装します
const hello = () => {
  return 'hello world';
};
export {
  hello
};
これでパッケージ側は完了です。パッケージを使用する側のprojectで使用したい関数はexportしてください
パッケージを使用するproject側
パッケージ側と同じくnpm初期化します
$ npm init
npm startコマンド、type: moduleを追加
// my-project/package.json
{
  "name": "my-project",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node index.js"
  },
  "author": "",
  "license": "ISC",
  "type": "module"
}
これで下準備は完了です
npm linkでシンボリックリンクを貼る
次にmy-projectでprivate-hello-packageを使用できるようにします 以下のコマンドでnpmシンボリックリンクが貼られます
$ cd {path}/package/private-hello-package
$ npm link
次に使用するprojectに移動してnpm linkでローカルでパッケージを使用できるようにします
$ cd {path}/my-project
$ npm link private-hello-package
これでnpm linkしたパッケージを使用できるようになったのでprivate-hello-packageを使用した実装をしてみます
// index.js
import { hello } from "private-hello-package";
const result = hello();
console.log(result);
実行してみましょう
$ npm start
hello world
出力されましたね
詳細
シンボリックリンクの確認
npm linkしたnode_moduleを見てみましょう
$ ls -l {path}/my-project/node_modules
xxxxxx  private-hello-package -> ../../private-hello-package
相対的にパッケージが指定されています
またnpm linkはglobalにシンボリックリンクが貼られています
筆者はnodenvでnodeを管理しているので下記のディレクトリで確認できます
ls  -l ~/.nodenv/versions/18.8.0/lib/node_module
xxxxxxxxxx private-hello-package -> ../../../../../blog/package/private-hello-package
private-hello-packageを指定するとローカルのprivate-hello-packageを指定していることがわかります
シンボリックリンクの解除
$ cd {path}/package/private-hello-package
# 使用する側のシンボリックリンクを解除します
$ npm unlink private-hello-package
# パッケージのシンボリックリンクをglobalから解除します
$ npm unlink -g private-hello-package
scopeでのnpm link
scopeを使用することによってpackageをグルーピングすることが可能です
scopeを使用したnpm linkの例は以下になります
// private-hello-package/package.json
{
  "name": "@scope/private-hello-package",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "type": "module"
}
$ cd {path}/package/private-hello-package
$ npm link
# @scopeのディレクトリ配下にある
$ ls  -l ~/.nodenv/versions/18.8.0/lib/node_modules/@scope
xxxxxxx private-hello-package -> ../../../../../../blog/package/private-hello-package
$ cd {path}/package/my-project
$ npm link @scope/private-hello-package
このような階層でシンボリックリンクが貼られています
my-project
┗ node_modules
  ┗ @scope
    ┗ private-hello-package
npm linkについて解説しました
npm linkを駆使して開発を爆速にしましょう!使用し終わったらシンボリックリンクの解除もお忘れなく
