express、hapi、koa、sails は、Node.js 環境で Web サーバーや API を構築するための代表的なフレームワークです。express は最小限の設計で広く使われており、koa は非同期処理に強く、hapi は設定重視のエンタープライズ向け、sails は MVC 構造とリアルタイム機能を備えたフルスタックフレームワークです。それぞれ設計思想が大きく異なるため、プロジェクトの規模や要件に合わせて選ぶ必要があります。
これら 4 つのフレームワークは、Node.js でサーバーサイドアプリケーションを作るための道具ですが、作り方や考え方が大きく異なります。express と koa はコードで制御するタイプ、hapi は設定で制御するタイプ、sails はすべて込みのフルスタックタイプです。実際の開発現場でどう違うのか、主要な機能ごとに比較します。
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 して、前後の処理を挟み込めます。req と res が分かれておらず、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'
express はコード内でパスと関数を紐付けます。
app.get や app.post で直感的に書けます。// express: コードでルーティング
app.get('/users/:id', (req, res) => {
const id = req.params.id;
res.send(`User ${id}`);
});
koa はルーティング機能自体がないため、ライブラリを追加します。
@koa/router などが一般的です。// 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 とコントローラーを紐付けます。// sails: 設定ファイル (config/routes.js)
module.exports.routes = {
'get /users/:id': 'UserController.findOne'
};
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() でレスポンスを制御します。// 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);
}
}
};
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 でエラー形式を定義できます。// sails: config/responses.js
module.exports.responses = {
serverError: function (err) {
// 統一エラー処理
return this.res.status(500).json({ error: err });
}
};
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 は全部入りです。
// sails: 自動機能
// models/User.js を作るだけで DB テーブルが生成される
// sockets 設定でリアルタイム通信が可能
これらはすべて Node.js で動作し、HTTP リクエストを処理するという点では同じです。
// すべて JS/TS で実装可能
// const app = express(); (TS なら型推効く)
// express
app.use(compression());
// koa
app.use(compress());
// hapi
await server.register(require('hapi-compression'));
// sails
config.http.middleware order 設定
// すべて 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 — 手軽にフルスタックアプリを作りたい時に使います。ルールに従えるなら、開発速度は最も速くなる可能性があります。
プロジェクトが小さい場合や、カスタマイズを重視する場合は express か koa が無難です。大規模で統一されたルールが必要な場合は hapi、とにかく早く形にしたい場合は sails を検討してください。重要なのは、チームの習熟度と、将来のメンテナンス性を考慮することです。
標準的な API サーバーやマイクロサービス構築に最適です。ミドルウェアの生態系が非常に豊富で、情報も多いため、迷ったときの第一選択になります。学習コストが低く、既存のライブラリとの連携もスムーズです。
非同期処理(async/await)を自然に扱いたい場合に適しています。Express の開発チームが作成しており、軽量で柔軟です。ミドルウェアを自作する際や、最新の JavaScript 機能を積極的に使いたいプロジェクトで選ばれます。
設定ファイルで動作を制御したい大規模なシステムに向いています。入力検証やセキュリティ機能が最初から強く備わっており、堅牢な API 構築に適しています。ただし、hapi ではなく @hapi/hapi を使用するのが現在の標準です。
データベース連携や WebSocket 機能を素早く実装したい場合に有効です。MVC パターンに従っており、フロントエンド開発者がバックエンドも担当する際の生産性が高いです。ただし、フレームワークの仕組みに深く依存するため、カスタマイズには注意が必要です。
Fast, unopinionated, minimalist web framework for Node.js.
This project has a Code of Conduct.
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')
})
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.
PROTIP Be sure to read the migration guide to v5
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
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.
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
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.
If you discover a security vulnerability in Express, please see Security Policies and Procedures.
To run the test suite, first install the dependencies:
npm install
Then run npm test:
npm test
For information about the governance of the express.js project, see GOVERNANCE.md.
The original author of Express is TJ Holowaychuk