Next.js や Slidev などのフロントエンドのOSSで npm init slidev や npx create-next-app のようなテンプレートからプロジェクト作成するためのジェネレータが用意されており、なぜ npm init や npx など複数の方法でジェネレータを利用できるのか気になったので調べました。
パッケージ名にルールがある
NPMのドキュメントに npm init がジェネレータを認識するためのルールが記載されており、
どうやら create-<name> のような特定のルールでパッケージ名を指定するとジェネレータとしてNPMが認識してくれるようです。
具体的なルールは下記になります。
npm init <@scope> (same as `npm exec <@scope>/create`) npm init [<@scope>/]<name> (same as `npm exec [<@scope>/]create-<name>`)
パッケージを scoped-module として作成する場合は、@thasmto/create のようにスコープ名の後ろに create をつけたパッケージ名にすることで npm init @thasmtoで実行できるようになります。
また、 scoped-module ではない場合でも create-thasmto のように create- から始まるパッケージ名にすることで npm init thasmto と実行できます。
本来、npm init は新しい package.json を作成するために利用されますが、上記のルールに当てはまるパッケージが存在する場合は、内部で npx exec というコマンドが動きます。
そして npm exec はパッケージのコマンドを実行するためのコマンドであり、エイリアスとして npx が用意されています。
このことから以下の三つコマンドは同じパッケージを実行することがわかりました。
npm init next-app npm exec create-next-app npx create-next-app
また、yarn create も npm init と同様に create-* と名前付けされたパッケージを実行できます。
おわり
普段あまり意識することはないですがちょっとした疑問を解消をできました。 実際にジェネレータを作るには、テンプレートからプロジェクトディレクトリを生成するためのNode.jsのスクリプトを書く必要がありますが、その場合は下記の記事が参考になりそうでした。