概要
Vue.jsの公式クイックスタートにある以下コマンドについて、内部で何してるのかを各コマンドを実行しつつ、色々調べてみた。
npm create vue@latest
実行環境は以下Docker Imageで立ち上げたNode.jsコンテナ。
FROM node:18.18.0-bullseye-slim
USER node
WORKDIR /workspace
npm createは何してるのか
vue@latestやコマンド実行時の挙動の前に、npm createについて確認する。
npmとは
正式名称:Node Package Manager。
その名の通りNode.js上で参照する各種パッケージの依存関係やバージョンなどを管理するマネージャ。
npm公式ドキュメントによるとソフトウェアレジストリと定義されている。
レジストリの解釈が少し難しいが、大まかにライブラリと同じものと見做してよさそう。
ライブラリ=モジュールの集合=再利用可能なプログラムの集まり、ということで、npmのおかげで用いることで集約された各モジュール(Node.js的に言うならパッケージ)を好きにローカル環境にもってきて実行することが出来る。
Node.jsとの関係性については以下の図が分かりやすかった。
参考:https://nodesource.com/blog/NodeJS-securing-your-applications-1
npm createとは
npm createというコマンド自体は存在せず、実体としてはnpm initの模様。
とりあえずhelpを見てみた。
node@a9076da33620:/workspace$ npm create --help
Create a package.json file
Usage:
npm init <package-spec> (same as `npx <package-spec>`)
npm init <@scope> (same as `npx <@scope>/create`)
Options:
[-y|--yes] [-f|--force] [--scope <@scope>]
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
[-ws|--workspaces] [--no-workspaces-update] [--include-workspace-root]
aliases: create, innit
Run "npm help init" for more info
(誤字ってる気がするが)aliases見るとnpm createとnpm initを同列に扱ってる節がある。
npm initのhelpも確認してみたが、全く同じだった。
node@a9076da33620:/workspace$ npm init --help
Create a package.json file
Usage:
npm init <package-spec> (same as `npx <package-spec>`)
npm init <@scope> (same as `npx <@scope>/create`)
Options:
[-y|--yes] [-f|--force] [--scope <@scope>]
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
[-ws|--workspaces] [--no-workspaces-update] [--include-workspace-root]
aliases: create, innit
Run "npm help init" for more info
じゃあnpm initは何してるのか
公式ドキュメントによると、新規または既存のnpmパッケージをセットアップするコマンドとのこと。
引数(initializer)に指定した内容に応じて、対応付けられたnpm execコマンドが実行される。
要するに、以下のような対応関係でexecコマンドが実行される模様。
npm init <name>@<version> -> npm exec create-<name>@<version>
npm execは何してるんだ
なんとなく引数のパッケージを実行するコマンドっぽいことは伝わってきたが、一応helpを見てみた。
node@a9076da33620:/workspace$ npm exec --help
Run a command from a local or remote npm package
Usage:
npm exec -- <pkg>[@<version>] [args...]
npm exec --package=<pkg>[@<version>] -- <cmd> [args...]
npm exec -c '<cmd> [args...]'
npm exec --package=foo -c '<cmd> [args...]'
Options:
[--package <package-spec> [--package <package-spec> ...]] [-c|--call <call>]
[-w|--workspace <workspace-name> [-w|--workspace <workspace-name> ...]]
[-ws|--workspaces] [--include-workspace-root]
alias: x
Run "npm help exec" for more info
ローカルだけでなく、まだフェッチしてないnpmレジストリ上のリモートパッケージも指定できるみたい。
つまるところ
以上を踏まえると、npm create vue@latestは最終的にnpm exec create-vue@latestとして実行される。
クイックスタートのドキュメント通り、最新のcreate-vueパッケージを実行していることが分かる。
npm create vue@latest
↓
npm init vue@latest
↓
npm exec create-vue@latest
create-vueパッケージは何してるのか
先にまとめると、このパッケージが実施することは以下2点に集約される。
- package.jsonの作成
- 開発用パッケージ(viteなど)の設定ファイルの作成
実際にコマンドを叩いてみる。
対話形式で、各種開発に必要になるであろうパッケージを追加するかどうかのYes/Noの入力が求められる。
create-vueで導入を問われるものについて
Add ○○?と問われるものについて簡単に見ていく。
TypeScript
JavaScriptに型構造を持たせた言語。Node.js上で動かすアプリの場合、実行前にJavascriptにコンパイルされる。
JSX
JavaScript XML。
ざっくりいうとjavascriptの変数に直接htmlタグ文字列を埋め込める。DOM生成関数をcallする必要がないためより可読性に長ける。どうやらReactの方でよく使われている模様。
Vue Router
SPAにおけるURLと描画コンポーネントのルーティングを行う。
Pinia
状態管理パッケージ。同様のツールとしてvuexなどがある。
Vitest
単体テストツール。Jestとかと同じ部類に入る。ビルドツールであるviteとの親和性が高いらしい。
ESLint
構文解析(リンティング)ツール。jsコードを静的解析してくれる
Prettier
フォーマッター。js/ts以外にもhtmlとか色々対応してる。
npm installについて
パッケージのインストールを行う。利用ケースとしては以下の3つに集約されそう。
- パッケージの個別インストール
- パッケージの一括インストール
- 各versionを指定してのパッケージの一括インストール
それぞれ見ていく。
パッケージの個別インストール
以下コマンド実行にて行う。
npm install <package-name>
挙動は以下の通り。
- カレントディレクト内にnode_moduleディレクトリを作成(作成済みならパス)
- 指定パッケージ(およびその依存パッケージ)をnpmレジストリから探してDLし、node_module配下に配置
- インストールしたパッケージの名前とバージョンをpackage.jsonおよびpackage-lock.jsonに追記
ちなみに、インストール時の参照スコープとしてlocalとglobalが用意されており、以下のような使い分けになる。
- local
- プロジェクト内のjsファイルにて、require文でパッケージを参照する
- global
- CLI上でパッケージを直接実行する
コマンド実行時に -gオプション をつけるとglobal参照でインストールを行い、その場合は /usr/local/lib/node_modules/ 配下にパッケージは配置される。(npm listで確認可能)
両方の用途で参照する場合は、どちらも実施する必要があるとのこと。Prettierなどのフォーマッターなどでない限り、基本的にはlocalのみでインストールになると思われる。
パッケージの一括インストール
こちらはnpm installのみで実行する。
挙動は以下の通り。
- カレントディレクトリ内にpackage.jsonがあるかを探す
- 見つけたpackage.jsonに沿って、各パッケージをインストールする(以下個別インストール時の挙動と同じ)
各versionを指定してのパッケージの一括インストール
挙動は以下の通り。
- カレントディレクトリ内にpackage.jsonがあるかを探す
- カレントディレクトリ内にpackage-lock.jsonがあるかを探す
- 見つけたpackage.jsonに沿って各パッケージをインストールする
package.jsonとpackage-lock.jsonが作成済みの場合に実行可能。
インストール対象パッケージのバージョンの再現性を担保するのが目的と思われるため、package.jsonやpackage-lock.jsonの更新は特に行われない。
個人的QA
create-vueパッケージや各種npmコマンドを調べる過程で気になった挙動について。
Q. 何らかの不手際でpackage-lock.jsonのみ存在した場合はどうなるの?
A. package.jsonが無い旨のエラーが出力され、package-lock.jsonもそれに合わせて更新される(つまりまっさらになる)
package-lock.jsonだけでも一括インストールに必要な情報は足りてそうだが、上記処理から推測するに、あくまで参照としてはpackage.json → package-lock.jsonの参照順序になっている模様。
Q. npm installでの一括インストール実行に必要なものはつまり何?
A. package.jsonのみ。package.jsonさえあれば要らない何も捨ててしまおう
逆にpackage.jsonしか存在しないディレクトリ下で実行しても、ちゃんとnode_moduleディレクトリが作成される。
Q. vue-createでyes/noを聞かれるパッケージって後で自分で入れたりできないの?
A. 入れることは可能。
ただし、--save-devオプションをつけて入れるような開発用パッケージ(prettierとか)の場合、別途設定ファイルを用意する必要があるが、それらはnpm install時に自動作成されず、都度手動で作成する必要がある。
プロジェクト作成時にvue-createのインタラクションにYesと回答したパッケージの設定ファイルはvue-createが自動作成してくれるので、よりスムーズに導入が可能となっている。
終わりに
Vue公式のクイックスタートで紹介されている手順について、その構成要素となる技術について一通り調べてみた。
vue-createで導入する開発用パッケージやテストツールについてはまだまだよくわかっていないため、Vueアプリの作成をやりつつ、気になったことからまた調べていきたい。