一覧へ

静的ファイルの提供とエラー処理

Express で HTML、CSS、画像を配信し、404 および 500 エラーをきれいに処理する方法を学びます。

中級
|
10
|
検証済み (2026-07)
静的ファイルExpressエラー処理404ページミドルウェア
進捗0/55 (0%)

静的ファイルの配信とエラー処理

このトピックを終えると

Expressで、HTML、CSS、画像などの静的ファイルを配信し、404(ページが見つかりません)と500(サーバーエラー)のエラーを構造的に処理できるようになります。


静的ファイルとは

ウェブサーバーが処理するファイルには、2種類あります。

  • 動的ファイル: リクエストごとにサーバーがコードを実行して生成するレスポンス(API、データベースクエリの結果)
  • 静的ファイル: サーバーがそのまま転送するだけファイル(HTML、CSS、JavaScript、画像、フォント)

ブログの記事一覧は動的ですが、ブログのロゴ画像とスタイルシートは静的です。静的ファイルは、リクエストが来るたびに新しく作成する必要がないため、別のミドルウェアが効率的に処理します。


express.static — 静的ファイルミドルウェア

Expressは、express.static()ミドルウェアを内蔵しています。

text
project/
├── app.js
├── public/
│   ├── index.html
│   ├── css/
│   │   └── style.css
│   ├── js/
│   │   └── main.js
│   └── images/
│       └── logo.png
javascript
const express = require('express');
const path = require('path');
const app = express();

// publicフォルダを静的ファイルのルートとして設定
app.use(express.static(path.join(__dirname, 'public')));

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});

これで、ブラウザでhttp://localhost:3000/css/style.cssにアクセスすると、public/css/style.cssファイルが返されます。URLに/publicを付けなくても、express.staticpublicフォルダをルートにマッピングするためです。

URLプレフィックスの追加

javascript
// /assets/css/style.cssとしてアクセス
app.use('/assets', express.static(path.join(__dirname, 'public')));

最初の引数がURLプレフィックスです。このようにすると、実際のファイルパスはpublic/css/style.cssですが、URLは/assets/css/style.cssになります。CDNやバージョン管理のためにパスを分離する場合に便利です。

複数のフォルダの指定

javascript
app.use(express.static(path.join(__dirname, 'public')));
app.use(express.static(path.join(__dirname, 'uploads')));

2つのフォルダを静的ファイルのソースとして登録できます。最初のフォルダで見つからない場合、2番目のフォルダを検索します。順序が優先順位になります。


path.join__dirname — パスを安全に作成する

javascript
// Bad: 相対パス — 実行場所によって異なる
app.use(express.static('public'));

// Good: 絶対パス — どこで実行しても同じ
app.use(express.static(path.join(__dirname, 'public')));

__dirnameは、現在のファイルが存在するディレクトリの絶対パスです。path.join()は、OSに合ったパス区切り文字(/または\)を自動的に処理します。Windowsで/を直接記述すると問題が発生する可能性があるため、常にpath.joinを使用します。


404処理 — ページが見つからない

Expressで、どのルートにも一致しない場合、リクエストは単に破棄されます。クライアントは応答を永遠に待ち続けます。これを防ぐには、すべてのルートの後に404ハンドラーを配置する必要があります。

javascript
// ルートの定義
app.get('/', (req, res) => {
  res.send('Home');
});

app.get('/about', (req, res) => {
  res.send('About');
});

// 404ハンドラー — すべてのルートの後に、エラーハンドラーの前に
app.use((req, res) => {
  res.status(404).json({
    error: 'Not Found',
    message: `${req.method} ${req.url} does not exist`,
    status: 404
  });
});

位置が重要です。app.use()は順序どおりに実行されるため、404ハンドラーを最初に配置すると、すべてのリクエストが404になります。必ずすべてのルート定義の後に配置する必要があります。

HTML 404ページ

APIサーバーではなく、ウェブサイトの場合、JSONではなくHTMLページを表示する方が自然です。

javascript
app.use((req, res) => {
  res.status(404).sendFile(path.join(__dirname, 'public', '404.html'));
});

500処理 — サーバー内部エラー

エラー処理ミドルウェアは、パラメータが4つです。Expressは、このシグネチャで通常のミドルウェアとエラーハンドラーを区別します。

javascript
// エラーハンドラー — 404ハンドラーの後に
app.use((err, req, res, next) => {
  console.error(`[ERROR] ${err.stack}`);

  res.status(err.status || 500).json({
    error: 'Internal Server Error',
    message: process.env.NODE_ENV === 'production'
      ? 'Something went wrong'
      : err.message,
    status: err.status || 500
  });
});

注意すべき点2つ:

  1. 本番環境では、エラーメッセージを非表示にしますerr.messageにSQLクエリやファイルパスなどの機密情報が含まれている可能性があるためです。開発環境でのみ詳細なメッセージを表示します。

  2. エラーをスローする方法: ルート内でnext(err)を呼び出すと、エラーハンドラーにジャンプします。

javascript
app.get('/users/:id', async (req, res, next) => {
  try {
    const user = await findUser(req.params.id);
    if (!user) {
      const err = new Error('User not found');
      err.status = 404;
      return next(err);
    }
    res.json(user);
  } catch (err) {
    next(err); // DBエラーなど、予期しないエラー
  }
});

全体の構造 — 正しい順序

javascript
const express = require('express');
const path = require('path');
const app = express();

// 1. 基本ミドルウェア
app.use(express.json());
app.use(express.static(path.join(__dirname, 'public')));

// 2. ルート
app.get('/api/users', (req, res) => { /* ... */ });
app.post('/api/users', (req, res) => { /* ... */ });

// 3. 404ハンドラー(ルートの後)
app.use((req, res) => {
  res.status(404).json({ error: 'Not Found' });
});

// 4. エラーハンドラー(常に最後)
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ error: 'Internal Server Error' });
});

app.listen(3000);

この順序は、Expressプロジェクトの標準的な構造です。基本ミドルウェア → ルート → 404 → エラー。この順序を破ると、予期しない動作が発生します。


実際に起こりがちな間違い

間違い症状解決
404ハンドラーがルートより前すべてのリクエストが404404を一番後ろに移動
エラーハンドラーのパラメータが3つエラーがキャッチされない(err, req, res, next) 4つ必須
express.staticのパスが相対別のフォルダで実行するとファイルが見つからないpath.join(__dirname, ...)
エラーでnext(err)を呼び出さないエラーハンドラーに到達しないtry/catch + next(err)
本番環境でerr.stackを公開セキュリティ上の脆弱性NODE_ENVで分岐

重要なまとめ

静的ファイルとエラー処理は、「サーバーが正常なとき」と「異常なとき」の両方を処理することです。express.staticはファイルを効率的に配信し、404/500ハンドラーは、例外的な状況でもユーザーに意味のある応答を提供します。Expressのミドルウェアの順序(パース → 静的 → ルート → 404 → エラー)を覚えておくと、何をどこに配置すればよいかわからなくなることはありません。

💬 質問・コメント

0件のコメント

ログインせずに投稿できます。ゲスト投稿は投稿者自身で編集・削除できません。

0/2000

読み込み中...