npmにモジュールを公開することは多くなってると思いますが、今までのnpmだと名前は早い者勝ちでした。

最近npm Private Modulesというprivateで扱えるモジュールを有料でサポートしましたが、これはscoped modulesをprivateで扱う時だけ有料でpublicで公開する時は無料で行えます。

scoped modulesというのは、@username/project-name という感じで、@ユーザー名がパッケージ名に入るので異なるユーザー間では重複しません。

公開手順

実際にscoped modulesをpublicに公開する手順としては、

  1. npm init --scope=<npmユーザ名>
    • パッケージの名前が@<npmユーザ名>/パッケージ名になる
    • 手動で書き換えても別に問題ない
  2. 適当に開発
  3. npm publish --access=public
    • またはpublishConfigpublicに設定(こちらの方が宣言的)

するだけです。

簡単に書くとscoped modulesとして作って、公開する時はnpm publish --access=publicとするだけです。(デフォルトが--access=restrictedであるため明示する必要がある。必要なのは最初に公開する時のみ)

pacakge.jsonpublishConfigpublicに設定してある場合は、npm publish--accessオプションは不要です。

...
  "publishConfig": {
    "access": "public"
  }
...

こうして公開したモジュールは

npm install @<npmユーザ名>/パッケージ名

という感じで、普通のモジュールと同様にインストールできます。

以下の記事で書いてたpublishのパターンも少し更新しておきました。

公開例

実際に適当なものを作ってみました。

$ npm install @azu/github -g 

という感じでインストールできることがわかると思います。 npm version 2.xが必要ですが、Node 0.12を使っていれば勝手に入ってるはず。

npm install -g npm

で、npmだけのアップデートも可能です。

おわりに

scoped modulesを使うことで、npmでも名前空間っぽいものが扱えるようになりました。

scoped modulesであれば名前の重複などを気にしなくてよくなるのはいい気がします。

これの問題としては、周辺のツールがまだ未対応であったりすることがあります。 例えば、@myorg/mypackageという名前のモジュールをインストールすると以下のような配置でnode_modules以下にインストールされます。

node_modules
├── @myorg
│   └── mypackage
│       └── package.json
├── browserify
│   └──package.json
├── del
│   ├── index.js
│   └──package.json
....

そのため、ディレクトリが一つ深くなって再帰的に探索していないツールなどはscoped modulesを無視してしまう事があります。

具体的にはtsd linkなどはそういうバグがあったりしました。

追記(2019-01-24): [publishConfig](https://docs.npmjs.com/files/package.json#publishconfig)についてを追加