LoginSignup
2
1

「npx create-next-app」って何をしているの?

Posted at

はじめに

最近、Next.jsでの開発を進めていて、いつも使っている 「npx create-next-app って何してるんだ?」という疑問が頭をよぎりました。

よく、ふとした瞬間に、「これって本当に理解して使ってる?」と自問自答することってありますよね。特に、誰かに説明しようとすると、理解を曖昧にしているせいで思った以上に言葉に詰まることが多いです。

例えば、公式ドキュメントの「Installation」を参照してプロジェクトをセットアップする際に、手順をコピー&ペーストして「動いたからOK」としてしまうことが多いかと思います。実は私もそんなタイプです😅

この記事では、Next.jsでプロジェクトを作る過程で、「なぜそうなるのか」を掘り下げながら、より深く理解していくことを目指します。

Next.jsプロジェクトの作成

では、Next.jsのプロジェクトを作成していきます。
まずはいつも通り、Next.js 公式ドキュメント に記載されているまま進めていこうと思います。

  1. Node.jsをインストールする

    現在は Node.js 18.17 or later. と書いてあるので、Node.jsのダウンロードページ から v18.17以降 の Node.js をインストールします。

  2. Next.jsのプロジェクトを作成する

    以下のコマンドを実行してNext.jsのプロジェクトを作成します。

    npx create-next-app@latest
    
  3. 開発サーバーを起動します。

    以下のコマンドを実行して、開発サーバーを起動します。

    cd my-app
    npm run dev
    

ここまでが、Next.jsのプロジェクトを作成し、Next.jsアプリケーションを起動する手順となります。

初めてNext.jsのプロジェクトを作成する方やnpmを使用する方にとっては、これらの説明の中で、以下のような疑問が出てくるかと思います。

  1. Next.js に Node.js が必要な理由は?
  2. npx とは何か?
  3. npx create-next-app で何が行われているのか?
  4. npm run dev で何が行われているのか?

私自身、基礎を疎かにしがちな人間なので、何度も「あれ、これ前も調べたよね?」という状況になってしまうことがあります。そんな経験を活かして、今回はこれらの疑問について自身も学習しながら解説していきたいと思います。

疑問1. Next.js に Node.jsが必要な理由は?

『Node.jsとは何者なのか?』という説明を始めると、それだけで記事一本書けてしまう程のボリュームになってしまうので、本記事ではNode.jsは以下の役割をするツールだと思ってください。

役割1. JavaScriptをサーバーサイドで実行するためのランタイム

Next.jsは Node.js上で動作するフレームワーク です。
そのため、Next.jsのアプリを実行するためには、Node.jsが必須となります。

これだけではイメージが湧きにくいかもしれませんので、図で表現してみます。ここでは、ローカルPCからWebサーバー上にデプロイされたNext.jsアプリケーションにリクエストを送信するまでの流れを図解します。

JavaScriptをサーバーサイドで実行するためのランタイム_01
  1. 「ローカルPC」からリクエストが「Webサーバー」へ送信されます。これは一般的なクライアントとサーバー間の通信です。
  2. 「Webサーバー」上の「Next.jsアプリケーション」がそのリクエストを受け取ります。Next.jsはNode.jsを使用してWebサーバー機能を提供します。
  3. Next.jsアプリケーションはNode.jsランタイム上で動作しており、リクエストを処理することができます。この段階で、サーバーサイドレンダリングやAPIの呼び出しなどが行われます。
  4. 「Next.jsアプリケーション」がリクエストを処理し、「ローカルPC」にレスポンスのHTMLを返します。このHTMLはNext.jsによって生成され、必要に応じてプリレンダリングされたページや動的に生成されたページを含むことができます。

このことから「Next.jsアプリケーション」は Node.jsランタイム上 で動作していることがわかります。

Node.jsは一般的に サーバーサイド でJavaScriptを実行するランタイム環境として知られていますが、この説明ではインターネット越しの リモートサーバーで実行される というイメージが強調されがちです。しかし、ローカルPCにNode.jsをインストールし、Next.jsの開発サーバーを立ち上げて、Node.jsランタイム上でNext.jsアプリケーションを実行することも可能ですので、ローカルサイドでもNode.jsは使用される というイメージで理解していただければと思います。

JavaScriptをサーバーサイドで実行するためのランタイム_02

現在、Node.jsはサーバーサイドのアプリケーション開発だけでなく、フロントエンドの開発ツール としても広く使われています。

