express vs koa vs hapi vs sails
Node.js 向けバックエンドフレームワークの選定ガイド
expresskoahapisails類似パッケージ:

Node.js 向けバックエンドフレームワークの選定ガイド

expresshapikoasails は、Node.js 環境で Web サーバーや API を構築するための代表的なフレームワークです。express は最小限の設計で広く使われており、koa は非同期処理に強く、hapi は設定重視のエンタープライズ向け、sails は MVC 構造とリアルタイム機能を備えたフルスタックフレームワークです。それぞれ設計思想が大きく異なるため、プロジェクトの規模や要件に合わせて選ぶ必要があります。

npmのダウンロードトレンド

3 年

GitHub Starsランキング

統計詳細

パッケージ
ダウンロード数
Stars
サイズ
Issues
公開日時
ライセンス
express71,720,99068,88675.4 kB1914ヶ月前MIT
koa5,588,06835,74565 kB3321日前MIT
hapi57,57414,783-587年前BSD-3-Clause
sails27,09522,8433.27 MB5891ヶ月前MIT

Express vs Hapi vs Koa vs Sails:アーキテクチャと実装の比較

これら 4 つのフレームワークは、Node.js でサーバーサイドアプリケーションを作るための道具ですが、作り方や考え方が大きく異なります。expresskoa はコードで制御するタイプ、hapi は設定で制御するタイプ、sails はすべて込みのフルスタックタイプです。実際の開発現場でどう違うのか、主要な機能ごとに比較します。

🏗️ 基本構造:ミドルウェア vs 設定 vs MVC

express はミドルウェア関数を積み重ねて処理を作ります。

  • リクエストが来てからレスポンスを返すまで、関数の連鎖で処理します。
  • 自由度が高く、シンプルな構造です。
// express: ミドルウェアチェーン
const express = require('express');
const app = express();

app.use((req, res, next) => {
  console.log('Time:', Date.now());
  next();
});

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

koa もミドルウェアを使いますが、非同期処理が書きやすい構造です。

  • next()await して、前後の処理を挟み込めます。
  • reqres が分かれておらず、ctx 1 つにまとまっています。
// koa: 非同期ミドルウェア
const Koa = require('koa');
const app = new Koa();

app.use(async (ctx, next) => {
  console.log('Time:', Date.now());
  await next();
});

app.use(async (ctx) => {
  ctx.body = 'Hello World';
});

hapi はコードではなく設定オブジェクトでサーバーを定義します。

  • 関数をつなぐのではなく、設定項目を埋めます。
  • 大規模なシステムで統一感を出しやすいです。
// hapi: 設定ベース (@hapi/hapi)
const Hapi = require('@hapi/hapi');

const init = async () => {
  const server = Hapi.server({ port: 3000 });
  
  server.route({
    method: 'GET',
    path: '/',
    handler: (request, h) => {
      return 'Hello World';
    }
  });

  await server.start();
};

sails は MVC(モデル・ビュー・コントローラー)構造を強制します。

  • ファイル配置や命名規則に従うことで、自動で機能が生えます。
  • 初速が速いですが、ルールに従う必要があります。
// sails: Controller 動作 (api/controllers/HomeController.js)
module.exports = {
  index: async function (req, res) {
    return res.ok('Hello World');
  }
};

// config/routes.js
'get /': 'HomeController.index'

🛣️ ルーティング:コード定義 vs 設定ファイル

express はコード内でパスと関数を紐付けます。

  • app.getapp.post で直感的に書けます。
  • 複雑なルートでもコードで管理します。
// express: コードでルーティング
app.get('/users/:id', (req, res) => {
  const id = req.params.id;
  res.send(`User ${id}`);
});

koa はルーティング機能自体がないため、ライブラリを追加します。

  • @koa/router などが一般的です。
  • Express と似た書き方になります。
// koa: router ライブラリ使用
const Router = require('@koa/router');
const router = new Router();

router.get('/users/:id', (ctx) => {
  ctx.body = `User ${ctx.params.id}`;
});

app.use(router.routes());

hapi は設定オブジェクト内にパスを定義します。

  • ルート設定が明確に分離されます。
  • 検証ルールなどもここで一緒に書きます。
// hapi: 設定でルーティング
server.route({
  method: 'GET',
  path: '/users/{id}',
  options: {
    validate: {
      params: {
        id: Joi.number().integer()
      }
    }
  },
  handler: (request) => {
    return `User ${request.params.id}`;
  }
});

sails は設定ファイルまたはブループリント機能を使います。

  • config/routes.js で URL とコントローラーを紐付けます。
  • 何もしなくても自動で CRUD 経路ができる場合があります。
