Node.js Express.js
1. Express.jsとは?
Express.js(または単にExpress)は、WebアプリケーションやAPIを構築するために設計された、最もポピュラーなNode.js Webアプリケーションフレームワークです。
Node.jsにおける「デファクトスタンダード」のサーバーフレームワークとして広く認知されています。
主な特徴:
- ミニマルかつ柔軟: 必要最小限の機能を提供し、自由度が高い。
- アンオピニオンネイテッド(Unopinionated): アプリケーションの構造を開発者が自由に決定できる。
- 軽量で高速: オーバーヘッドが少なく、パフォーマンスに優れる。
- ミドルウェアによる拡張性: 豊富なミドルウェアを組み合わせて機能を拡張可能。
- 巨大なエコシステム: 膨大な数のプラグインや拡張機能が存在する。
2. なぜExpress.jsを選ぶのか?
Expressは、Node.jsの機能を隠蔽することなく、Webアプリケーションに必要な基本機能の薄いレイヤーを提供します。
提供される主な機能:
- 堅牢なルーティング(Routing)システム
- HTTPヘルパー(リダイレクト、キャッシングなど)
- HTTPリクエストに応答するためのミドルウェアサポート
- 動的なHTMLレンダリングのためのテンプレートエンジン
- エラーハンドリング用ミドルウェア
3. Expressを始める
ExpressはあらゆるNode.jsプロジェクトに追加できます。新しいExpressアプリケーションの開始方法は以下の通りです。
3.1 前提条件
開始する前に、以下が準備されていることを確認してください:
- Node.jsのインストール(v14.0.0以降を推奨)
- npm(Node.jsに付属)または yarn
- コードエディタ(VS Code, WebStormなど)
3.2 Expressのインストール
Node.jsアプリケーションでExpressを使用するには、まずインストールが必要です:
npm install expressExpressをインストールし、package.jsonの依存関係(dependencies)に保存する場合:
npm install express --save4. Hello Worldの例
Expressを使用したシンプルな「Hello World」アプリケーションを作成してみましょう。
この例は、Expressアプリケーションの基本的な構造を示しています。
主要な構成要素:
- Expressモジュールのインポート
- Expressアプリケーションインスタンスの作成
- ルートの定義
- サーバーの起動
const express = require('express');
const app = express();
const port = 8080;
// ルートURLへのGETリクエストに対するルートを定義
app.get('/', (req, res) => {
res.send('ExpressからのHello World!');
});
// サーバーの起動
app.listen(port, () => {
console.log(`サンプルアプリが http://localhost:${port} で待機中です`);
});このコードをapp.jsという名前で保存し、Node.jsで実行します:node app.js
その後、ブラウザで http://localhost:8080 にアクセスすると、「Hello World」メッセージが表示されます。
5. 基本的なルーティング(Basic Routing)
ルーティングとは、アプリケーションが特定のエンドポイント(URI)へのクライアントリクエストに対して、異なるHTTPメソッド(GET, POST, PUT, DELETEなど)を使用してどのように応答するかを指します。
Expressは、HTTPメソッドに対応するルートを定義するためのシンプルなメソッドを提供します:
app.get()- GETリクエストを処理app.post()- POSTリクエストを処理app.put()- PUTリクエストを処理app.delete()- DELETEリクエストを処理app.all()- すべてのHTTPメソッドを処理
const express = require('express');
const app = express();
const port = 8080;
// ルートパスへのGETリクエストに応答
app.get('/', (req, res) => {
res.send('ホームページへのGETリクエスト');
});
// ルートパスへのPOSTリクエストに応答
app.post('/', (req, res) => {
res.send('ホームページへのPOSTリクエスト');
});
// /aboutパスへのGETリクエストに応答
app.get('/about', (req, res) => {
res.send('アバウトページ');
});
// 他のすべてのルートをキャッチ
app.all('*', (req, res) => {
res.status(404).send('404 - ページが見つかりません');
});
app.listen(port, () => {
console.log(`サーバーが起動しました: http://localhost:${port}`);
});6. ルートパラメータ(Route Parameters)
ルートパラメータは、URL内の特定の値をキャプチャする名前付きのURLセグメントです。
パス内でコロン : プレフィックスを付けて指定します。
例:/users/:userId/books/:bookId
この例では、userId と bookId がルートパラメータであり、req.params を介してアクセスできます。
const express = require('express');
const app = express();
const port = 8080;
// パラメータを含むルート
app.get('/users/:userId/books/:bookId', (req, res) => {
// req.paramsを使用してパラメータにアクセス
res.send(`ユーザーID: ${req.params.userId}, 本ID: ${req.params.bookId}`);
});
app.listen(port, () => {
console.log(`サーバーが実行中: http://localhost:${port}`);
});7. クエリパラメータ(Query Parameters)
クエリパラメータは、URLの ? の後に続くキーと値のペアです。
Expressによって自動的にパースされ、req.query で利用可能になります。
例:http://example.com/search?q=express&page=2
このURLでは、q=express と page=2 がクエリパラメータであり、req.query.q および req.query.page としてアクセスできます。
const express = require('express');
const app = express();
const port = 8080;
// クエリパラメータを処理するルート
app.get('/search', (req, res) => {
// req.queryを使用してクエリパラメータにアクセス
const { q, category } = req.query;
res.send(`検索クエリ: ${q}, カテゴリ: ${category || 'なし'}`);
});
app.listen(port, () => {
console.log(`検索APIが待機中: http://localhost:${port}`);
});8. Expressにおけるミドルウェア
ミドルウェア関数は、Expressアプリケーションのバックボーンです。
以下の要素にアクセスできます:
- リクエストオブジェクト (req)
- レスポンスオブジェクト (res)
- スタック内の次のミドルウェア関数 (next)
ミドルウェアができること:
- 任意のコードの実行
- リクエストおよびレスポンスオブジェクトの変更
- リクエスト・レスポンスサイクルの終了
- スタック内の次のミドルウェアの呼び出し
8.1 組み込みミドルウェア
Expressには、いくつかの便利な組み込みミドルウェアが含まれています:
express.json()- JSONリクエストボディをパースexpress.urlencoded()- URLエンコードされたリクエストボディをパースexpress.static()- 静的ファイルを配信express.Router()- モジュール化されたルートハンドラを作成
const express = require('express');
const app = express();
const port = 8080;
// JSONリクエストボディをパースするためのミドルウェア
app.use(express.json());
// URLエンコードされたリクエストボディをパースするためのミドルウェア
app.use(express.urlencoded({ extended: true }));
// publicディレクトリから静的ファイルを配信するためのミドルウェア
app.use(express.static('public'));
// JSONミドルウェアを使用するPOSTルート
app.post('/api/users', (req, res) => {
// req.bodyにパースされたJSONデータが含まれる
console.log(req.body);
res.status(201).json({ message: 'ユーザーが作成されました', user: req.body });
});
app.listen(port, () => {
console.log(`ミドルウェアデモ実行中: http://localhost:${port}`);
});9. Expressにおけるエラーハンドリング
Expressのエラーハンドリングは、4つの引数 (err, req, res, next) を持つ特別なミドルウェア関数を通じて行われます。
ポイント:
- エラーハンドリングミドルウェアは必ず4つの引数を持つ必要がある
- 他の
app.use()やルート呼び出しの後に定義する必要がある - 複数のエラーハンドリングミドルウェアを定義可能
next(err)を使用してエラーを次のハンドラに渡す
const express = require('express');
const app = express();
const port = 8080;
// エラーを投げる可能性のあるルート
app.get('/error', (req, res) => {
// エラーのシミュレーション
throw new Error('何かがうまくいきませんでした!');
});
// 非同期コードでnext(error)を使用するルート
app.get('/async-error', (req, res, next) => {
// 失敗する非同期操作のシミュレーション
setTimeout(() => {
try {
// 失敗する可能性のある処理
const result = nonExistentFunction(); // ここでエラーが発生
res.send(result);
} catch (error) {
next(error); // エラーをExpressに渡す
}
}, 100);
});
// カスタムエラーハンドリングミドルウェア
// エラーハンドラーとして認識されるために4つのパラメータが必要
app.use((err, req, res, next) => {
console.error(err.stack);
res.status(500).send('サーバーエラーが発生しました!');
});
app.listen(port, () => {
console.log(`エラーハンドリングデモ: http://localhost:${port}`);
});10. 静的ファイルの配信
Expressは、組み込みの express.static ミドルウェアを使用して、画像、CSS、JavaScriptなどの静的ファイルを配信できます。
ベストプラクティス:
- 静的ファイルは専用のディレクトリ(通常は
publicまたはstatic)に配置する - ルート定義の前に静的ミドルウェアをマウントする
- 本番環境ではパフォーマンス向上のために CDN の使用を検討する
- 静的アセットに適切なキャッシュヘッダーを設定する
const express = require('express');
const path = require('path');
const app = express();
const port = 8080;
// 'public'ディレクトリから静的ファイルを配信
app.use(express.static('public'));
// 仮想パスプレフィックスを指定することも可能
app.use('/static', express.static('public'));
// 絶対パスの使用(推奨)
app.use('/assets', express.static(path.join(__dirname, 'public')));
app.get('/', (req, res) => {
res.send(`
<h1>静的ファイル配信の例</h1>
<img src="/images/logo.png" alt="ロゴ">
<link rel="stylesheet" href="/css/style.css">
<script src="/js/script.js"></script>
`);
});
app.listen(port, () => {
console.log(`静的ファイルサーバー: http://localhost:${port}`);
});11. 別ファイルでのルーティング
構成を整理するために、Express Router を使用してルートを別々のファイルに定義できます。
routes/users.js
const express = require('express');
const router = express.Router();
// このルーター専用のミドルウェア
router.use((req, res, next) => {
console.log('ユーザー・ルーターの時刻:', Date.now());
next();
});
router.get('/', (req, res) => {
res.send('ユーザーホームページ');
});
router.get('/:id', (req, res) => {
res.send(`ID: ${req.params.id} のユーザープロファイル`);
});
module.exports = router;app.js (メインファイル)
const express = require('express');
const usersRouter = require('./routes/users');
const app = express();
const port = 8080;
// ルーターの使用
app.use('/users', usersRouter);
app.get('/', (req, res) => {
res.send('メインアプリケーションのホームページ');
});
app.listen(port, () => {
console.log(`モジュール化ルーティング実行中: http://localhost:${port}`);
});12. テンプレートエンジン
Expressは、動的なHTMLを生成するためにテンプレートエンジンを設定できます。
const express = require('express');
const app = express();
const port = 8080;
// ビューエンジンをEJSに設定
app.set('view engine', 'ejs');
// テンプレートが配置されているディレクトリを設定
app.set('views', './views');
app.get('/', (req, res) => {
const data = {
title: 'Expressテンプレートの例',
message: 'EJSからのこんにちは!',
items: ['アイテム 1', 'アイテム 2', 'アイテム 3']
};
// views/index.ejsテンプレートをレンダリング
res.render('index', data);
});
app.listen(port, () => {
console.log(`テンプレートデモ実行中: http://localhost:${port}`);
});※ 使用には npm install ejs が必要です。
13. Express Application Generator
Express Application Generator は、Expressアプリケーションのスケルトンを迅速に作成するためのツールです。
主な特徴:
- 適切に構造化されたアプリケーションを作成
- 開発環境のセットアップ
- 一般的なミドルウェアの設定
- エラーハンドリングの組み込み
- 各種テンプレートエンジンのサポート
使用方法:
# ジェネレーターをグローバルにインストール
npm install -g express-generator
# 新しいExpressアプリケーションを作成
express --view=ejs myapp
# ディレクトリに移動してインストール・起動
cd myapp
npm install
npm start14. Express.js ベストプラクティス
堅牢でメンテナンス性の高いExpressアプリケーションを構築するためのベストプラクティスです:
- プロジェクト構造: 機能やコンポーネントごとにコードを整理する。
- 環境変数: 設定には
dotenvを使用する。 - エラーハンドリング: エラーハンドリングを集中管理する。
- ロギング:
morganやwinstonなどのロギングライブラリを使用する。 - セキュリティ: Helmet やレート制限(rate limiting)などのセキュリティ対策を実装する。
- バリデーション:
express-validatorなどのライブラリを使用して入力を検証する。
14.1 セキュリティのベストプラクティス
const express = require('express');
const helmet = require('helmet');
const cors = require('cors');
const app = express();
// セキュリティミドルウェア(HTTPヘッダーの設定)
app.use(helmet());
// CORSの設定
app.use(cors({
origin: 'https://example.com',
methods: ['GET', 'POST'],
allowedHeaders: ['Content-Type', 'Authorization']
}));14.2 パフォーマンスのベストプラクティス
compressionミドルウェアを使用してレスポンスを圧縮する。- 適切なキャッシング戦略を実装する。
- 本番環境では Nginx などのリバースプロキシを前面に配置することを検討する。
- Clustering を使用してマルチコアシステムを最大限に活用する。
- データベースクエリを最適化する。