役割2. Node.jsのパッケージを使用するためのもの

Node.jsは、サーバーサイドでJavaScriptを実行するランタイム環境として知られていますが、それだけでなく、npm というパッケージマネージャーも提供しています。(Node.jsをインストールすると、npmも一緒にインストールされます)

Node.jsのパッケージとは、「TypeScript」や「Prettier」などのツールやライブラリのことを指します。これらを使用するためには、Node.jsをインストールする際に同梱される npm を利用してパッケージをインストールする必要があります。

Node.jsのパッケージは npmレジストリ で公開されており、npmコマンドを使用してインストールできます。

例えば、TypeScriptを使用するためには、以下のコマンドを実行してTypeScriptをインストールします。

npm install -g typescript
npmレジストリ

Next.jsのプロジェクトを作成する際にも、Node.jsのパッケージである create-next-app を使用して、Next.jsのプロジェクトを作成しています。
create-next-app も以下のnpmレジストリで公開されており、npmコマンドを使用してインストールすることができます。

疑問2. npxとは?

次に npx について説明していきます。

コマンドはどのように実行されているのか?

まずは node index.js のように「nodeコマンド」を実行する方法を改めて確認しましょう。

『そんなの知ってるよ!』と思う方もいるかもしれませんが、改めて確認したいと思います。

まず、コマンドを実行するためには コマンドラインツール を使用します。
コマンドラインツールのありかは、以下のコマンドで確認できます。

$ echo $PATH | tr ':' '\n'
・・・
/usr/local/bin
・・・

一般的なコマンドラインツールは /usr/local/bin に配置されており、ここに配置することでコマンドが実行できるようになります。このパスはデフォルトで設定されているパスとなります。

Unix系のオペレーティングシステム(macOSやLinuxなど)では、多くのコマンドラインツールやプログラムが /usr/local/bin ディレクトリにインストールされます。

実際に node のパスを確認すると、以下のようになります。

$ which node
/usr/local/bin/node

node index.js を実行すると、以下のような実行フローになります。

コマンドを実行するには?_01

npmとは何か?

npm は Node.js インストール時に /usr/local/bin にインストールされるので、「npmコマンド」を実行できます。

$ which npm
/usr/local/bin/npm

しかし、/usr/local/bin/npm は、シンボリックリンクが設定されたエイリアスファイルになっています。

npmとは?_02

Node.jsのパッケージは通常 /usr/local/lib/node_modules にインストールされます。そのため、グローバルにコマンドを実行するためには、/usr/local/bin にシンボリックリンクを設定することが一般的です。このシンボリックリンクは、/usr/local/lib/node_modules の実行可能ファイルを刺しています。

npmのシンボリックリンクを確認すると、以下のようになっています。

$ ls -l $(which npm)
lrwxr-xr-x  1 root  wheel  38  5 11 14:33 /usr/local/bin/npm -> ../lib/node_modules/npm/bin/npm-cli.js

これは、/usr/local/bin/npm/usr/local/lib/node_modules/npm/bin/npm-cli.js へのシンボリックリンクであることを示しています。

そのため、npmコマンドを実行すると、/usr/local/lib/node_modules/npm/bin/npm-cli.js のJavaScriptプログラムを実行していることがわかります。

npmとは?_01

Node.jsパッケージをインストールして使用する

Node.jsのパッケージをインストールする際には、「npm」を使用します。

npm install -g {パッケージ名}

このコマンドでパッケージをグローバルにインストールすると、システム全体で使用できるようになります。たとえば、TypeScriptをグローバルにインストールすると、どのディレクトリにいてもTypeScriptコマンドを実行できるようになります。

npm install -g typescript
cd {任意のディレクトリ}
tsc init       ← カレントディレクトリがどこでも実行できる

グローバルにインストールされたパッケージは、実行可能ファイルが /usr/local/bin/ に配置されるため、どこからでもコマンドを実行できます。

$ which tsc
/usr/local/bin/tsc
Node.jsパッケージのインストール_01

なぜ typescript 〜 ではなく tsc 〜 で実行するのかというと、これはnpmパッケージのpackage.jsonファイル内の binプロパティ によるものです。このプロパティを利用して、 パッケージ名とは異なるコマンド名を指定できます。
TypeScriptの場合、binプロパティに tsc が設定されているため、tsc 〜で実行することができます。

{
    "name": "typescript",
    ・・・
    "bin": {
        "tsc": "./bin/tsc"
    },
    ・・・
}