// sails: 設定ファイル (config/routes.js)
module.exports.routes = {
  'get /users/:id': 'UserController.findOne'
};

⚡ 非同期処理:コールバック vs async/await

express は伝統的にコールバックを使いますが、現在は async/await も使えます。

  • next() 関数を呼ぶ必要があります。
  • エラー処理は next(err) で行います。
// express: async/await 対応
app.get('/data', async (req, res, next) => {
  try {
    const data = await fetchData();
    res.json(data);
  } catch (err) {
    next(err);
  }
});

koa は最初から async/await を前提に作られています。

  • next()await するのが基本です。
  • コードがフラットになり、読みやすいです。
// koa: 自然な async/await
app.use(async (ctx, next) => {
  const data = await fetchData();
  await next();
  ctx.body = data;
});

hapi はハンドラー関数を async 定義できます。

  • 戻り値を返すだけでレスポンスになります。
  • try/catch でエラーを返すこともできます。
// hapi: async handler
server.route({
  method: 'GET',
  path: '/data',
  handler: async (request) => {
    const data = await fetchData();
    return data;
  }
});

sails はコントローラー内で async/await を使います。

  • res.ok()res.serverError() でレスポンスを制御します。
  • Waterline ORM なども Promise に対応しています。
// sails: async controller
module.exports = {
  getData: async function (req, res) {
    try {
      const data = await fetchData();
      return res.ok(data);
    } catch (err) {
      return res.serverError(err);
    }
  }
};

🛡️ エラー処理:自動 vs 手動

express はエラーミドルウェアで一括処理します。

  • 最後尾にエラー用の関数を置きます。
  • next(err) を呼ぶとそこに飛びます。
// express: エラーミドルウェア
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

koa はアプリレベルでエラーをキャッチします。

  • app.on('error') でログ出力などを行います。
  • 個別のミドルウェアで try/catch することも多いです。
// koa: エラーイベント
app.on('error', (err) => {
  log.error(err, 'server error');
});

// ミドルウェア内
app.use(async (ctx) => {
  try {
    // ... processing
  } catch (err) {
    ctx.status = err.status || 500;
    ctx.body = err.message;
  }
});

hapi は拡張機能(plugins)でエラーを処理します。

  • onPreResponse 拡張ポイントを使います。
  • 統一されたエラーレスポンス形式を作りやすいです。
// hapi: 拡張機能でエラー処理
server.ext('onPreResponse', (request, h) => {
  const response = request.response;
  if (response.isBoom) {
    // 統一フォーマットに変換など
  }
  return h.continue;
});

sails はポリシーやレスポンス設定で処理します。

  • config/responses.js でエラー形式を定義できます。
  • 500 エラーなどは自動でハンドリングされます。
// sails: config/responses.js
module.exports.responses = {
  serverError: function (err) {
    // 統一エラー処理
    return this.res.status(500).json({ error: err });
  }
};

📦 機能範囲:最小限 vs 全部入り

express は必要最小限です。

  • データベースや認証機能は自分で選びます。
  • 好きなライブラリを組み合わせられます。
// express: 自分でライブラリを選ぶ
const mongoose = require('mongoose');
const passport = require('passport');
// 自由に構成

koa さらに最小限です。

  • ボディパーサーさえデフォルトではありません。
  • 必要なものだけを追加します。
// koa: 必要なミドルウェアを追加
const bodyParser = require('koa-bodyparser');
app.use(bodyParser());

hapi は検証や認証機能が充実しています。

  • joi による入力検証が組み込みやすいです。
  • 認証プラグインも公式で提供されています。
// hapi: 検証機能
options: {
  validate: {
    payload: Joi.object({
      username: Joi.string().required()
    })
  }
}

sails は全部入りです。

  • ORM、WebSocket、認証などが最初からあります。
  • 設定するだけで動く機能が多いです。
// sails: 自動機能
// models/User.js を作るだけで DB テーブルが生成される
// sockets 設定でリアルタイム通信が可能

📊 類似点:共通する基盤

これらはすべて Node.js で動作し、HTTP リクエストを処理するという点では同じです。

1. 🟢 JavaScript/TypeScript 対応

  • すべて JavaScript で書けます。
  • TypeScript の型定義もコミュニティで用意されています。
// すべて JS/TS で実装可能
// const app = express(); (TS なら型推効く)

2. 🔌 ミドルウェア/プラグイン機構

  • 機能を追加する仕組みを持っています。
  • 認証、ログ、圧縮などを後から足せます。
// express
app.use(compression());
// koa
app.use(compress());
// hapi
await server.register(require('hapi-compression'));
// sails
config.http.middleware order 設定

