これは Node.js Advent Calendar 2019 の8日目の記事です。
昨日は @yuta-ron さんによる スクレイピング & サーバレスAPIでNode.jsの雰囲気を体験してみる でした。
初学者向けpackage.jsonハンズオン
Node.js初学者向けにpackage.jsonハンズオンを実施しましたので、その時に作ったハンズオン資料を公開します。
npmコマンドやpackage.jsonに慣れることが目的のハンズオンの資料ですので、Node.jsとは何か?といった説明はしません。ご了承ください。
文章の手順通りに進めていけば、npmコマンドやpackage.json編集が体験できます!
事前準備
Node.jsのインストール
事前にNode.jsのインストールをお願いします。(すでにNode.jsがインストール済の方は飛ばしてください。)
Windowsの場合
Windowsの方は、こちらの記事をご参照ください。Chocolatey > Nodist > Node.jsの順番でインストールします。
Windowsで、Chocolateyとnodistで、バージョン切り替え可能なNode.jsの環境を構築する
Macの場合
Macの方は、こちらの記事をご参照ください。Homebrew > nodebrew > Node.jsの順番でインストールします。
macOS に Homebrew で nodebrew をインストールして Node.js を使う
package.jsonハンズオン
それではハンズオンを始めます。
作業ディレクトリを作ろう
お好きな場所に作業ディレクトリを作りましょう。
Windowsの場合
今回のハンズオンでは以下のディレクトリを 作業ディレクトリ
と呼ぶことにします。
D:\JavaScript\package-json-handson
Macの場合
今回のハンズオンでは以下のディレクトリを 作業ディレクトリ
と呼ぶことにします。
~/JavaScript/package-json-handson
WindowsならGit Bashを使おう
Web界隈ではLinuxサーバーが主流ですので、DOSコマンドよりもLinuxコマンドが使える環境の方が、何かと都合がよいと思います。
Git for Windows
をインストールしていれば、 Git Bash
というターミナルがインストールされており、そこでLinuxコマンドが使えます。
今回のハンズオンでは、Git Bashを使う前提で進めます。
カレントディレクトリを作業ディレクトリにしてください。
作業ディレクトリに移動
カレントディレクトリを作業ディレクトリにしてください。
以下のコマンドを実行してみましょう。
# Windows
cd /d/JavaScript/package-json-handson
# Mac
cd ~/JavaScript/package-json-handson
npmコマンドでpackage.jsonを生成してみる
作業ディレクトリにnpmパッケージを作っていきます。
以下のコマンドを実行して、npmパッケージを初期化してみましょう。
# 作業ディレクトリをnpmで初期化
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 json` 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: (package-json-handson)
最後の行で上記のように表示されると思います。
ここでは、これから作るnpmパッケージの名前をどうするのか質問されています。デフォルトでディレクトリ名が表示されていますので、そのまま何も入力せずEnterしてください。
そうすると、以下のように次の質問が表示されます。
version: (1.0.0)
ここでは、npmパッケージのバージョンをどうするのか聞かれています。
デフォルトは 1.0.0
となっていますが、ここでは、 0.1.0
を入力してください。(理由は後で説明します。)
そうすると、以下のように次の質問が表示されます。
description:
ここでは、npmパッケージの説明文の入力を求められています。
とりあえず handson
と入力してください。(後から変更できますので、真剣に悩まなくても大丈夫です。)
そうすると、以下のように次々と質問されます。
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
とりあえず、何も入力せず、すべてEnterしてください。
そうすると、最後に以下の質問が表示されます。
Is this OK? (yes)
ここでも、何も入力せずEnterしてください。(yes
の意味になります。)
これで、npmパッケージの初期化が完了しました!
package.json
が作業ディレクトリに生成されていますので、内容を確認してみましょう!
# package.json の中身を表示する
cat package.json
以下のようにJSON形式のデータが表示されれば成功です!
{
"name": "package-json-handson",
"version": "0.1.0",
"description": "handson",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
自分が入力してきた値が格納されていることがわかると思います。
npm-scriptをつくってみる
テキストエディター(こだわりがなければVS Codeがオススメです)で package.json
を開いてください。
scripts
という項目があります。この部分には、独自のスクリプトを登録できます。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"show-files": "ls -al"
},
試しに、上記のように show-files
の行を追加してみてください。
package.json
を保存したら、以下のコマンドを実行してみましょう。
npm run show-files
そうすると、 ls -al
が実行されます!
Linuxコマンドが動くターミナル(Git Bash等)なら、ファイル一覧が表示されます!
もし、コマンドプロンプトを使っている場合は、Linuxコマンドが動かないので、エラーが表示されます。
この独自のスクリプトのことを npm-script
と呼びます!覚えておきましょう。
app.jsをつくってみる
作業ディレクトリに app.js
というファイルを作ってください。
中身に以下の一行を書いて保存してください。
console.log("Hello World!");
以下のコマンドを実行してみてください。
node app.js
以下が表示されれば成功です。
Hello World!
おまけ: index.js
と app.js
の使い分け
たったいま、 app.js
を作りましたが、先ほどの package.json
には index.js
という記述がありました。
これらは何が違うのでしょうか?
実は、今作っているnpmパッケージが
- アプリケーションなら
app.js
に、最初に実行するコードを書く。 - ライブラリなら
index.js
に、最初に実行するコードを書く。
という慣習があります。(諸説あります)
Start Scriptを作ってみる
今度は、 package.json
の scripts
に start
の行を追加してください。
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"show-files": "ls -al",
"start": "node app.js"
},
以下のコマンドを実行してみてください。
npm run start
以下が表示されれば成功です。
Hello World!
次に、以下のコマンドを実行してみてください。
npm start
こちらのコマンドでも同じ結果になりました!以下が表示されれば成功です。
Hello World!
実は npm start
というのは npm run start
のエイリアスになっています。
メインに実行する処理はnpm-scriptの start
に登録しましょう。
moment
をインストールしてみる
まず、以下のコマンドを実行してみましょう。
# moment をインストール
npm install moment
作業ディレクトリに node_modules
フォルダーが生成されました。
このフォルダーを開くと、 moment
フォルダーが見つかります。
加えて、 package.json
に以下の行が自動で追加されます。
"dependencies": {
"moment": "^2.24.0"
}
バージョン番号が勝手に追加されましたね。このバージョンの先頭についている ^
に関しては、あとで説明します。
次に、app.js
を以下のように書き換えてください。
// ライブラリを読み込む
const moment = require("moment");
// 現在時刻を取得する
const now = moment().format("YYYY-MM-DD HH:mm:ssZ");
// 現在時刻を表示する
console.log(now);
以下のコマンドを実行してみてください。
npm start
すると、以下のように現在時刻が表示されます。
2019-11-20 18:51:02+09:00
moment
は日付に関する処理を扱った歴史のあるライブラリで、Node.js界隈で広く使われています。
歴史がある分、多機能でファイルサイズが大きいという欠点もあります。
dayjs
のような軽量なライブラリも台頭してきていますので、必要に応じて使い分けていきましょう。
moment
をアンインストールしてみる
せっかく入れた moment
ですが、今度はアンインストールしてみます。
以下のコマンドを実行してみましょう。
# moment をアンインストール
npm uninstall moment
node_modules
フォルダーから moment
フォルダーが削除されました。
同時に package.json
からも消えました。
"dependencies": {}
以下のコマンドを実行してみてください。
npm start
moment
がなくなったので、以下のようにエラーが表示されるはずです。
internal/modules/cjs/loader.js:626
throw err;
^
Error: Cannot find module 'moment'
package.json
から moment
をインストールしてみる
今度は、 package.json
に以下の行を手動で追加してみましょう。
"dependencies": {
"moment": "^2.24.0"
}
以下のコマンドを実行してみます。
# dependencies に書かれたライブラリをインストール
npm install
実は、これでも moment
がインストールされます!
以下のコマンドを実行してみてください。
npm start
以下のように現在時刻が表示されれば成功です。
2019-11-20 18:51:02+09:00
dependencies
に色々インストールしてみる
試しに色々インストールしてみましょう
# dependencies にインストール
npm install express
npm install cors
package.json
の dependencies
にアルファベット順で追加されていくのがわかると思います。
"dependencies": {
"cors": "^2.8.5",
"express": "^4.17.1",
"moment": "^2.24.0"
}
eslint
を dev-dependencies
にインストールしてみる
ESLintというライブラリがあります。
これを使うと、JavaScriptの文法を検査し、問題があればVS Code上に警告を表示してくれたりします。
このライブラリは開発環境では使いますが、サーバー環境では使いません。
こういったライブラリを扱うのが devDependencies
です。
以下のコマンドを実行してみてください。
# devDependencies にインストール
npm install --save-dev eslint
npm install --save-dev eslint-config-airbnb-base
package.json
に dependencies
とは別に devDependencies
という項目が増えたと思います。
"devDependencies": {
"eslint": "^5.16.0",
"eslint-config-airbnb-base": "^13.1.0",
},
dependencies
のみインストールする
サーバー環境等で、 devDependencies
をインストールせずに、 dependencies
のみをインストールしたいということがあります。
以下のコマンドを使えば可能です。
# dependencies のみインストール
npm install --production
セマンティックバージョニングについて
いつのまにか package-lock.json
というものが生成されています。これは何なのでしょうか?
これが何なのか説明する前に、セマンティックバージョンについて説明します。
Node.js界隈では セマンティックバージョニング X.Y.Z
という考え方が浸透しています。
おおざっぱに説明すると、以下のようにバージョン番号を付けます。
-
X
: メジャーバージョン : 互換性がなくなったら上昇 -
Y
: マイナーバージョン : 互換性を保ちつつ、機能を追加したら上昇 -
Z
: パッチバージョン : バグ修正したら上昇
それでは、一番最初の開発版のバージョンはどうするのか?というと、セマンティックバージョニングによれば、 0.1.0
から始めるのが良いとされています。
このハンズオンの最初に、バージョン番号を 0.1.0
にしたのも、それが理由です。
バージョンの範囲指定について
package.json
でのバージョンの範囲指定についても説明します。
先ほど ^
という記号が登場しました。以下のような特徴があります。
-
~X.Y.Z
: パッチバージョンZ
の上昇まで許容します。 -
^X.Y.Z
: マイナーバージョンY
の上昇まで許容します。
たとえば、以下の表のように、複数のバージョンを持つライブラリがあるとします。
バージョン | 2.x | 2.1.x | ~2.1.1 | ^2.1.1 |
---|---|---|---|---|
1.35.7 | ||||
2.0.0 | ||||
2.1.0 | ||||
2.1.1 | ||||
2.1.2 | ||||
2.2.0 | ||||
3.0.0 |
がついているものの中で、最新のものがインストールされます!
このようにバージョンを範囲指定することで、 npm install
するだけで、バグが修正された新しいライブラリを使うことができます。
ただし、以下のようなことも発生します。
- Aさん、11月に
npm install
を実行したところ、2.1.1
がインストールされた。 - Bさん、12月に
npm install
を実行したところ、2.1.2
がインストールされた。
npm install
を実行したタイミングで異なるバージョンのライブラリがインストールされます!
結局どのバージョンがインストールされているのか?は、 package.json
を見ただけではわかりません。
それを記録しているのが、 package-lock.json
です!
これは自動で生成されるファイルなので、このファイルを手動で編集しないようにお願いします。
npm ci
で package-lock.json
から高速にインストールする
せっかく色々インストールしましたが、ここでいったん、 node_modules
フォルダーを削除してみましょう。
(VS Codeで node_modules
を開いている場合は、エラーが起きるかもしれません。その場合は、VS Codeを閉じてください。)
削除ができたら、以下のコマンドを実行してください。
npm ci
node_modules
フォルダーが復活しました!
実は、 npm ci
は package-lock.json
を元にライブラリをインストールするんです!
また、 npm install
よりも npm ci
の方が、インストールが早く終わったことに気づいたかもしれません。
npm install
を実行したときは、ライブラリが依存している別のライブラリを検索したりと、依存関係の解決に時間がかかります。
しかし、 package-lock.json
には、そういった依存関係の検索が済んだデータが記載されています。そのため、 npm ci
の方が npm install
よりも高速になったんです。
グローバルに npm install
今度は、以下のコマンドを実行してくてみましょう。
npm install --global fixpack
fixpack
というライブラリがインストールされたはずですが、 package.json
にも node_modules
にも fixpack
は追加されていません。
実は、npmにはグローバル用の node_modules
があり、そこに追加されています。
WindowsでNodistを使ってNode.jsをインストールした場合、 C:\Program Files (x86)\Nodist\bin\node_modules
にあるようです。
fixpack
を使ってみる
グローバルにインストールした fixpack
を使ってみましょう。
以下のコマンドを実行してください。
fixpack
package.json
の中身が自動でソートされたと思います。
とくにぐちゃぐちゃになりがちな dependencies
の中身がアルファベット順にソートされるので便利です。
積極的に使っていきましょう!
さいごに
以上おつかれさまでした。
ひととおり、npmコマンドや package.json
の編集を体験できたと思います。
本記事作成にあたり、以下のページを参考にしました。ありがとうございました。
- npm Documentation / npm-package.json
- セマンティック バージョニング
- package.json のチルダ(~) とキャレット(^)
- npm ciを使おう あるいはより速く
- fixpackでpackage.jsonの各項目を並び替える
これは Node.js Advent Calendar 2019 の8日目の記事でした。
明日は @shimataro999 さんによる Node.js v12のES Modulesと、Babel/TypeScriptの対応について です!