Node.jsのパッケージは通常 /usr/local/lib/node_modules にインストールされますので、TypeScriptも /usr/local/lib/node_modules/typescript/bin/tsc にインストールされることになります。

$ ls -l $(which tsc)
lrwxr-xr-x  1 root  wheel  38  5 11 15:25 /usr/local/bin/tsc -> ../lib/node_modules/typescript/bin/tsc

この出力結果は、/usr/local/bin/tsc/usr/local/lib/node_modules/typescript/bin/tsc へのシンボリックリンクであることを示しています。これにより、tscコマンドをどこからでも実行できるようになっています。

グローバルにインストールされているパッケージの一覧を見てみましょう。以下のコマンドを使用すると、/usr/local/lib/node_modules にインストールされたNode.jsのパッケージを確認できます。

$ npm -g list
/usr/local/lib
・・・・
├── npm@10.5.2
└── typescript@5.4.5

npxとは何か?

ようやく、npxについての説明となります。

npmはパッケージを管理するためのツールで、インストールしたパッケージを管理 します。一方で、npxはパッケージを インストールせずに実行 するためのツールです。これにより、一時的なパッケージの実行や、プロジェクト固有のパッケージの実行が可能になります。

npxのパスを確認すると、以下のようになっています。

$ ls -l $(which npx)
lrwxr-xr-x  1 root  wheel  38  5 11 14:33 /usr/local/bin/npx -> ../lib/node_modules/npm/bin/npx-cli.js

この出力から、/usr/local/bin/npx/usr/local/lib/node_modules/npm/bin/npx-cli.js へのシンボリックリンクであることがわかります。つまり、npxは npmに付属しているツール ということになります。

疑問3. npx create-next-app で何が行われているのか?

「create-next-app」は、Next.jsのプロジェクトを作成するためのパッケージです。このパッケージをグローバルにインストールして使用することもできますが、npxを使用することで、インストールせずに直接実行することが可能です。

npxの動作を理解するためには、実際にコマンドを実行してみるのが最も分かりやすいと思いますので、以下のコマンドを試してみます。

npx create-next-app@latest

このコマンドを実行すると、Next.jsのプロジェクトが作成されます。具体的には、以下の処理が行われています。

  1. まず、カレントディレクトリのnpmプロジェクトに create-next-app というパッケージがインストールされているかを確認します。

    Node.jsが必要な理由_01
  2. もしインストールされていなければ、npmレジストリから create-next-app パッケージをダウンロードし、一時的にインストール します。

    Node.jsが必要な理由_02

    npmレジストリからnpxでパッケージを使用した場合、/Users/{ユーザ名}/.npm/_npx に「一時ディレクトリ」が作成され、その配下に「node_modules」が作成されます。ここにパッケージが一時的にインストールされ、使用されます。

  3. パッケージがインストールされたら、create-next-app を実行し、Next.jsのプロジェクトが作成されます。

    Node.jsが必要な理由_03

このプロセスにより、グローバルにパッケージをインストールせずにパッケージを実行することができる のがnpxの特徴です。

疑問4. npm run dev とは何をしているのか?

npm run {スクリプト名} は、package.jsonscripts セクションに記述されたスクリプトを実行するコマンドです。例えば、Next.jsプロジェクトの package.jsondev というスクリプトが next dev というコマンドを実行するように定義されています。

npm_run_devとは_02

このため、devスクリプト は実質的に next dev を実行します。

npm_run_devとは_01

next dev コマンドを使用すると、Next.jsの開発サーバーが起動します。ただし、「nextパッケージ」はNext.jsプロジェクトの「node_modules」に配置されているため、カレントディレクトリがNext.jsプロジェクト内である場合のみ 使用できます。

プロジェクト固有のパッケージを使用したい場合は npx を利用します。この場合、npx next dev と実行することで、プロジェクト内で使用可能な next パッケージ使用し、npm run dev と同様の動作を行うことができます。

まとめ

今回は、Next.jsプロジェクト作成の裏側で行われていることを学びながら解説しました。以前はこの辺りの知識が曖昧で、不明確な説明をしてしまうことがありましたが、今回の学習を記事にまとめたことで、より詳細で正確な説明ができるようになったと思います。

基本的なコマンド実行の仕組みやnpmの仕組みを理解することで、今後の開発での問題解決や応用に役立つため、他の技術に対しても同じアプローチで、基礎からしっかりと学習を進めることが重要だと感じました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1