3. 🌐 HTTP 標準準拠

  • ステータスコード、ヘッダー、メソッドを標準通りに扱います。
  • REST API 構築に適しています。
// すべて status code 設定可能
res.status(200); // express
ctx.status = 200; // koa
return h.response().code(200); // hapi
return res.ok(); // sails

📝 結論:選び方の基準

express — 迷ったらこれ。情報が多く、困ったときに解決策が見つかりやすいです。標準的な API サーバーに最適です。

koa — 非同期処理をきれいに書きたい場合に選ります。ミドルウェア開発者や、軽量な構成を好むチームに向いています。

hapi — 設定で管理したい大規模システムに適しています。ただし、パッケージ名は @hapi/hapi を使うのが現在のルールです。

sails — 手軽にフルスタックアプリを作りたい時に使います。ルールに従えるなら、開発速度は最も速くなる可能性があります。

💡 最終的なアドバイス

プロジェクトが小さい場合や、カスタマイズを重視する場合は expresskoa が無難です。大規模で統一されたルールが必要な場合は hapi、とにかく早く形にしたい場合は sails を検討してください。重要なのは、チームの習熟度と、将来のメンテナンス性を考慮することです。

選び方: express vs koa vs hapi vs sails

  • express:

    標準的な API サーバーやマイクロサービス構築に最適です。ミドルウェアの生態系が非常に豊富で、情報も多いため、迷ったときの第一選択になります。学習コストが低く、既存のライブラリとの連携もスムーズです。

  • koa:

    非同期処理(async/await)を自然に扱いたい場合に適しています。Express の開発チームが作成しており、軽量で柔軟です。ミドルウェアを自作する際や、最新の JavaScript 機能を積極的に使いたいプロジェクトで選ばれます。

  • hapi:

    設定ファイルで動作を制御したい大規模なシステムに向いています。入力検証やセキュリティ機能が最初から強く備わっており、堅牢な API 構築に適しています。ただし、hapi ではなく @hapi/hapi を使用するのが現在の標準です。

  • sails:

    データベース連携や WebSocket 機能を素早く実装したい場合に有効です。MVC パターンに従っており、フロントエンド開発者がバックエンドも担当する際の生産性が高いです。ただし、フレームワークの仕組みに深く依存するため、カスタマイズには注意が必要です。

express のREADME

Express Logo

Fast, unopinionated, minimalist web framework for Node.js.

This project has a Code of Conduct.

Table of contents

NPM Version NPM Downloads Linux Build Test Coverage OpenSSF Scorecard Badge

import express from 'express'

const app = express()

app.get('/', (req, res) => {
  res.send('Hello World')
})

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

Installation

This is a Node.js module available through the npm registry.

Before installing, download and install Node.js. Node.js 18 or higher is required.

If this is a brand new project, make sure to create a package.json first with the npm init command.

Installation is done using the npm install command:

npm install express

Follow our installing guide for more information.

Features

  • Robust routing
  • Focus on high performance
  • Super-high test coverage
  • HTTP helpers (redirection, caching, etc)
  • View system supporting 14+ template engines
  • Content negotiation
  • Executable for generating applications quickly

Docs & Community

PROTIP Be sure to read the migration guide to v5

Quick Start

The quickest way to get started with express is to utilize the executable express(1) to generate an application as shown below:

Install the executable. The executable's major version will match Express's:

npm install -g express-generator@4

Create the app:

express /tmp/foo && cd /tmp/foo

Install dependencies:

npm install

Start the server:

npm start

View the website at: http://localhost:3000

Philosophy

The Express philosophy is to provide small, robust tooling for HTTP servers, making it a great solution for single page applications, websites, hybrids, or public HTTP APIs.

Express does not force you to use any specific ORM or template engine. With support for over 14 template engines via @ladjs/consolidate, you can quickly craft your perfect framework.

Examples

To view the examples, clone the Express repository:

git clone https://github.com/expressjs/express.git --depth 1 && cd express

Then install the dependencies:

npm install

Then run whichever example you want:

node examples/content-negotiation

Contributing

The Express.js project welcomes all constructive contributions. Contributions take many forms, from code for bug fixes and enhancements, to additions and fixes to documentation, additional tests, triaging incoming pull requests and issues, and more!

See the Contributing Guide for more technical details on contributing.

Security Issues

If you discover a security vulnerability in Express, please see Security Policies and Procedures.

Running Tests

To run the test suite, first install the dependencies:

npm install

Then run npm test:

npm test

Current project team members

For information about the governance of the express.js project, see GOVERNANCE.md.

The original author of Express is TJ Holowaychuk

List of all contributors

TC (Technical Committee)

TC emeriti members

TC emeriti members

Triagers

Triagers emeriti members

Emeritus Triagers

License

MIT