概要

Node.jsを仕事上で最近1,2ヶ月初めて使うようになったので、調べて理解したものをまとめる(といっても内容的なは初歩的なものである)。

file

NPM

npm(node package manager)は、node.jsのパッケージを関するするCLI。パッケージの

  • 作成
  • インストール
  • npmへの公開

などができる。別のCLIであるYarn(「ヤーン」、Facebookが開発した)もあるが、やはりnpmが一番メジャーである。

プロジェクト=パッケージ

プロジェクト=コードのまとめり(repo単位とリニアイコールと考えてもいいかもしれない)。

package.json

パッケージ管理の設計書みたいなもので、package.jsonを読み込むことで同じパッケージをインストールすることができるような仕組みになっている。

npmでは、「パッケージ=package.jsonがいる親ディレクトリに含まれるファイル群」であり、npmのコマンドは、通常package.jsonがいるプロジェクトの「ルートディレクトリ」で実行される。

パッケージ作成

パッケージの「ルートディレクトリ」にて、下記コマンドを実行し、package.jsonを生成する。インタラクティブの質問をスキップするには-yオプションを付ける。

以下に、npm initを実行した際に出てきた質問のデフォルトと意味あいを書いておく。

$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help init` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
質問 説明
package name: (user_details) デフォルトは括弧内のディレクトリ名
version: (1.0.0) デフォルト1.0.0
description: 説明
entry point: (user_details.js) エントリポイント。デフォルトは中にあるjsファイル名(複数ある場合は?)
test command: テスト用のスクリプト
git repository: git repo URL
keywords: パッケージ公開時のための検索キーワード
author: 著者
license: (ISC) パッケージのライセンス

dependenciesの表記

Semver (Semantic Versioning)の規則に従う必要がある(3.1.4があるとする場合、3Major、利用側は一般的にプログラム修正が必要、1Minor、新機能追加だが、利用側は修正しなくてもそのまま使える。4Patchで、不具合修正などでバージョンが上がる)。

  "dependencies": {
    "express": "^4.17.1",
    "request": "~2.88.0"
  },

^(キャレット, caret)や~(チルダ、tilde)を先頭に付ける場合とつけない場合の意味合いを下表にまとめた。

意味あい
^3.1.4 Majorは一致しMinorPatchは指定されたもの以上。3.2.5は合致、3.1.3は合致しない
~2.7.18 MajorMinorは一致しPatchは指定されたもの以上。2.7.20は合致、2.8.8は合致しない
0.6.18 先頭に何も付いていない場合はちょうどそのバージョンである

package-lock.jsonがなく、dependenciesがローカルにインストールされていない状態でnpm installが実行されると、package.json にあるdependenciesのルールに従い、指定されたバージョンにマッチする中で最も新しいバージョンがインストールされる。

dependenciesを編集(追加/バージョン変更など)をする際、package.jsonは直接編集しないで、npmを通じて行うべき。 注意:npm v4までは、dependenciesとして追加するときに--saveを指定しないとpackage.jsonに反映されないが、npm v5以降はデフォルトで反映するようになった。

devDependency(devDep)として追加する場合は-D(--save-devのエイリアス)を指定する。

バージョン指定する場合は、package@versionの形を書けばいい、例:

$ npm install react@latest
$ npm install [email protected]

パッケージの削除はnpm uninstall <package>

scripts

"scripts": {
    "start": "node index.js",
    "lint": "eslint",
    "cmd": "command arg",
	"precmd": "pre command arg",
	"postcmd": "post command arg"
  },

コマンドの別名(エイリアス)であり、npm run <name>のように実行できる。pre<name>post<name>の別名があると、cmdの実行前にprecmdが、実行後postcmdが実行される具合。

main

そのパッケージを外からインポートするときにどの JavaScript ファイルが入り口であるかを指定するものである。例えば、パッケージrequestを利用する場合、

const req = require('request');

そのrequestpackage.json(node_modules/request/package.json)をみると、

省略
  "license": "Apache-2.0",
  "engines": {
    "node": ">= 6"
  },
  "main": "index.js",
  "files": [
    "lib/",
    "index.js",
    "request.js"
  ],
  "dependencies": {
    "aws-sign2": "~0.7.0",
省略

のように、main: index.js,になっている。これは、index.jsがエクスポートした値が、require('request')の戻り値になることを表している。

index.jsの中身をみると、module.exports = requestになっている。その値が、const reqに代入されていることになる。

// Exports

module.exports = request
request.Request = require('./request')
request.initParams = initParams

package.jsonmainは、そのパッケージをNPMで公開しない限り重要ではない。

bin

binも、外から使われるものでなければ重要ではないものなので、割愛する。

package-lock.json

dependencyのバージョンをlock(固定)するためのファイルであり、npm installの実行時に自動的に作成される。npm v5以降に導入され、dependency、dependencydependency…と間接的なものも含めすべてのdependencyのバージョン(とそのintegrity)が記録される。

package.jsonとpackage-lock.jsonの優先順位

  • package-lock.jsonが存在しないとき package.jsonに基づいてdependencyがインストールされ、実際にインストールされたバージョンがpackage-lock.jsonに記録する。
  • package-lock.jsonが存在するとき package-lock.jsonに基づいてインストールされるが、package.jsonとの矛盾があれば、package.jsonが優先され、実際にインストールされたバージョンがpackage-lock.jsonに記録する。

ユースケース

npm install

開発中のソースコードだけあり、dependenciesがインストールされていないとき。

npm install

dependenciesはインストールされたが、新たにパッケージを追加したいとき。

npm audit

脆弱性のあるdependencyがあるか自動でチェックすることができる(報告されているものならば)。

参考資料(THX)