はじめに
Amplify Gen 2 のクイックスタートで作ったプロジェクトに、ライブラリを追加したときの話。
そもそも私自身プログラマではないため、結構あいまいな状態で Node.js を使ったアプリを Kiro といっしょに作っていました。
今回は、OIDC プロキシ用の jose(JWT ライブラリ)の追加が必要になった際、
「あれ、具体的に何すれば良いんだっけ?」
となり、改めて npm とか package.json とか調べてみたので、まとめておきます。
Amplify クイックスタートの package.json を読み解く
まず、Amplify Gen 2 のクイックスタートで生成される package.json を見てみます。
{
"dependencies": {
"@aws-amplify/ui-react": "^6.x",
"aws-amplify": "^6.x",
"react": "^19.x",
"react-dom": "^19.x"
},
"devDependencies": {
"@aws-amplify/backend": "^1.x",
"@aws-amplify/backend-cli": "^1.x",
"@types/react": "^19.x",
"@types/react-dom": "^19.x",
"aws-cdk": "^2",
"aws-cdk-lib": "^2",
"constructs": "^10.x",
"typescript": "^5.x"
}
}
これらがこのプロジェクトで利用するライブラリ群です。
dependencies と devDependencies に分かれて記載されているのが見えます。
両者の使い分けはどの様になっているのでしょうか?
判断基準: 「本番で実行されるか?」
答えはシンプルです。
-
dependencies:本番でアプリの実行に使われるパッケージ -
devDependencies:開発・ビルド時にのみ必要なパッケージ
この基準でクイックスタートの分類を見直すと、、、
dependencies(本番で実行される):
-
react,react-dom— Reactで作った画面をブラウザへ表示する -
aws-amplify— AWSサービスとフロントエンドを接続。 Cognito 認証などに使用 -
@aws-amplify/ui-react— Amplify用のReact UIコンポーネント集
devDependencies(ビルド時のみ):
-
@aws-amplify/backend— Amplify Gen2 のバックエンド定義ライブラリ -
aws-cdk-lib,constructs— AWS CDK で必要なライブラリ -
typescript— コンパイル時にエラー検知 -
@types/*— TypeScriptでReactを書くために必要
つまり 「本番環境でそのコードが実行されるか?」 で判断しています。
ライブラリの追加方法は?
今回追加した jose は Lambda の中で JWT 署名に使います。
- Lambda は本番で実行される ✅
-
joseのコードは Lambda 内でimportされて実際に動く ✅
→ dependencies に追加する
npm install jose
さらに @types/node と tsx も追加しました。
それぞれ、以下のようにビルド時に使われます。
-
@types/node:TypeScript の型定義。本番では不要 -
tsx:@aws-amplify/backend-cli が内部的に必要。ビルド時のみ
→ devDependencies に追加する
npm install -D @types/node tsx
補足: npm / package.json の基礎知識
自分への備忘録も兼ねて、非プログラマ向けに前提となる基礎知識を整理しておきます。
npm とは
npm(Node Package Manager) は、Node.js に付属するパッケージマネージャーです。「ライブラリを追加・管理するためのコマンド」というイメージ。
# jose というライブラリをプロジェクトに追加する
npm install jose
これを実行すると:
-
joseのコードがnode_modules/フォルダにダウンロードされる -
package.jsonのdependenciesにjoseが記録される -
package-lock.jsonにバージョンが固定される
package.json とは
プロジェクトが使うライブラリの一覧表です。チームで開発するとき、全員が同じライブラリを使えるようにするための設定ファイルです。
{
"name": "my-app",
"dependencies": {
"jose": "^6.x"
},
"devDependencies": {
"typescript": "^5.x"
}
}
新しくプロジェクトをクローンした人が npm install を実行すると、この一覧に書かれたライブラリが全部インストールされます。
テンプレートを配布する際にも便利ですよね。
ここで、ライブラリのバージョンを指定する際に ^5.x のような表記をすることがあります。
これはバージョンの範囲を示しており、^は「メジャーバージョン5系なら、自動で新しいものを使ってOK」ということを意味します。^5.x の例だと、>=5.0.0 <6.0.0 となり、メジャーバージョン6系以降は使われないこととなります。
node_modules とは
npm install でダウンロードされたライブラリの実体が入るフォルダです。容量が大きいため Git にはコミットせず(.gitignore で除外)、各自が npm install で復元します。
package-lock.json とは
package.json にはバージョンの範囲が書かれていますが、package-lock.json は「実際にインストールされたバージョン」を正確に記録するファイルとなります。
-
package.json: 「jose の 6 系を使う」(範囲指定) -
package-lock.json: 「jose の 6.0.11 を使う」(完全固定)
これにより、チームメンバー全員や CI/CD 環境でまったく同じバージョンのライブラリが再現されます。package-lock.json は Git にコミットしてください。
チーム開発の場合は運用ルール含めもう少し工夫する必要がある気はしますが、今回はこれ以上の言及は避けます。
npm ci とは
npm ci コマンドは package-lock.json を厳密に再現するインストール方法です。
Amplify Hosting のビルド環境でも npm ci が使われており、ロック通りのバージョンがインストールされます。
npm install のオプション
# dependencies に追加(本番で使うもの)
npm install jose
# devDependencies に追加(開発時のみ使うもの)
npm install -D typescript
# -D は --save-dev の省略形
この「どっちに入れるか」が本記事のテーマでした。
まとめ
今回は dependencies と devDependencies の違いについて簡単にまとめてみました。
| パッケージ | 分類 | 理由 |
|---|---|---|
jose |
dependencies | Lambda で JWT 署名に使用。本番で実行される |
@types/node |
devDependencies | 型定義。本番では不要 |
tsx |
devDependencies | ビルドツール。本番では不要 |
判断基準はシンプル: 「本番環境でそのコードが実行されるか?」
Amplify クイックスタートの package.json が良いお手本になるので、迷ったときはそこを見返してみてください。